tcs3472.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. --[[
  2. @module tcs3472
  3. @summary tcs3472 颜色传感器
  4. @version 1.0
  5. @date 2022.03.14
  6. @author Dozingfiretruck
  7. @usage
  8. --注意:因使用了sys.wait()所有api需要在协程中使用
  9. -- 用法实例
  10. local tcs3472 = require "tcs3472"
  11. i2cid = 0
  12. i2c_speed = i2c.FAST
  13. sys.taskInit(function()
  14. i2c.setup(i2cid,i2c_speed)
  15. tcs3472.init(i2cid)--初始化,传入i2c_id
  16. while 1 do
  17. local rgb_data = tcs3472.get_rgb()
  18. log.info("rgb_data.R:",rgb_data.R)
  19. log.info("rgb_data.G:",rgb_data.G)
  20. log.info("rgb_data.B:",rgb_data.B)
  21. log.info("rgb_data.C:",rgb_data.C)
  22. if rgb_data.R then
  23. local lux_date = tcs3472.get_lux(rgb_data)
  24. log.info("lux_date:",lux_date)
  25. end
  26. sys.wait(1000)
  27. end
  28. end)
  29. ]]
  30. local tcs3472 = {}
  31. local sys = require "sys"
  32. local i2cid
  33. local TCS3472_ADDRESS_ADR = 0x29
  34. ---器件所用地址
  35. local TCS3472_CMD_BIT = 0x80
  36. local TCS3472_CMD_Read_Byte = 0x00
  37. local TCS3472_CMD_Read_Word = 0x20
  38. local TCS3472_CMD_Clear_INT = 0x66 -- RGBC Interrupt flag clear
  39. local TCS3472_ENABLE = 0x00
  40. local TCS3472_ENABLE_AIEN = 0x10 -- RGBC Interrupt Enable
  41. local TCS3472_ENABLE_WEN = 0x08 -- Wait enable - Writing 1 activates the wait timer
  42. local TCS3472_ENABLE_AEN = 0x02 -- RGBC Enable - Writing 1 actives the ADC, 0 disables it
  43. local TCS3472_ENABLE_PON = 0x01 -- Power on - Writing 1 activates the internal oscillator, 0 disables it
  44. local TCS3472_ATIME = 0x01 -- Integration time
  45. local TCS3472_WTIME = 0x03 -- Wait time (if TCS34725_ENABLE_WEN is asserted)
  46. local TCS3472_WTIME_2_4MS = 0xFF -- WLONG0 = 2.4ms WLONG1 = 0.029s
  47. local TCS3472_WTIME_204MS = 0xAB -- WLONG0 = 204ms WLONG1 = 2.45s
  48. local TCS3472_WTIME_614MS = 0x00 -- WLONG0 = 614ms WLONG1 = 7.4s
  49. local TCS3472_AILTL = 0x04 -- Clear channel lower interrupt threshold
  50. local TCS3472_AILTH = 0x05
  51. local TCS3472_AIHTL = 0x06 -- Clear channel upper interrupt threshold
  52. local TCS3472_AIHTH = 0x07
  53. local TCS3472_PERS = 0x0C -- Persistence register - basic SW filtering mechanism for interrupts
  54. local TCS3472_PERS_NONE = 0x00 -- Every RGBC cycle generates an interrupt
  55. local TCS3472_PERS_1_CYCLE = 0x01 -- 1 clean channel value outside threshold range generates an interrupt
  56. local TCS3472_PERS_2_CYCLE = 0x02 -- 2 clean channel values outside threshold range generates an interrupt
  57. local TCS3472_PERS_3_CYCLE = 0x03 -- 3 clean channel values outside threshold range generates an interrupt
  58. local TCS3472_PERS_5_CYCLE = 0x04 -- 5 clean channel values outside threshold range generates an interrupt
  59. local TCS3472_PERS_10_CYCLE = 0x05 -- 10 clean channel values outside threshold range generates an interrupt
  60. local TCS3472_PERS_15_CYCLE = 0x06 -- 15 clean channel values outside threshold range generates an interrupt
  61. local TCS3472_PERS_20_CYCLE = 0x07 -- 20 clean channel values outside threshold range generates an interrupt
  62. local TCS3472_PERS_25_CYCLE = 0x08 -- 25 clean channel values outside threshold range generates an interrupt
  63. local TCS3472_PERS_30_CYCLE = 0x09 -- 30 clean channel values outside threshold range generates an interrupt
  64. local TCS3472_PERS_35_CYCLE = 0x0a -- 35 clean channel values outside threshold range generates an interrupt
  65. local TCS3472_PERS_40_CYCLE = 0x0b -- 40 clean channel values outside threshold range generates an interrupt
  66. local TCS3472_PERS_45_CYCLE = 0x0c -- 45 clean channel values outside threshold range generates an interrupt
  67. local TCS3472_PERS_50_CYCLE = 0x0d -- 50 clean channel values outside threshold range generates an interrupt
  68. local TCS3472_PERS_55_CYCLE = 0x0e -- 55 clean channel values outside threshold range generates an interrupt
  69. local TCS3472_PERS_60_CYCLE = 0x0f -- 60 clean channel values outside threshold range generates an interrupt
  70. local TCS3472_CONFIG = 0x0D
  71. local TCS3472_CONFIG_WLONG = 0x02 -- Choose between short and long (12x) wait times via TCS34725_WTIME
  72. local TCS3472_CONTROL = 0x0F -- Set the gain level for the sensor
  73. local TCS3472_CHIP_ID_CHECK = 0x12 -- 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727
  74. local TCS34721_TCS34725_CHIP_ID = 0x44
  75. local TCS34723_TCS34727_CHIP_ID = 0x4D
  76. local TCS3472_STATUS = 0x13
  77. local TCS3472_STATUS_AINT = 0x10 -- RGBC Clean channel interrupt
  78. local TCS3472_STATUS_AVALID = 0x01 -- Indicates that the RGBC channels have completed an integration cycle
  79. local TCS3472_CDATAL = 0x14 -- Clear channel data
  80. local TCS3472_CDATAH = 0x15
  81. local TCS3472_RDATAL = 0x16 -- Red channel data
  82. local TCS3472_RDATAH = 0x17
  83. local TCS3472_GDATAL = 0x18 -- Green channel data
  84. local TCS3472_GDATAH = 0x19
  85. local TCS3472_BDATAL = 0x1A -- Blue channel data
  86. local TCS3472_BDATAH = 0x1B
  87. -- Offset and Compensated
  88. local TCS3472_R_Coef = 0.136
  89. local TCS3472_G_Coef = 1.000
  90. local TCS3472_B_Coef = -0.444
  91. local TCS3472_GA = 1.0
  92. local TCS3472_DF = 310.0
  93. local TCS3472_CT_Coef = 3810.0
  94. local TCS3472_CT_Offset = 1391.0
  95. -- Integration Time
  96. local TCS3472_INTEGRATIONTIME_2_4MS = 0xFF -- 2.4ms - 1 cycle - Max Count: 1024
  97. local TCS3472_INTEGRATIONTIME_24MS = 0xF6 -- 24ms - 10 cycles - Max Count: 10240
  98. local TCS3472_INTEGRATIONTIME_50MS = 0xEB -- 50ms - 20 cycles - Max Count: 20480
  99. local TCS3472_INTEGRATIONTIME_101MS = 0xD5 -- 101ms - 42 cycles - Max Count: 43008
  100. local TCS3472_INTEGRATIONTIME_154MS = 0xC0 -- 154ms - 64 cycles - Max Count: 65535
  101. local TCS3472_INTEGRATIONTIME_700MS = 0x00 -- 700ms - 256 cycles - Max Count: 65535
  102. --Gain
  103. local TCS3472_GAIN_1X = 0x00 -- No gain
  104. local TCS3472_GAIN_4X = 0x01 -- 4x gain
  105. local TCS3472_GAIN_16X = 0x02 -- 16x gain
  106. local TCS3472_GAIN_60X = 0x03 -- 60x gain
  107. local integrationTime_t,gain_t
  108. --[[
  109. Writes an 8-bit value to the specified register/address
  110. ]]
  111. local function tcs3472_writebyte(add, data)
  112. i2c.send(i2cid, TCS3472_ADDRESS_ADR, {bit.bor(add,TCS3472_CMD_BIT), data})
  113. end
  114. --[[
  115. Read an unsigned byte from the I2C device
  116. ]]
  117. local function tcs3472_readbyte(add)
  118. i2c.send(i2cid, TCS3472_ADDRESS_ADR, bit.bor(add,TCS3472_CMD_BIT))
  119. local revData = i2c.recv(i2cid, TCS3472_ADDRESS_ADR, 1)
  120. return revData:byte()
  121. end
  122. --[[
  123. Read an unsigned word from the I2C device
  124. ]]
  125. local function tcs3472_readword(add)
  126. i2c.send(i2cid, TCS3472_ADDRESS_ADR, bit.bor(add,TCS3472_CMD_BIT))
  127. local _,revData = pack.unpack(i2c.recv(i2cid, TCS3472_ADDRESS_ADR, 2), "<H")
  128. return revData
  129. end
  130. --[[
  131. function: TCS3472 wake up
  132. ]]
  133. local function tcs3472_enable()
  134. tcs3472_writebyte(TCS3472_ENABLE, TCS3472_ENABLE_PON)
  135. -- sys.wait(3)
  136. tcs3472_writebyte(TCS3472_ENABLE, bit.bor(TCS3472_ENABLE_PON,TCS3472_ENABLE_AEN))
  137. sys.wait(3)
  138. end
  139. --[[
  140. function: TCS3472 Sleep
  141. ]]
  142. local function tcs3472_disable()
  143. --Turn the device off to save power
  144. local reg = tcs3472_readbyte(TCS3472_ENABLE)
  145. tcs3472_writebyte(TCS3472_ENABLE, bit.band(reg,bit.bnot(bit.bor(TCS3472_ENABLE_PON,TCS3472_ENABLE_AEN))))
  146. end
  147. --[[
  148. function: TCS3472 Set Integration Time
  149. ]]
  150. local function tcs3472_set_integration_time(time)
  151. --Update the timing register
  152. tcs3472_writebyte(TCS3472_ATIME, time);
  153. integrationTime_t = time;
  154. end
  155. --[[
  156. function: TCS3472 Set gain
  157. ]]
  158. local function tcs3472_set_gain(gain)
  159. tcs3472_writebyte(TCS3472_CONTROL, gain)
  160. gain_t = gain;
  161. end
  162. --[[
  163. function: Interrupt Enable
  164. ]]
  165. local function tcs3472_interrupt_enable()
  166. local data = tcs3472_readbyte(TCS3472_ENABLE);
  167. tcs3472_writebyte(TCS3472_ENABLE, bit.bor(data,TCS3472_ENABLE_AIEN))
  168. end
  169. --[[
  170. function: Interrupt Disable
  171. ]]
  172. local function tcs3472_interrupt_disable()
  173. local data = tcs3472_readbyte(TCS3472_ENABLE);
  174. tcs3472_writebyte(TCS3472_ENABLE, bit.band(data,bit.bnot(TCS3472_ENABLE_AIEN)))
  175. end
  176. --[[
  177. function: Set Interrupt Persistence register, Interrupts need to be maintained
  178. for several cycles
  179. ]]
  180. local function tcs3472_set_interrupt_persistence_reg(tcs3472_per)
  181. if tcs3472_per < 0x10 then
  182. tcs3472_writebyte(TCS3472_PERS, tcs3472_per)
  183. else
  184. tcs3472_writebyte(TCS3472_PERS, TCS3472_PERS_60_CYCLE)
  185. end
  186. end
  187. --[[
  188. function: Set Interrupt Threshold
  189. parameter :
  190. Threshold_H,Threshold_L:
  191. Two 16-bit interrupt threshold registers allow the user to set limits
  192. below and above a desired light level. An interrupt can be generated
  193. when the Clear data (CDATA) is less than the Clear interrupt low
  194. threshold (AILTx) or is greater than the Clear interrupt high
  195. threshold (AIHTx)(Clear is the Clear ADC Channel Data Registers)
  196. ]]
  197. local function tcs3472_set_interrupt_threshold(threshold_h, threshold_l)
  198. tcs3472_writebyte(TCS3472_AILTL, bit.band(threshold_l,0xff))
  199. tcs3472_writebyte(TCS3472_AILTH, bit.rshift(threshold_l, 8))
  200. tcs3472_writebyte(TCS3472_AIHTL, bit.band(threshold_h,0xff))
  201. tcs3472_writebyte(TCS3472_AIHTH, bit.rshift(threshold_h, 8))
  202. end
  203. --[[
  204. function: Clear interrupt flag
  205. ]]
  206. local function tcs3472_Clear_Interrupt_Flag()
  207. tcs3472_writebyte(TCS3472_CMD_Clear_INT, 0x00)
  208. end
  209. --器件ID检测
  210. local function tcs3472_check()
  211. local chip_id = tcs3472_readbyte(TCS3472_CHIP_ID_CHECK)--读器件地址
  212. if chip_id == TCS34721_TCS34725_CHIP_ID then
  213. log.info("Device i2c id is: TCS34721/TCS34725")
  214. elseif chip_id == TCS34723_TCS34727_CHIP_ID then
  215. log.info("Device i2c id is: TCS34723/TCS34727")
  216. else
  217. log.info("i2c", "Can't find TCS3472")
  218. return false
  219. end
  220. return true
  221. end
  222. --[[
  223. tcs3472初始化
  224. @api tcs3472.init(i2c_id)
  225. @number 所在的i2c总线id
  226. @return bool 成功返回true
  227. @usage
  228. tcs3472.init(0)
  229. ]]
  230. function tcs3472.init(i2c_id)
  231. i2cid = i2c_id
  232. sys.wait(20)
  233. if tcs3472_check() then
  234. --- Set the integration time and gain
  235. tcs3472_set_integration_time(TCS3472_INTEGRATIONTIME_2_4MS)
  236. tcs3472_set_gain(TCS3472_GAIN_60X);
  237. --- Set Interrupt
  238. -- tcs3472_set_interrupt_threshold(0xff00, 0x00ff)--Interrupt upper and lower threshold
  239. -- tcs3472_set_interrupt_persistence_reg(TCS3472_PERS_2_CYCLE)
  240. tcs3472_enable()
  241. -- tcs3472_interrupt_enable()
  242. sys.wait(800)
  243. log.info("tsc3472 init_ok")
  244. return true
  245. end
  246. return false
  247. end
  248. --[[
  249. 获取RGB的数据
  250. @api tcs3472.get_rgb()
  251. @return table tcs3472 rgb数据
  252. @usage
  253. local rgb_data = tcs3472.get_rgb()
  254. log.info("rgb_data.R:",rgb_data.R)
  255. log.info("rgb_data.G:",rgb_data.G)
  256. log.info("rgb_data.B:",rgb_data.B)
  257. log.info("rgb_data.C:",rgb_data.C)
  258. ]]
  259. function tcs3472.get_rgb()
  260. local status = TCS3472_STATUS_AVALID;
  261. local rgb_data={R=nil,G=nil,B=nil,C=nil}
  262. status = tcs3472_readbyte(TCS3472_CDATAL)
  263. if status == nil then
  264. log.error("tcs3472","read status error")
  265. return rgb_data
  266. end
  267. if bit.band(status,TCS3472_STATUS_AVALID) then
  268. rgb_data.C = tcs3472_readword(TCS3472_CDATAL)
  269. rgb_data.R = tcs3472_readword(TCS3472_RDATAL)
  270. rgb_data.G = tcs3472_readword(TCS3472_GDATAL)
  271. rgb_data.B = tcs3472_readword(TCS3472_BDATAL)
  272. end
  273. if integrationTime_t== TCS3472_INTEGRATIONTIME_2_4MS then
  274. sys.wait(3)
  275. elseif integrationTime_t== TCS3472_INTEGRATIONTIME_24MS then
  276. sys.wait(24)
  277. elseif integrationTime_t== TCS3472_INTEGRATIONTIME_50MS then
  278. sys.wait(50)
  279. elseif integrationTime_t== TCS3472_INTEGRATIONTIME_101MS then
  280. sys.wait(101)
  281. elseif integrationTime_t== TCS3472_INTEGRATIONTIME_154MS then
  282. sys.wait(154)
  283. elseif integrationTime_t== TCS3472_INTEGRATIONTIME_700MS then
  284. sys.wait(700)
  285. end
  286. return rgb_data
  287. end
  288. --[[
  289. 获取lux的数据
  290. @api tcs3472.get_lux()
  291. @table rgb_data rgb数据
  292. @return number lux数据
  293. @usage
  294. local lux_date = tcs3472.get_lux(rgb_data)
  295. log.info("lux_date:",lux_date)
  296. ]]
  297. function tcs3472.get_lux(rgb)
  298. local lux,cpl,atime_ms
  299. local gain_temp=1
  300. local ir=1
  301. local r_comp,g_comp,b_comp
  302. atime_ms = ((256 - integrationTime_t) * 2.4)
  303. if rgb.R + rgb.G + rgb.B > rgb.C then
  304. ir = (rgb.R + rgb.G + rgb.B - rgb.C) / 2
  305. else
  306. ir = 0
  307. end
  308. r_comp = rgb.R - ir
  309. g_comp = rgb.G - ir
  310. b_comp = rgb.B - ir
  311. if gain_t == TCS3472_GAIN_1X then
  312. gain_temp = 1
  313. elseif gain_t == TCS3472_GAIN_4X then
  314. gain_temp = 4
  315. elseif gain_t == TCS3472_GAIN_16X then
  316. gain_temp = 16
  317. elseif gain_t == TCS3472_GAIN_60X then
  318. gain_temp = 60
  319. end
  320. cpl = (atime_ms * gain_temp) / (TCS3472_GA * TCS3472_DF)
  321. lux = (TCS3472_R_Coef * r_comp + TCS3472_G_Coef * g_comp + TCS3472_B_Coef * b_comp) / cpl
  322. return lux
  323. end
  324. return tcs3472