tcs3472.lua 13 KB

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