MatrixMiniR4 1.1.4
Matrix Mini R4 Arduino Library API Documentation
Loading...
Searching...
No Matches
MiniR4TCS34725.cpp
Go to the documentation of this file.
1
5#include <math.h>
6#include <stdlib.h>
7
8#include "MiniR4TCS34725.h"
9
18float powf(const float x, const float y)
19{
20 return (float)(pow((double)x, (double)y));
21}
22
28void Adafruit_TCS34725::write8(uint8_t reg, uint8_t value)
29{
30 uint8_t buffer[2] = {(uint8_t)(TCS34725_COMMAND_BIT | reg), value};
31 i2c_dev->write(buffer, 2);
32}
33
39uint8_t Adafruit_TCS34725::read8(uint8_t reg)
40{
41 uint8_t buffer[1] = {(uint8_t)(TCS34725_COMMAND_BIT | reg)};
42 i2c_dev->write_then_read(buffer, 1, buffer, 1);
43 return buffer[0];
44}
45
51uint16_t Adafruit_TCS34725::read16(uint8_t reg)
52{
53 uint8_t buffer[2] = {(uint8_t)(TCS34725_COMMAND_BIT | reg), 0};
54 i2c_dev->write_then_read(buffer, 1, buffer, 2);
55 return (uint16_t(buffer[1]) << 8) | (uint16_t(buffer[0]) & 0xFF);
56}
57
62{
64 delay(3);
66 /* Set a delay for the integration time.
67 This is only necessary in the case where enabling and then
68 immediately trying to read values back. This is because setting
69 AEN triggers an automatic integration, so if a read RGBC is
70 performed too quickly, the data is not yet valid and all 0's are
71 returned */
72 /* 12/5 = 2.4, add 1 to account for integer truncation */
73 delay((256 - _tcs34725IntegrationTime) * 12 / 5 + 1);
74}
75
80{
81 /* Turn the device off to save power */
82 uint8_t reg = 0;
85}
86
95 uint8_t it, tcs34725Gain_t gain, uint8_t addr, TwoWire* theWire, uint8_t mux_ch)
96{
97 _tcs34725Initialised = false;
98 _tcs34725IntegrationTime = it;
99 _tcs34725Gain = gain;
100 if (i2c_dev) delete i2c_dev;
101 i2c_dev = new MiniR4_I2CDevice(addr, theWire, mux_ch);
102}
103
113{
114 return init();
115}
116
122{
123 if (!i2c_dev->begin()) return false;
124
125 /* Make sure we're actually connected */
126 uint8_t x = read8(TCS34725_ID);
127 if ((x != 0x4d) && (x != 0x44) && (x != 0x10)) {
128 return false;
129 }
130 _tcs34725Initialised = true;
131
132 /* Set default integration time and gain */
133 setIntegrationTime(_tcs34725IntegrationTime);
134 setGain(_tcs34725Gain);
135
136 /* Note: by default, the device is in power down mode on bootup */
137 enable();
138
139 return true;
140}
141
148{
149 if (!_tcs34725Initialised) begin();
150
151 /* Update the timing register */
153
154 /* Update value placeholders */
155 _tcs34725IntegrationTime = it;
156}
157
164{
165 if (!_tcs34725Initialised) begin();
166
167 /* Update the timing register */
169
170 /* Update value placeholders */
171 _tcs34725Gain = gain;
172}
173
185void Adafruit_TCS34725::getRawData(uint16_t* r, uint16_t* g, uint16_t* b, uint16_t* c)
186{
187 if (!_tcs34725Initialised) begin();
188
193
194 /* Set a delay for the integration time */
195 /* 12/5 = 2.4, add 1 to account for integer truncation */
196 delay((256 - _tcs34725IntegrationTime) * 12 / 5 + 1);
197}
198
212void Adafruit_TCS34725::getRawDataOneShot(uint16_t* r, uint16_t* g, uint16_t* b, uint16_t* c)
213{
214 if (!_tcs34725Initialised) begin();
215
216 enable();
217 getRawData(r, g, b, c);
218 disable();
219}
220
230void Adafruit_TCS34725::getRGB(float* r, float* g, float* b)
231{
232 uint16_t red, green, blue, clear;
233 getRawData(&red, &green, &blue, &clear);
234 uint32_t sum = clear;
235
236 // Avoid divide by zero errors ... if clear = 0 return black
237 if (clear == 0) {
238 *r = *g = *b = 0;
239 return;
240 }
241
242 *r = (float)red / sum * 255.0;
243 *g = (float)green / sum * 255.0;
244 *b = (float)blue / sum * 255.0;
245}
246
257uint16_t Adafruit_TCS34725::calculateColorTemperature(uint16_t r, uint16_t g, uint16_t b)
258{
259 float X, Y, Z; /* RGB to XYZ correlation */
260 float xc, yc; /* Chromaticity co-ordinates */
261 float n; /* McCamy's formula */
262 float cct;
263
264 if (r == 0 && g == 0 && b == 0) {
265 return 0;
266 }
267
268 /* 1. Map RGB values to their XYZ counterparts. */
269 /* Based on 6500K fluorescent, 3000K fluorescent */
270 /* and 60W incandescent values for a wide range. */
271 /* Note: Y = Illuminance or lux */
272 X = (-0.14282F * r) + (1.54924F * g) + (-0.95641F * b);
273 Y = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
274 Z = (-0.68202F * r) + (0.77073F * g) + (0.56332F * b);
275
276 /* 2. Calculate the chromaticity co-ordinates */
277 xc = (X) / (X + Y + Z);
278 yc = (Y) / (X + Y + Z);
279
280 /* 3. Use McCamy's formula to determine the CCT */
281 n = (xc - 0.3320F) / (0.1858F - yc);
282
283 /* Calculate the final CCT */
284 cct = (449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F;
285
286 /* Return the results in degrees Kelvin */
287 return (uint16_t)cct;
288}
289
304 uint16_t r, uint16_t g, uint16_t b, uint16_t c)
305{
306 uint16_t r2, b2; /* RGB values minus IR component */
307 uint16_t sat; /* Digital saturation level */
308 uint16_t ir; /* Inferred IR content */
309
310 if (c == 0) {
311 return 0;
312 }
313
314 /* Analog/Digital saturation:
315 *
316 * (a) As light becomes brighter, the clear channel will tend to
317 * saturate first since R+G+B is approximately equal to C.
318 * (b) The TCS34725 accumulates 1024 counts per 2.4ms of integration
319 * time, up to a maximum values of 65535. This means analog
320 * saturation can occur up to an integration time of 153.6ms
321 * (64*2.4ms=153.6ms).
322 * (c) If the integration time is > 153.6ms, digital saturation will
323 * occur before analog saturation. Digital saturation occurs when
324 * the count reaches 65535.
325 */
326 if ((256 - _tcs34725IntegrationTime) > 63) {
327 /* Track digital saturation */
328 sat = 65535;
329 } else {
330 /* Track analog saturation */
331 sat = 1024 * (256 - _tcs34725IntegrationTime);
332 }
333
334 /* Ripple rejection:
335 *
336 * (a) An integration time of 50ms or multiples of 50ms are required to
337 * reject both 50Hz and 60Hz ripple.
338 * (b) If an integration time faster than 50ms is required, you may need
339 * to average a number of samples over a 50ms period to reject ripple
340 * from fluorescent and incandescent light sources.
341 *
342 * Ripple saturation notes:
343 *
344 * (a) If there is ripple in the received signal, the value read from C
345 * will be less than the max, but still have some effects of being
346 * saturated. This means that you can be below the 'sat' value, but
347 * still be saturating. At integration times >150ms this can be
348 * ignored, but <= 150ms you should calculate the 75% saturation
349 * level to avoid this problem.
350 */
351 if ((256 - _tcs34725IntegrationTime) <= 63) {
352 /* Adjust sat to 75% to avoid analog saturation if atime < 153.6ms */
353 sat -= sat / 4;
354 }
355
356 /* Check for saturation and mark the sample as invalid if true */
357 if (c >= sat) {
358 return 0;
359 }
360
361 /* AMS RGB sensors have no IR channel, so the IR content must be */
362 /* calculated indirectly. */
363 ir = (r + g + b > c) ? (r + g + b - c) / 2 : 0;
364
365 /* Remove the IR component from the raw RGB values */
366 r2 = r - ir;
367 b2 = b - ir;
368
369 if (r2 == 0) {
370 return 0;
371 }
372
373 /* A simple method of measuring color temp is to use the ratio of blue */
374 /* to red light, taking IR cancellation into account. */
375 uint16_t cct = (3810 * (uint32_t)b2) /
376 (uint32_t)r2 +
377 1391;
379 return cct;
380}
381
392uint16_t Adafruit_TCS34725::calculateLux(uint16_t r, uint16_t g, uint16_t b)
393{
394 float illuminance;
395
396 /* This only uses RGB ... how can we integrate clear or calculate lux */
397 /* based exclusively on clear since this might be more reliable? */
398 illuminance = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
399
400 return (uint16_t)illuminance;
401}
402
409{
410 uint8_t r = read8(TCS34725_ENABLE);
411 if (i) {
413 } else {
414 r &= ~TCS34725_ENABLE_AIEN;
415 }
417}
418
423{
424 uint8_t buffer[1] = {TCS34725_COMMAND_BIT | 0x66};
425 i2c_dev->write(buffer, 1);
426}
427
435void Adafruit_TCS34725::setIntLimits(uint16_t low, uint16_t high)
436{
437 write8(0x04, low & 0xFF);
438 write8(0x05, low >> 8);
439 write8(0x06, high & 0xFF);
440 write8(0x07, high >> 8);
441}
@ x
@ y
float powf(const float x, const float y)
Implements missing powf function.
Handling TCS34725 Color Sensor support (currently replace by MXColor).
#define TCS34725_CDATAL
tcs34725Gain_t
#define TCS34725_ATIME
#define TCS34725_CONTROL
#define TCS34725_ENABLE_PON
#define TCS34725_ENABLE
#define TCS34725_ENABLE_AEN
#define TCS34725_RDATAL
#define TCS34725_GDATAL
#define TCS34725_BDATAL
#define TCS34725_COMMAND_BIT
#define TCS34725_ID
#define TCS34725_ENABLE_AIEN
void getRGB(float *r, float *g, float *b)
Read the RGB color detected by the sensor.
boolean init()
Part of begin.
uint16_t calculateLux(uint16_t r, uint16_t g, uint16_t b)
Converts the raw R/G/B values to lux.
Adafruit_TCS34725(uint8_t=TCS34725_INTEGRATIONTIME_2_4MS, tcs34725Gain_t=TCS34725_GAIN_1X, uint8_t addr=TCS34725_ADDRESS, TwoWire *theWire=&Wire, uint8_t mux=-1)
Constructor.
void clearInterrupt()
Clears inerrupt for TCS34725.
void getRawDataOneShot(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c)
Reads the raw red, green, blue and clear channel values in one-shot mode (e.g., wakes from sleep,...
uint8_t read8(uint8_t reg)
Reads an 8 bit value over I2C.
uint16_t calculateColorTemperature_dn40(uint16_t r, uint16_t g, uint16_t b, uint16_t c)
Converts the raw R/G/B values to color temperature in degrees Kelvin using the algorithm described in...
boolean begin()
Initializes I2C and configures the sensor.
uint16_t read16(uint8_t reg)
Reads a 16 bit values over I2C.
void setGain(tcs34725Gain_t gain)
Adjusts the gain on the TCS34725.
void disable()
Disables the device (putting it in lower power sleep mode)
void enable()
Enables the device.
void setIntegrationTime(uint8_t it)
Sets the integration time for the TC34725.
uint16_t calculateColorTemperature(uint16_t r, uint16_t g, uint16_t b)
Converts the raw R/G/B values to color temperature in degrees Kelvin.
void getRawData(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c)
Reads the raw red, green, blue and clear channel values.
void setIntLimits(uint16_t l, uint16_t h)
Sets inerrupt limits.
void setInterrupt(boolean flag)
Sets interrupt for TCS34725.
void write8(uint8_t reg, uint8_t value)
Writes a register and an 8 bit value over I2C.
The class which defines how we will talk to this device over I2C.
bool write(const uint8_t *buffer, size_t len, bool stop=true, const uint8_t *prefix_buffer=nullptr, size_t prefix_len=0)
Write a buffer or two to the I2C device. Cannot be more than maxBufferSize() bytes.
bool write_then_read(const uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len, bool stop=false)
Write some data, then read some data from I2C into another buffer. Cannot be more than maxBufferSize(...
bool begin(bool addr_detect=true)
Initializes and does basic address detection.