3333#define LTR381RGB_ALS_THRES_LTV_3 0X26
3434
3535enum {
36- ADC_RES_16BIT = 0x00 ,
37- ADC_RES_17BIT = 0x01 ,
36+ ADC_RES_20BIT = 0x00 ,
37+ ADC_RES_19BIT = 0x01 ,
3838 ADC_RES_18BIT = 0x02 ,
39- ADC_RES_19BIT = 0x03 ,
40- ADC_RES_20BIT = 0x04 ,
39+ ADC_RES_17BIT = 0x03 ,
40+ ADC_RES_16BIT = 0x04 ,
4141};
4242
4343enum {
4646 ADC_MEAS_RATE_100MS = 0x02 ,
4747 ADC_MEAS_RATE_200MS = 0x03 ,
4848 ADC_MEAS_RATE_400MS = 0x04 ,
49+ ADC_MEAS_RATE_500MS = 0x05 ,
50+ ADC_MEAS_RATE_1000MS = 0x06 ,
51+ ADC_MEAS_RATE_2000MS = 0x07 ,
4952};
5053
5154enum {
@@ -71,6 +74,9 @@ int LTR381RGBClass::begin() {
7174
7275 uint8_t res = readRegister (LTR381RGB_PART_ID);
7376 if ((res & 0xF0 ) != 0xC0 ) {
77+ #ifdef DEBUG
78+ dumpReg ();
79+ #endif
7480 return 0 ;
7581 }
7682
@@ -79,12 +85,13 @@ int LTR381RGBClass::begin() {
7985 if ((res & 0x20 ) != 0 ) {
8086 return 0 ;
8187 }
82-
88+ setCalibrations ( 158 , 137 , 155 , 1 , 1 , 0 );
8389 enableALSInterrupt ();
84- setGain (ALS_CS_GAIN_1);
85-
86- setUpperThreshold (10000 );
87- setLowerThreshold (100 );
90+ setGain (ALS_CS_GAIN_18);
91+ setMeasurementRate (ADC_MEAS_RATE_25MS);
92+ setADCResolution (ADC_RES_16BIT);
93+ setUpperThreshold (_upperThreshold);
94+ setLowerThreshold (lowerThreshold);
8895 return 1 ;
8996}
9097
@@ -95,23 +102,59 @@ void LTR381RGBClass::end() {
95102int LTR381RGBClass::readColors (int & r, int & g, int & b) {
96103 enableRGB ();
97104 unsigned long start = millis ();
98- while (!available () && (millis () - start) < _timeout);
105+ while (!available () && (millis () - start) < _timeout) {
106+ delay (50 );
107+ }
108+ disableMeas ();
109+ uint8_t buf[9 ] = {0 };
110+ int res = readRegisters (LTR381RGB_CS_DATA_GREEN, buf, 9 );
111+ if (res != 1 ) {
112+ return 0 ;
113+ }
114+ if (_calibrated) {
115+ int lg = adcToValue ((buf[2 ] << 16 | buf[1 ] << 8 | buf[0 ]));
116+ int lr = adcToValue ((buf[5 ] << 16 | buf[4 ] << 8 | buf[3 ]));
117+ int lb = adcToValue ((buf[8 ] << 16 | buf[7 ] << 8 | buf[6 ]));
118+ r = normAndTrim (lr, _minR, _maxR);
119+ g = normAndTrim (lg, _minG, _maxG);
120+ b = normAndTrim (lb, _minB, _maxB);
121+
122+ } else {
123+ g = adcToValue ((buf[2 ] << 16 | buf[1 ] << 8 | buf[0 ]));
124+ r = adcToValue ((buf[5 ] << 16 | buf[4 ] << 8 | buf[3 ]));
125+ b = adcToValue ((buf[8 ] << 16 | buf[7 ] << 8 | buf[6 ]));
126+ }
127+
128+ return 1 ;
129+ }
130+
131+ int LTR381RGBClass::readRawColors (int & r, int & g, int & b) {
132+ enableRGB ();
133+ unsigned long start = millis ();
134+ while (!available () && (millis () - start) < _timeout) {
135+ delay (50 );
136+ }
137+ disableMeas ();
99138 uint8_t buf[9 ] = {0 };
100139 int res = readRegisters (LTR381RGB_CS_DATA_GREEN, buf, 9 );
101140 if (res != 1 ) {
102141 return 0 ;
103142 }
104- g = buf[2 ] << 16 | buf[1 ] << 8 | buf[0 ];
105- r = buf[5 ] << 16 | buf[4 ] << 8 | buf[3 ];
106- b = buf[8 ] << 16 | buf[7 ] << 8 | buf[6 ];
143+ int resolution = getADCResolution (_adcResolution);
144+ g = resolution & (buf[2 ] << 16 | buf[1 ] << 8 | buf[0 ]);
145+ r = resolution & (buf[5 ] << 16 | buf[4 ] << 8 | buf[3 ]);
146+ b = resolution & (buf[8 ] << 16 | buf[7 ] << 8 | buf[6 ]);
107147
108148 return 1 ;
109149}
110150
111151int LTR381RGBClass::readAmbientLight (int & lux) {
112152 enableALS ();
113153 unsigned long start = millis ();
114- while (!available () && (millis () - start) < _timeout);
154+ while (!available () && (millis () - start) < _timeout) {
155+ delay (50 );
156+ }
157+ disableMeas ();
115158 uint8_t buf[3 ] = {0 };
116159 int res = readRegisters (LTR381RGB_ALS_DATA, buf, 3 );
117160 if (res != 1 ) {
@@ -125,22 +168,31 @@ int LTR381RGBClass::readAmbientLight(int& lux) {
125168int LTR381RGBClass::readLux (int & lux) {
126169 enableALS ();
127170 unsigned long start = millis ();
128- while (!available () && (millis () - start) < _timeout);
171+ while (!available () && (millis () - start) < _timeout) {
172+ delay (50 );
173+ }
174+ disableMeas ();
129175 uint8_t buf[6 ] = {0 };
130176 int res = readRegisters (LTR381RGB_CS_DATA_IR, buf, 6 );
131177 if (res != 1 ) {
132178 return 0 ;
133179 }
180+ int gain = getLuxGain (_gain);
181+ float intTime = getLuxIntTime (_adcResolution);
134182 int ir = buf[2 ] << 16 | buf[1 ] << 8 | buf[0 ];
135183 int csg = buf[5 ] << 16 | buf[4 ] << 8 | buf[3 ];
136- lux = ((0 .8f *csg)/(_gain*_adcResolution))*(1 - (0 .033f *(ir/csg)));
184+ lux = ((0 .8f *csg)/(gain*intTime))*(1 - (0 .033f *(ir/csg)));
185+
137186 return 1 ;
138187}
139188
140189int LTR381RGBClass::readIR (int & ir) {
141190 enableALS ();
142191 unsigned long start = millis ();
143- while (!available () && (millis () - start) < _timeout);
192+ while (!available () && (millis () - start) < _timeout) {
193+ delay (50 );
194+ }
195+ disableMeas ();
144196 uint8_t buf[3 ] = {0 };
145197 int res = readRegisters (LTR381RGB_CS_DATA_IR, buf, 3 );
146198 if (res != 1 ) {
@@ -152,19 +204,31 @@ int LTR381RGBClass::readIR(int& ir) {
152204}
153205
154206void LTR381RGBClass::setGain (int gain) {
207+ if (gain > 0x04 ) {
208+ gain = 0x04 ;
209+ }
210+ _gain = gain;
155211 writeRegister (LTR381RGB_ALS_CS_GAIN, (0x07 & gain));
156- _gain = getLuxGain (gain);
157212}
158213
159214void LTR381RGBClass::setADCResolution (int resolution) {
215+ if (resolution > 0x04 ) {
216+ resolution = 0x04 ;
217+ }
160218 uint8_t res = readRegister (LTR381RGB_ALS_CS_MEAS_RATE);
161- writeRegister (LTR381RGB_ALS_CS_MEAS_RATE, ((res & 0xF8 ) | resolution));
162- _adcResolution = getLuxResolution (resolution);
219+ writeRegister (LTR381RGB_ALS_CS_MEAS_RATE, ((res & 0x8F ) | (resolution << 4 )));
220+ _adcResolution = resolution;
221+ setTimeout (getADCResTime (resolution) + getADCRate (_rate));
163222}
164223
165224void LTR381RGBClass::setMeasurementRate (int rate) {
225+ if (rate > 0x08 ) {
226+ rate = 0x08 ;
227+ }
228+ _rate = rate;
166229 uint8_t res = readRegister (LTR381RGB_ALS_CS_MEAS_RATE);
167- writeRegister (LTR381RGB_ALS_CS_MEAS_RATE, ((res & 0x8F ) | (rate << 4 )));
230+ writeRegister (LTR381RGB_ALS_CS_MEAS_RATE, ((res & 0xF8 ) | rate));
231+ setTimeout (getADCResTime (_adcResolution) + getADCRate (rate));
168232}
169233
170234void LTR381RGBClass::setUpperThreshold (int utv) {
@@ -175,6 +239,7 @@ void LTR381RGBClass::setUpperThreshold(int utv) {
175239 writeRegister (LTR381RGB_ALS_THRES_UTV_1, utv0);
176240 writeRegister (LTR381RGB_ALS_THRES_UTV_2, utv1);
177241 writeRegister (LTR381RGB_ALS_THRES_UTV_3, 0x0F & utv2);
242+ _upperThreshold = utv;
178243}
179244
180245void LTR381RGBClass::setLowerThreshold (int ltv) {
@@ -185,15 +250,62 @@ void LTR381RGBClass::setLowerThreshold(int ltv) {
185250 writeRegister (LTR381RGB_ALS_THRES_LTV_1, ltv0);
186251 writeRegister (LTR381RGB_ALS_THRES_LTV_2, ltv1);
187252 writeRegister (LTR381RGB_ALS_THRES_LTV_3, 0x0F & ltv2);
253+ _lowerThreshold = ltv;
188254}
189255
190256void LTR381RGBClass::setTimeout (unsigned long timeout) {
191- _timeout = timeout;
257+ if (timeout > 200 ) {
258+ _timeout = timeout;
259+ } else {
260+ _timeout = 200 ;
261+ }
262+ }
263+
264+ int LTR381RGBClass::getADCResTime (int resolution) {
265+ switch (resolution) {
266+ case ADC_RES_16BIT:
267+ return 25 ;
268+ case ADC_RES_17BIT:
269+ return 50 ;
270+ case ADC_RES_18BIT:
271+ return 100 ;
272+ case ADC_RES_19BIT:
273+ return 200 ;
274+ case ADC_RES_20BIT:
275+ return 400 ;
276+ default :
277+ return 100 ;
278+ }
279+ }
280+
281+ int LTR381RGBClass::getADCRate (int rate) {
282+ switch (rate) {
283+ case ADC_MEAS_RATE_25MS:
284+ return 25 ;
285+ case ADC_MEAS_RATE_50MS:
286+ return 50 ;
287+ case ADC_MEAS_RATE_100MS:
288+ return 100 ;
289+ case ADC_MEAS_RATE_200MS:
290+ return 200 ;
291+ case ADC_MEAS_RATE_400MS:
292+ return 400 ;
293+ case ADC_MEAS_RATE_500MS:
294+ return 500 ;
295+ case ADC_MEAS_RATE_1000MS:
296+ return 1000 ;
297+ case ADC_MEAS_RATE_2000MS:
298+ return 2000 ;
299+ case ADC_MEAS_RATE_2000MS + 1 :
300+ return 2000 ;
301+ default :
302+ return 100 ;
303+ }
192304}
193305
194306void LTR381RGBClass::enableALSInterrupt () {
195307 uint8_t res = readRegister (LTR381RGB_INT_CFG);
196- writeRegister (LTR381RGB_INT_CFG, res | 0x03 );
308+ writeRegister (LTR381RGB_INT_CFG, res | 0x04 );
197309}
198310
199311void LTR381RGBClass::disableALSInterrupt () {
@@ -206,6 +318,37 @@ void LTR381RGBClass::resetSW() {
206318 writeRegister (LTR381RGB_MAIN_CTRL, res | 0x80 );
207319}
208320
321+ void LTR381RGBClass::setCalibrations (int rmax, int gmax, int bmax, int rmin, int gmin, int bmin) {
322+ _maxR = rmax;
323+ _maxG = gmax;
324+ _maxB = bmax;
325+ _minR = rmin;
326+ _minG = gmin;
327+ _minB = bmin;
328+ _calibrated = true ;
329+ }
330+
331+ void LTR381RGBClass::dumpReg () {
332+ for (int i = 0x00 ; i < 0x27 ; i++) {
333+ if (i == 0x01 || i == 0x02 || i ==0x03 || i == 0x08 || i == 0x09
334+ || i == 016 || i == 0x17 || i == 0x18 || i == 0x1B || i == 0x1C
335+ || i == 0x1D || i == 0x1E || i == 0x1F || i == 0x20 ) {
336+ Serial.print (" ADDRESS 0x" );
337+ Serial.print (i, HEX);
338+ Serial.println (" IS RESERVED" );
339+ continue ;
340+ }
341+
342+ int res = readRegister (i);
343+ Serial.print (" REGISTER ADDRESS 0x" );
344+ Serial.print (i, HEX);
345+ Serial.print (" VALUE= 0x" );
346+ Serial.print (res, HEX);
347+ Serial.print (" :" );
348+ Serial.println (res, BIN);
349+ }
350+ }
351+
209352int LTR381RGBClass::getLuxGain (int gain) {
210353 switch (gain) {
211354 case ALS_CS_GAIN_1:
@@ -218,11 +361,29 @@ int LTR381RGBClass::getLuxGain(int gain) {
218361 return 9 ;
219362 case ALS_CS_GAIN_18:
220363 return 18 ;
364+ default :
365+ return 6 ;
366+ }
367+ }
368+
369+ int LTR381RGBClass::getADCResolution (int resolution) {
370+ switch (resolution) {
371+ case ADC_RES_16BIT:
372+ return 65534 ;
373+ case ADC_RES_17BIT:
374+ return 131071 ;
375+ case ADC_RES_18BIT:
376+ return 262143 ;
377+ case ADC_RES_19BIT:
378+ return 524287 ;
379+ case ADC_RES_20BIT:
380+ return 1048575 ;
381+ default :
382+ return 262143 ;
221383 }
222- return _gain;
223384}
224385
225- float LTR381RGBClass::getLuxResolution (int resolution) {
386+ float LTR381RGBClass::getLuxIntTime (int resolution) {
226387 switch (resolution) {
227388 case ADC_RES_16BIT:
228389 return 0.25 ;
@@ -234,12 +395,25 @@ float LTR381RGBClass::getLuxResolution(int resolution) {
234395 return 2 .0f ;
235396 case ADC_RES_20BIT:
236397 return 4 .0f ;
398+ default :
399+ return 1 .0f ;
237400 }
238- return _adcResolution;
239401}
240402
241403int LTR381RGBClass::available () {
242404 auto res = readRegister (LTR381RGB_MAIN_STATUS);
405+ if ((res & 0x20 ) == 0x20 ) {
406+ Serial.println (" Power-On event happens" );
407+ resetSW ();
408+ #ifdef DEBUG
409+ dumpReg ();
410+ #endif
411+ // clear the reading after the reset
412+ res = readRegister (LTR381RGB_MAIN_STATUS);
413+ setADCResolution (_adcResolution);
414+ setGain (_gain);
415+ return 0 ;
416+ }
243417 if ((res & 0x08 ) == 0x08 ) {
244418 return 1 ;
245419 }
@@ -254,6 +428,28 @@ void LTR381RGBClass::enableALS() {
254428 writeRegister (LTR381RGB_MAIN_CTRL, 0x02 );
255429}
256430
431+ void LTR381RGBClass::disableMeas () {
432+ writeRegister (LTR381RGB_MAIN_CTRL, 0x00 );
433+ }
434+
435+ int LTR381RGBClass::normAndTrim (int color, int min, int max) {
436+ color = (color - min)*255 /(max - min);
437+ if (color < 0 ) {
438+ color = 0 ;
439+ }
440+ if (color > 255 ) {
441+ color = 255 ;
442+ }
443+ return color;
444+
445+ }
446+
447+ int LTR381RGBClass::adcToValue (int adc) {
448+ int resolution = getADCResolution (_adcResolution);
449+ return ((resolution & adc)*255 /(resolution));;
450+ }
451+
452+
257453int LTR381RGBClass::readRegister (uint8_t address) {
258454 uint8_t value;
259455 if (readRegisters (address, &value, sizeof (value)) != 1 ) {
0 commit comments