TCS34725(5746).c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. #include "TCS34725.h"
  2. typedef enum
  3. {
  4. TCS34725_INTEGRATIONTIME_2_4MS = 0xFF, /**< 2.4ms - 1 cycle - Max Count: 1024 */
  5. TCS34725_INTEGRATIONTIME_24MS = 0xF6, /**< 24ms - 10 cycles - Max Count: 10240 */
  6. TCS34725_INTEGRATIONTIME_50MS = 0xEB, /**< 50ms - 20 cycles - Max Count: 20480 */
  7. TCS34725_INTEGRATIONTIME_101MS = 0xD5, /**< 101ms - 42 cycles - Max Count: 43008 */
  8. TCS34725_INTEGRATIONTIME_154MS = 0xC0, /**< 154ms - 64 cycles - Max Count: 65535 */
  9. TCS34725_INTEGRATIONTIME_700MS = 0x00 /**< 700ms - 256 cycles - Max Count: 65535 */
  10. }
  11. tcs34725IntegrationTime_t;
  12. typedef enum
  13. {
  14. TCS34725_GAIN_1X = 0x00, /**< No gain */
  15. TCS34725_GAIN_4X = 0x01, /**< 4x gain */
  16. TCS34725_GAIN_16X = 0x02, /**< 16x gain */
  17. TCS34725_GAIN_60X = 0x03 /**< 60x gain */
  18. }
  19. tcs34725Gain_t;
  20. tcs34725IntegrationTime_t _tcs34725IntegrationTime;
  21. tcs34725Gain_t _tcs34725Gain;
  22. uint8_t TCS34725_I2C_Read(uint8_t addr, uint8_t reg)
  23. {
  24. uint8_t TCS34725_I2C[3]={0,};
  25. uint16_t value = 0;
  26. uint8_t data = 0;
  27. data=HAL_I2C_Mem_Read(&hi2c1, addr, reg, 1, TCS34725_I2C, 1, 10);
  28. value = TCS34725_I2C[0];
  29. return value;
  30. }
  31. void TCS34725_I2C_Write(uint8_t addr, uint8_t reg, uint8_t data)
  32. {
  33. uint8_t tmp_afe;
  34. tmp_afe = data;
  35. HAL_I2C_Mem_Write(&hi2c1, addr, reg, 1, &tmp_afe, 1, 10);
  36. }
  37. /**************************************************************************/
  38. /*!
  39. Adjusts the gain on the TCS34725 (adjusts the sensitivity to light)
  40. */
  41. /**************************************************************************/
  42. void TCS34725_getrawdata(void)
  43. {
  44. uint8_t data_ret_R =0;
  45. uint8_t data_ret_G =0;
  46. uint8_t data_ret_B =0;
  47. uint8_t data_ret_C =0;
  48. uint8_t DEV_DATA = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_ID);
  49. uint8_t C_DATA_L = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_CDATAL);
  50. uint8_t C_DATA_H = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_CDATAH);
  51. uint8_t R_DATA_L = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_RDATAL);
  52. uint8_t R_DATA_H = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_RDATAH);
  53. uint8_t G_DATA_L = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_GDATAL);
  54. uint8_t G_DATA_H = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_GDATAH);
  55. uint8_t B_DATA_L = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_BDATAL);
  56. uint8_t B_DATA_H = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_BDATAH);
  57. #if 0
  58. double CLEAR = 0;
  59. double RED = 0;
  60. double GREEN = 0;
  61. double BLUE = 0;
  62. printf("************************************\r\n");
  63. printf("1. DEV ID\t:\t%x\r\n", DEV_DATA);
  64. CLEAR = (C_DATA_H << 8) | C_DATA_L;
  65. data_ret_C = (CLEAR / 65535)*255;
  66. printf("CLEAR : %d\r\n",data_ret_C);
  67. RED = (R_DATA_H << 8) | R_DATA_L;
  68. data_ret_R = (RED / 65535)*255;
  69. printf("RED : %d\r\n",data_ret_R);
  70. GREEN = (G_DATA_H << 8) | G_DATA_L;
  71. data_ret_G = (GREEN / 65535)*255;
  72. printf("GREEN : %d\r\n",data_ret_G);
  73. BLUE = (B_DATA_H << 8) | B_DATA_L;
  74. data_ret_B = (BLUE / 65535)*255;
  75. printf("BLUE : %d\r\n",data_ret_B);
  76. #else
  77. double CLEAR = 0;
  78. double RED = 0;
  79. double GREEN = 0;
  80. double BLUE = 0;
  81. CLEAR = (C_DATA_H << 8) | C_DATA_L;
  82. data_ret_C = (CLEAR / 65535)*255;
  83. RED = (R_DATA_H << 8) | R_DATA_L;
  84. data_ret_R = (RED / 65535)*255;
  85. GREEN = (G_DATA_H << 8) | G_DATA_L;
  86. data_ret_G = (GREEN / 65535)*255;
  87. BLUE = (B_DATA_H << 8) | B_DATA_L;
  88. data_ret_B = (BLUE / 65535)*255;
  89. #if 0
  90. printf("02%04x%05d%04x%05d%04x%05d%04x%05d03\r\n",data_ret_C,data_ret_C,data_ret_R,data_ret_R,data_ret_G,data_ret_G,data_ret_B,data_ret_B);
  91. #else
  92. // printf("%04x,%05d,%04x,%05d,%04x,%05d,%04x,%05d,\r\n",data_ret_C,data_ret_C,data_ret_R,data_ret_R,data_ret_G,data_ret_G,data_ret_B,data_ret_B);
  93. printf("%x %d %d %d %d %d %d %d %d\r\n",DEV_DATA,(uint16_t)CLEAR,data_ret_C,(uint16_t)RED,data_ret_R,(uint16_t)GREEN,data_ret_G,(uint16_t)BLUE,data_ret_B);
  94. #endif
  95. #endif
  96. #if 0
  97. uint16_t CLEAR = 0;
  98. uint16_t RED = 0;
  99. uint16_t GREEN = 0;
  100. uint16_t BLUE = 0;
  101. CLEAR = (C_DATA_H << 8) | C_DATA_L;
  102. RED = (R_DATA_H << 8) | R_DATA_L;
  103. GREEN = (G_DATA_H << 8) | G_DATA_L;
  104. BLUE = (B_DATA_H << 8) | B_DATA_L;
  105. printf("1. DEV ID\t:\t%x\r\n", DEV_DATA);
  106. printf("3. C\t:\tHEX : [%04x]\tDEC : [%05d]\r\n", CLEAR,CLEAR);
  107. printf("4. R\t:\tHEX : [%04x]\tDEC : [%05d]\r\n", RED,RED);
  108. printf("5. G\t:\tHEX : [%04x]\tDEC : [%05d]\r\n", GREEN,GREEN);
  109. printf("6. B\t:\tHEX : [%04x]\tDEC : [%05d]\r\n", BLUE,BLUE);
  110. #else
  111. // printf("02%04x%05d%04x%05d%04x%05d%04x%05d03\r\n",CLEAR,CLEAR,RED,RED,GREEN,GREEN,BLUE,BLUE);
  112. #endif
  113. }
  114. void TCS34725_disable(void){
  115. /* Turn the device off to save power */
  116. uint8_t reg = 0;
  117. reg = TCS34725_I2C_Read(TCS34725_ADDRESS,TCS34725_ENABLE);
  118. TCS34725_I2C_Write(TCS34725_ADDRESS,TCS34725_ENABLE, reg & ~(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN));
  119. }
  120. void TCS34725_enable(void)
  121. {
  122. TCS34725_I2C_Write(TCS34725_ADDRESS, TCS34725_ENABLE, TCS34725_ENABLE_PON);
  123. HAL_Delay(3);
  124. TCS34725_I2C_Write(TCS34725_ADDRESS, TCS34725_ENABLE, TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN);
  125. switch (_tcs34725IntegrationTime)
  126. {
  127. case TCS34725_INTEGRATIONTIME_2_4MS:
  128. HAL_Delay(3);
  129. break;
  130. case TCS34725_INTEGRATIONTIME_24MS:
  131. HAL_Delay(24);
  132. break;
  133. case TCS34725_INTEGRATIONTIME_50MS:
  134. HAL_Delay(50);
  135. break;
  136. case TCS34725_INTEGRATIONTIME_101MS:
  137. HAL_Delay(101);
  138. break;
  139. case TCS34725_INTEGRATIONTIME_154MS:
  140. HAL_Delay(154);
  141. break;
  142. case TCS34725_INTEGRATIONTIME_700MS:
  143. HAL_Delay(700);
  144. break;
  145. }
  146. }
  147. void tcs34725SetIntegrationTime(tcs34725IntegrationTime_t it)
  148. {
  149. TCS34725_I2C_Write(TCS34725_ADDRESS,TCS34725_ATIME, it);
  150. _tcs34725IntegrationTime = it;
  151. }
  152. void getRawDataOneShot (void)
  153. {
  154. // TCS34725_enable();
  155. TCS34725_getrawdata();
  156. // TCS34725_disable();
  157. }
  158. /**************************************************************************/
  159. /*!
  160. @brief Converts the raw R/G/B values to color temperature in degrees
  161. Kelvin
  162. */
  163. /**************************************************************************/
  164. uint16_t calculateColorTemperature(uint16_t r, uint16_t g, uint16_t b)
  165. {
  166. float X, Y, Z; /* RGB to XYZ correlation */
  167. float xc, yc; /* Chromaticity co-ordinates */
  168. float n; /* McCamy's formula */
  169. float cct;
  170. /* 1. Map RGB values to their XYZ counterparts. */
  171. /* Based on 6500K fluorescent, 3000K fluorescent */
  172. /* and 60W incandescent values for a wide range. */
  173. /* Note: Y = Illuminance or lux */
  174. X = (-0.14282F * r) + (1.54924F * g) + (-0.95641F * b);
  175. Y = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
  176. Z = (-0.68202F * r) + (0.77073F * g) + ( 0.56332F * b);
  177. /* 2. Calculate the chromaticity co-ordinates */
  178. xc = (X) / (X + Y + Z);
  179. yc = (Y) / (X + Y + Z);
  180. /* 3. Use McCamy's formula to determine the CCT */
  181. n = (xc - 0.3320F) / (0.1858F - yc);
  182. /* Calculate the final CCT */
  183. cct = (449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F;
  184. /* Return the results in degrees Kelvin */
  185. return (uint16_t)cct;
  186. }
  187. /**************************************************************************/
  188. /*!
  189. @brief Converts the raw R/G/B values to lux
  190. */
  191. /**************************************************************************/
  192. uint16_t calculateLux(uint16_t r, uint16_t g, uint16_t b)
  193. {
  194. float illuminance;
  195. /* This only uses RGB ... how can we integrate clear or calculate lux */
  196. /* based exclusively on clear since this might be more reliable? */
  197. illuminance = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
  198. return (uint16_t)illuminance;
  199. }
  200. /**************************************************************************/
  201. /*!
  202. @brief Sets gain to the specified value
  203. */
  204. /**************************************************************************/
  205. void tcs34725SetGain(tcs34725Gain_t gain)
  206. {
  207. TCS34725_I2C_Write(TCS34725_ADDRESS,TCS34725_CONTROL, gain);
  208. _tcs34725Gain = gain;
  209. }
  210. /**************************************************************************/
  211. /*!
  212. @brief Converts the raw R/G/B values to color temperature in degrees
  213. Kelvin using the algorithm described in DN40 from Taos (now AMS).
  214. */
  215. /**************************************************************************/
  216. uint16_t calculateColorTemperature_dn40(uint16_t r, uint16_t g, uint16_t b, uint16_t c)
  217. {
  218. int rc; /* Error return code */
  219. uint16_t r2, g2, b2; /* RGB values minus IR component */
  220. int gl; /* Results of the initial lux conversion */
  221. uint8_t gain_int; /* Gain multiplier as a normal integer */
  222. uint16_t sat; /* Digital saturation level */
  223. uint16_t ir; /* Inferred IR content */
  224. /* Analog/Digital saturation:
  225. *
  226. * (a) As light becomes brighter, the clear channel will tend to
  227. * saturate first since R+G+B is approximately equal to C.
  228. * (b) The TCS34725 accumulates 1024 counts per 2.4ms of integration
  229. * time, up to a maximum values of 65535. This means analog
  230. * saturation can occur up to an integration time of 153.6ms
  231. * (64*2.4ms=153.6ms).
  232. * (c) If the integration time is > 153.6ms, digital saturation will
  233. * occur before analog saturation. Digital saturation occurs when
  234. * the count reaches 65535.
  235. */
  236. if ((256 - _tcs34725IntegrationTime) > 63) {
  237. /* Track digital saturation */
  238. sat = 65535;
  239. } else {
  240. /* Track analog saturation */
  241. sat = 1024 * (256 - _tcs34725IntegrationTime);
  242. }
  243. /* Ripple rejection:
  244. *
  245. * (a) An integration time of 50ms or multiples of 50ms are required to
  246. * reject both 50Hz and 60Hz ripple.
  247. * (b) If an integration time faster than 50ms is required, you may need
  248. * to average a number of samples over a 50ms period to reject ripple
  249. * from fluorescent and incandescent light sources.
  250. *
  251. * Ripple saturation notes:
  252. *
  253. * (a) If there is ripple in the received signal, the value read from C
  254. * will be less than the max, but still have some effects of being
  255. * saturated. This means that you can be below the 'sat' value, but
  256. * still be saturating. At integration times >150ms this can be
  257. * ignored, but <= 150ms you should calculate the 75% saturation
  258. * level to avoid this problem.
  259. */
  260. if ((256 - _tcs34725IntegrationTime) <= 63) {
  261. /* Adjust sat to 75% to avoid analog saturation if atime < 153.6ms */
  262. sat -= sat/4;
  263. }
  264. /* Check for saturation and mark the sample as invalid if true */
  265. if (c >= sat) {
  266. return 0;
  267. }
  268. /* AMS RGB sensors have no IR channel, so the IR content must be */
  269. /* calculated indirectly. */
  270. ir = (r + g + b > c) ? (r + g + b - c) / 2 : 0;
  271. /* Remove the IR component from the raw RGB values */
  272. r2 = r - ir;
  273. g2 = g - ir;
  274. b2 = b - ir;
  275. /* Convert gain to a usable integer value */
  276. switch(_tcs34725Gain) {
  277. case TCS34725_GAIN_4X: /* GAIN 4X */
  278. gain_int = 4;
  279. break;
  280. case TCS34725_GAIN_16X: /* GAIN 16X */
  281. gain_int = 16;
  282. break;
  283. case TCS34725_GAIN_60X: /* GAIN 60X */
  284. gain_int = 60;
  285. break;
  286. case TCS34725_GAIN_1X: /* GAIN 1X */
  287. default:
  288. gain_int = 1;
  289. break;
  290. }
  291. /* Calculate the counts per lux (CPL), taking into account the optional
  292. * arguments for Glass Attenuation (GA) and Device Factor (DF).
  293. *
  294. * GA = 1/T where T is glass transmissivity, meaning if glass is 50%
  295. * transmissive, the GA is 2 (1/0.5=2), and if the glass attenuates light
  296. * 95% the GA is 20 (1/0.05). A GA of 1.0 assumes perfect transmission.
  297. *
  298. * NOTE: It is recommended to have a CPL > 5 to have a lux accuracy
  299. * < +/- 0.5 lux, where the digitization error can be calculated via:
  300. * 'DER = (+/-2) / CPL'.
  301. */
  302. float cpl = (((256-_tcs34725IntegrationTime)*2.4f) * gain_int) /
  303. (1.0f * 310.0f);
  304. /* Determine lux accuracy (+/- lux) */
  305. float der = 2.0f / cpl;
  306. /* Determine the maximum lux value */
  307. float max_lux = 65535.0 / (cpl * 3);
  308. /* Lux is a function of the IR-compensated RGB channels and the associated
  309. * color coefficients, with G having a particularly heavy influence to
  310. * match the nature of the human eye.
  311. *
  312. * NOTE: The green value should be > 10 to ensure the accuracy of the lux
  313. * conversions. If it is below 10, the gain should be increased, but
  314. * the clear<100 check earlier should cover this edge case.
  315. */
  316. gl = 0.136f * (float)r2 + /** Red coefficient. */
  317. 1.000f * (float)g2 + /** Green coefficient. */
  318. -0.444f * (float)b2; /** Blue coefficient. */
  319. float lux = gl / cpl;
  320. /* A simple method of measuring color temp is to use the ratio of blue */
  321. /* to red light, taking IR cancellation into account. */
  322. uint16_t cct = (3810 * (uint32_t)b2) / /** Color temp coefficient. */
  323. (uint32_t)r2 + 1391; /** Color temp offset. */
  324. return cct;
  325. }
  326. void i2c_status(HAL_StatusTypeDef data){
  327. switch(data){
  328. case HAL_OK :printf("HAL_OK \r\n");break;
  329. case HAL_ERROR :printf("HAL_ERROR \r\n");break;
  330. case HAL_BUSY :printf("HAL_BUSY \r\n");break;
  331. case HAL_TIMEOUT :printf("HAL_TIMEOUT\r\n");break;
  332. }
  333. }
  334. void TCS34725_init(void){
  335. uint8_t DEV_DATA = TCS34725_I2C_Read(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | TCS34725_ID);
  336. // tcs34725SetIntegrationTime(TCS34725_INTEGRATIONTIME_700MS);
  337. // tcs34725SetGain(TCS34725_GAIN_60X);
  338. TCS34725_enable();
  339. if(DEV_DATA == 0x44){
  340. printf("TCS34725_Success\r\n");
  341. }else{
  342. printf("TCS34725_Failed\r\n");
  343. }
  344. }