tweaked detection to use photoresistor through an opamp

Dependents:   rgb_sensor_buffer

Fork of rgb_sensor by Milosch Meriac

Committer:
meriac
Date:
Wed Jun 25 14:55:45 2014 +0000
Revision:
0:576e43bd193d
Child:
2:4545984e62b6
moved rgb_sensor to separate library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
meriac 0:576e43bd193d 1 /* Discrete RGB color sensor
meriac 0:576e43bd193d 2 *
meriac 0:576e43bd193d 3 * - uses single-channel light-dependent resistor (via ADC)
meriac 0:576e43bd193d 4 * and a RGB LED.
meriac 0:576e43bd193d 5 * - compensates background light
meriac 0:576e43bd193d 6 *
meriac 0:576e43bd193d 7 * Copyright (c) 2014 ARM Limited
meriac 0:576e43bd193d 8 *
meriac 0:576e43bd193d 9 * Licensed under the Apache License, Version 2.0 (the "License");
meriac 0:576e43bd193d 10 * you may not use this file except in compliance with the License.
meriac 0:576e43bd193d 11 * You may obtain a copy of the License at
meriac 0:576e43bd193d 12 *
meriac 0:576e43bd193d 13 * http://www.apache.org/licenses/LICENSE-2.0
meriac 0:576e43bd193d 14 *
meriac 0:576e43bd193d 15 * Unless required by applicable law or agreed to in writing, software
meriac 0:576e43bd193d 16 * distributed under the License is distributed on an "AS IS" BASIS,
meriac 0:576e43bd193d 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
meriac 0:576e43bd193d 18 * See the License for the specific language governing permissions and
meriac 0:576e43bd193d 19 * limitations under the License.
meriac 0:576e43bd193d 20 */
meriac 0:576e43bd193d 21
meriac 0:576e43bd193d 22 #include <mbed.h>
meriac 0:576e43bd193d 23 #include <pinmap.h>
meriac 0:576e43bd193d 24 #include "rgb_sensor.h"
meriac 0:576e43bd193d 25
meriac 0:576e43bd193d 26 static const PinMap RGB_Sensor__PinMap_ADC[] = {
meriac 0:576e43bd193d 27 {P0_23, ADC0_0, 1},
meriac 0:576e43bd193d 28 {P0_24, ADC0_1, 1},
meriac 0:576e43bd193d 29 {P0_25, ADC0_2, 1},
meriac 0:576e43bd193d 30 {P0_26, ADC0_3, 1},
meriac 0:576e43bd193d 31 {P1_30, ADC0_4, 3},
meriac 0:576e43bd193d 32 {P1_31, ADC0_5, 3},
meriac 0:576e43bd193d 33 {P0_2, ADC0_7, 2},
meriac 0:576e43bd193d 34 {P0_3, ADC0_6, 2},
meriac 0:576e43bd193d 35 {NC, NC, 0}
meriac 0:576e43bd193d 36 };
meriac 0:576e43bd193d 37
meriac 0:576e43bd193d 38 DigitalOut g_dbg(LED1);
meriac 0:576e43bd193d 39
meriac 0:576e43bd193d 40 /* initialize globally */
meriac 0:576e43bd193d 41 RGB_Sensor* RGB_Sensor::m_global = NULL;
meriac 0:576e43bd193d 42
meriac 0:576e43bd193d 43 RGB_Sensor::RGB_Sensor(PinName red, PinName green, PinName blue, PinName adc)
meriac 0:576e43bd193d 44 :m_red(red), m_green(green), m_blue(blue)
meriac 0:576e43bd193d 45 {
meriac 0:576e43bd193d 46 uint32_t clkdiv;
meriac 0:576e43bd193d 47
meriac 0:576e43bd193d 48 m_done=true;
meriac 0:576e43bd193d 49
meriac 0:576e43bd193d 50 /* allow only one instance */
meriac 0:576e43bd193d 51 if(m_global)
meriac 0:576e43bd193d 52 {
meriac 0:576e43bd193d 53 m_adc_channel = (ADCName)NC;
meriac 0:576e43bd193d 54 return;
meriac 0:576e43bd193d 55 }
meriac 0:576e43bd193d 56
meriac 0:576e43bd193d 57 /* disable LED's */
meriac 0:576e43bd193d 58 m_red = 1;
meriac 0:576e43bd193d 59 m_green = 1;
meriac 0:576e43bd193d 60 m_blue = 1;
meriac 0:576e43bd193d 61
meriac 0:576e43bd193d 62 // enable ADC power
meriac 0:576e43bd193d 63 LPC_SC->PCONP |= (1<<12);
meriac 0:576e43bd193d 64 // set ADC clock to PCLK
meriac 0:576e43bd193d 65 LPC_SC->PCLKSEL0 = (LPC_SC->PCLKSEL0 & ~(0x3UL<<24)) | (0x1UL<<24);
meriac 0:576e43bd193d 66
meriac 0:576e43bd193d 67 // determine mapping
meriac 0:576e43bd193d 68 m_adc_channel = (ADCName)pinmap_peripheral(adc, RGB_Sensor__PinMap_ADC);
meriac 0:576e43bd193d 69 if (m_adc_channel == (ADCName)NC)
meriac 0:576e43bd193d 70 return;
meriac 0:576e43bd193d 71
meriac 0:576e43bd193d 72 // initialize ADC
meriac 0:576e43bd193d 73 clkdiv = ((SystemCoreClock+RGB_MAX_ADC_CLK-1)/RGB_MAX_ADC_CLK)-1;
meriac 0:576e43bd193d 74 LPC_ADC->ADCR = (1UL<<m_adc_channel) | (clkdiv<<8) | (1UL<<21);
meriac 0:576e43bd193d 75
meriac 0:576e43bd193d 76 // set up ADC IRQ
meriac 0:576e43bd193d 77 NVIC_SetVector(ADC_IRQn, (uint32_t)&__adc_irq);
meriac 0:576e43bd193d 78 LPC_ADC->ADINTEN = (1UL<<m_adc_channel);
meriac 0:576e43bd193d 79 NVIC_EnableIRQ(ADC_IRQn);
meriac 0:576e43bd193d 80
meriac 0:576e43bd193d 81 // propagate pin setting
meriac 0:576e43bd193d 82 pinmap_pinout(adc, RGB_Sensor__PinMap_ADC);
meriac 0:576e43bd193d 83
meriac 0:576e43bd193d 84 // remember this instance
meriac 0:576e43bd193d 85 m_global = this;
meriac 0:576e43bd193d 86 }
meriac 0:576e43bd193d 87
meriac 0:576e43bd193d 88 RGB_Sensor::~RGB_Sensor(void)
meriac 0:576e43bd193d 89 {
meriac 0:576e43bd193d 90 /* only deal with fully initialized objects */
meriac 0:576e43bd193d 91 if(m_adc_channel == (ADCName)NC)
meriac 0:576e43bd193d 92 return;
meriac 0:576e43bd193d 93 /* wait for completion */
meriac 0:576e43bd193d 94 wait();
meriac 0:576e43bd193d 95 /* reset global reference */
meriac 0:576e43bd193d 96 m_global = NULL;
meriac 0:576e43bd193d 97 /* turn off ADC */
meriac 0:576e43bd193d 98 LPC_ADC->ADINTEN = 0;
meriac 0:576e43bd193d 99 LPC_ADC->ADCR = 0;
meriac 0:576e43bd193d 100 LPC_SC->PCONP &= ~(1UL<<12);
meriac 0:576e43bd193d 101 }
meriac 0:576e43bd193d 102
meriac 0:576e43bd193d 103 void RGB_Sensor::__adc_irq(void)
meriac 0:576e43bd193d 104 {
meriac 0:576e43bd193d 105 if(m_global)
meriac 0:576e43bd193d 106 m_global->adc_irq();
meriac 0:576e43bd193d 107 }
meriac 0:576e43bd193d 108
meriac 0:576e43bd193d 109 void RGB_Sensor::adc_irq(void)
meriac 0:576e43bd193d 110 {
meriac 0:576e43bd193d 111 uint32_t sample, status;
meriac 0:576e43bd193d 112
meriac 0:576e43bd193d 113 status = LPC_ADC->ADSTAT;
meriac 0:576e43bd193d 114 if(status & (1UL<<m_adc_channel))
meriac 0:576e43bd193d 115 {
meriac 0:576e43bd193d 116 /* always read sample to acknowledge IRQ */
meriac 0:576e43bd193d 117 sample = (((&LPC_ADC->ADDR0)[m_adc_channel])>>4) & 0xFFF;
meriac 0:576e43bd193d 118
meriac 0:576e43bd193d 119 if(!m_done)
meriac 0:576e43bd193d 120 {
meriac 0:576e43bd193d 121 m_adc_aggregation[m_rgb_channel] += sample;
meriac 0:576e43bd193d 122
meriac 0:576e43bd193d 123 m_adc_count++;
meriac 0:576e43bd193d 124 if(m_adc_count>=RGB_OVERSAMPLING)
meriac 0:576e43bd193d 125 {
meriac 0:576e43bd193d 126 m_adc_count=0;
meriac 0:576e43bd193d 127 m_rgb_channel++;
meriac 0:576e43bd193d 128
meriac 0:576e43bd193d 129 /* prepare LEDs for upcoming channel */
meriac 0:576e43bd193d 130 switch(m_rgb_channel)
meriac 0:576e43bd193d 131 {
meriac 0:576e43bd193d 132 case 1:
meriac 0:576e43bd193d 133 m_red = 0;
meriac 0:576e43bd193d 134 break;
meriac 0:576e43bd193d 135
meriac 0:576e43bd193d 136 case 2:
meriac 0:576e43bd193d 137 m_red = 1;
meriac 0:576e43bd193d 138 m_green = 0;
meriac 0:576e43bd193d 139 break;
meriac 0:576e43bd193d 140
meriac 0:576e43bd193d 141 case 3:
meriac 0:576e43bd193d 142 m_green = 1;
meriac 0:576e43bd193d 143 m_blue= 0;
meriac 0:576e43bd193d 144 break;
meriac 0:576e43bd193d 145
meriac 0:576e43bd193d 146 default:
meriac 0:576e43bd193d 147 m_blue= 1;
meriac 0:576e43bd193d 148 m_done = true;
meriac 0:576e43bd193d 149 /* stop data aquisition */
meriac 0:576e43bd193d 150 LPC_ADC->ADCR &= ~(1UL<<16);
meriac 0:576e43bd193d 151 }
meriac 0:576e43bd193d 152 }
meriac 0:576e43bd193d 153 }
meriac 0:576e43bd193d 154 }
meriac 0:576e43bd193d 155 LPC_ADC->ADSTAT = status;
meriac 0:576e43bd193d 156 }
meriac 0:576e43bd193d 157
meriac 0:576e43bd193d 158 bool RGB_Sensor::capture(void)
meriac 0:576e43bd193d 159 {
meriac 0:576e43bd193d 160 /* ignore mis-configurations */
meriac 0:576e43bd193d 161 if(m_adc_channel==(ADCName)NC)
meriac 0:576e43bd193d 162 return false;
meriac 0:576e43bd193d 163
meriac 0:576e43bd193d 164 m_done = false;
meriac 0:576e43bd193d 165 m_adc_count = m_rgb_channel = 0;
meriac 0:576e43bd193d 166 memset((void*)&m_adc_aggregation, 0, sizeof(m_adc_aggregation));
meriac 0:576e43bd193d 167 /* start ADC burst mode */
meriac 0:576e43bd193d 168 LPC_ADC->ADCR |= (1UL<<16);
meriac 0:576e43bd193d 169
meriac 0:576e43bd193d 170 return true;
meriac 0:576e43bd193d 171 }
meriac 0:576e43bd193d 172
meriac 0:576e43bd193d 173 bool RGB_Sensor::wait(void)
meriac 0:576e43bd193d 174 {
meriac 0:576e43bd193d 175 /* ignore mis-configurations */
meriac 0:576e43bd193d 176 if(m_adc_channel==(ADCName)NC)
meriac 0:576e43bd193d 177 return false;
meriac 0:576e43bd193d 178
meriac 0:576e43bd193d 179 while(!m_done)
meriac 0:576e43bd193d 180 __WFE();
meriac 0:576e43bd193d 181
meriac 0:576e43bd193d 182 return true;
meriac 0:576e43bd193d 183 }
meriac 0:576e43bd193d 184
meriac 0:576e43bd193d 185 bool RGB_Sensor::capture(TRGB &rgb)
meriac 0:576e43bd193d 186 {
meriac 0:576e43bd193d 187 if(!(capture() && wait()))
meriac 0:576e43bd193d 188 return false;
meriac 0:576e43bd193d 189
meriac 0:576e43bd193d 190 /* correct "DC" offset by subdstracting
meriac 0:576e43bd193d 191 * environment light
meriac 0:576e43bd193d 192 */
meriac 0:576e43bd193d 193 rgb.ch.red = m_adc_aggregation[1] - m_adc_aggregation[0];
meriac 0:576e43bd193d 194 rgb.ch.green = m_adc_aggregation[2] - m_adc_aggregation[0];
meriac 0:576e43bd193d 195 rgb.ch.blue = m_adc_aggregation[3] - m_adc_aggregation[0];
meriac 0:576e43bd193d 196
meriac 0:576e43bd193d 197 return true;
meriac 0:576e43bd193d 198 }