BME680.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. --- 模块功能:BME680功能测试.
  2. -- @author openLuat
  3. -- @module i2c.testI2c
  4. -- @license MIT
  5. -- @copyright openLuat
  6. -- @release 2021.09.19
  7. module(...,package.seeall)
  8. require"utils"
  9. require "powerKey"
  10. local i2cid = 2
  11. local i2cslaveaddr = 0x76
  12. local cmd,i ={0x1D,0x1f,0x20,0x21,0x22,0x23,0x24,0xEA,0xE9,0x8B,0x8A,0x8C,0x2A,0x2B,0xD0,0x74,0x70,0x71,0x72,0xEE,0xED,0xEB,0xEC,0x02,0x00}
  13. local pressure_data={0x1F,0x20,0x21,0x8F,0x8E,0x91,0x90,0x92,0x95,0x94,0x97,0x96,0x99,0x98,0x9D,0x9C,0x9F,0x9E,0xA0}
  14. local temprature_data={0x22,0x23,0x24,0xEA,0XE9,0X8B,0x8A,0x8C}
  15. local humidity_data={0x25,0x26,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8}
  16. local gas_data={0x2A,0x2B,0x04,0xED,0xEC,0xEB,0xEE,0x02,0x00}
  17. local chip_id={0xD0}
  18. local ctrl_meas=0xB6 --初始化配置值 寄存器地址0x74
  19. local setup_ctrl_meas --初始化配置函数
  20. local i2copen_flag=false --i2c打开标志
  21. temperature=nil --温度值
  22. pressure=nil --压力值
  23. humidity=nil --湿度值
  24. local gasResistence --大气质量电阻值
  25. local iaq --空气质量水平
  26. local CompensateTemperature --计算实际温度数据
  27. local CompensatePressure --计算实际压力
  28. local CompensateHumidity --计算实际湿度数据
  29. --setup ctrl meas
  30. --return i2c open flag
  31. setup_ctrl_meas=function()
  32. sys.taskInit(function()
  33. if i2c.setup(i2cid,100000) ~= 100000 then
  34. print("BME680 init fail")
  35. i2copen_flag=false
  36. return i2copen_flag
  37. end
  38. i2c.send(i2cid,i2cslaveaddr, {0xB6,0xE0}) --执行复位
  39. sys.wait(1000)
  40. i2c.send(i2cid,i2cslaveaddr, {0x74, ctrl_meas})
  41. i2c.send(i2cid,i2cslaveaddr, {0x72,0x05})
  42. i2c.send(i2cid,i2cslaveaddr, {0x75,0x1C})
  43. i2c.send(i2cid,i2cslaveaddr, {0x70,0x08})
  44. i2c.send(i2cid,i2cslaveaddr, {0x71,0x19})
  45. i2c.send(i2cid,i2cslaveaddr, {0x74, ctrl_meas})
  46. sys.wait(20)
  47. end)
  48. i2copen_flag=true
  49. return i2copen_flag
  50. end
  51. local function readdata(table)
  52. if not i2copen_flag then
  53. if i2c.setup(i2cid,100000) ~= 100000 then
  54. print("init fail")
  55. return
  56. end
  57. else
  58. for i=1,#table,1 do
  59. --向从设备i2cslaveaddr发送寄存器地址cmd[i]
  60. i2c.send(i2cid,i2cslaveaddr,table[i])
  61. print("testI2c.init",string.format("%02X",table[i]),string.toHex(i2c.recv(i2cid,i2cslaveaddr,1)))
  62. end
  63. end
  64. end
  65. local function longCb()
  66. -- sys.taskInit(function()
  67. -- if not i2copen_flag then
  68. -- if i2c.setup(i2cid,100000) ~= 100000 then
  69. -- print("init fail")
  70. -- return
  71. -- end
  72. -- else log.debug("BME680","i2c is open") end
  73. -- while true do
  74. -- i2c.send(i2cid,i2cslaveaddr, {0x74, ctrl_meas})
  75. -- sys.wait(10)
  76. -- log.debug("压力","======================================================================")
  77. -- readdata(pressure_data)
  78. -- log.debug("温度","======================================================================")
  79. -- readdata(temprature_data)
  80. -- log.debug("湿度","======================================================================")
  81. -- readdata(humidity_data)
  82. -- log.debug("空气质量","======================================================================")
  83. -- readdata(gas_data)
  84. -- log.debug("芯片ID","======================================================================")
  85. -- readdata(chip_id)
  86. -- sys.wait(5000)
  87. -- end
  88. -- --i2c.close(i2cid)
  89. -- end)
  90. CompensateTemperature()
  91. CompensateHumidity()
  92. CompensatePressure()
  93. end
  94. local function shortCb()
  95. setup_ctrl_meas()
  96. end
  97. powerKey.setup(3000, longCb, shortCb)
  98. --计算实际温度数据
  99. --reurn 实际温度
  100. CompensateTemperature=function ()
  101. sys.taskInit(function()
  102. if not i2copen_flag then
  103. if i2c.setup(i2cid,100000) ~= 100000 then
  104. print("init fail")
  105. return
  106. end
  107. else
  108. i2c.send(i2cid,i2cslaveaddr, {0x74, ctrl_meas})
  109. sys.wait(10)
  110. i2c.send(i2cid,i2cslaveaddr,0xE9)
  111. local dig_t1=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  112. dig_t1=tonumber(string.sub(dig_t1,3,4)..string.sub(dig_t1,1,2),16)
  113. i2c.send(i2cid,i2cslaveaddr,0x8A)
  114. local dig_t2=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  115. dig_t2=tonumber(string.sub(dig_t2,3,4)..string.sub(dig_t2,1,2),16)
  116. i2c.send(i2cid,i2cslaveaddr,0x8C)
  117. local dig_t3=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  118. dig_t3=tonumber(dig_t3,16)
  119. i2c.send(i2cid,i2cslaveaddr,0x22)
  120. local adcCode=string.toHex(i2c.recv(i2cid,i2cslaveaddr,3))
  121. adcCode=tonumber(string.sub(adcCode,1,5),16)
  122. local var2,var1
  123. var1 = (adcCode) / 16384.0 - dig_t1 / 1024.0
  124. var1 = var1 * dig_t2
  125. var2 = ((adcCode) / 131072.0 - dig_t1 / 8192.0)
  126. var2 = (var2 * var2) * dig_t3
  127. temperature = (var1 + var2) / 5120.0
  128. end
  129. log.info("BME680 ",(string.format("实际温度%.2f℃\n",temperature)))
  130. end)
  131. return
  132. end
  133. --计算实际湿度数据
  134. CompensateHumidity=function ()
  135. sys.taskInit(function()
  136. if not i2copen_flag then
  137. if i2c.setup(i2cid,100000) ~= 100000 then
  138. print("init fail")
  139. return
  140. end
  141. else
  142. i2c.send(i2cid,i2cslaveaddr, {0x74, ctrl_meas})
  143. sys.wait(10)
  144. i2c.send(i2cid,i2cslaveaddr,0xE2)
  145. local dig_h1=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  146. dig_h1=tonumber(string.sub(dig_h1,3,4)..string.sub(dig_h1,1,1),16)
  147. i2c.send(i2cid,i2cslaveaddr,0xE1)
  148. local dig_h2=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  149. dig_h2=tonumber(string.sub(dig_h2,1,3),16)
  150. i2c.send(i2cid,i2cslaveaddr,0xE4)
  151. local dig_h3=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  152. dig_h3=tonumber(dig_h3,16)
  153. i2c.send(i2cid,i2cslaveaddr,0xE5)
  154. local dig_h4=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  155. dig_h4=tonumber(dig_h4,16)
  156. i2c.send(i2cid,i2cslaveaddr,0xE6)
  157. local dig_h5=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  158. dig_h5=tonumber(dig_h5,16)
  159. i2c.send(i2cid,i2cslaveaddr,0xE7)
  160. local dig_h6=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  161. dig_h6=tonumber(dig_h6,16)
  162. i2c.send(i2cid,i2cslaveaddr,0xE8)
  163. local dig_h7=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  164. dig_h7=tonumber(dig_h7,16)
  165. i2c.send(i2cid,i2cslaveaddr,0x25)
  166. local adcCode=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  167. adcCode=tonumber(adcCode,16)
  168. --log.debug("测试","dig_h1",dig_h1,"dig_h2",dig_h2,"dig_h3",dig_h3,"dig_h4",dig_h4,"dig_h5",dig_h5,"dig_h6",dig_h6,"dig_h7",dig_h7,"\n","adcCode",adcCode)
  169. local var1,var2,var3,var4,temp
  170. --log.debug("测试",temperature)
  171. if temperature and adcCode and dig_h1 then
  172. temp=temperature
  173. var1=(adcCode)-((dig_h1*16)+((dig_h3/2)*temp))
  174. var2=var1*(((dig_h2/262144)*(1 + ((dig_h4/16384)*temp)+((dig_h5/1048576)*temp*temp))))
  175. var3 =dig_h6 / 16384
  176. var4 =dig_h7 / 2097152
  177. humidity = var2 + ((var3 + (var4 * temp)) * var2 * var2)
  178. log.info("BME680 ",(string.format("实际湿度%.2f℃",humidity)).."%")
  179. else
  180. log.warn("BME680","需先测量当前环境温度进行校准","temperature",temperature,"adcCode",adcCode,"dig_h1",dig_h1)
  181. end
  182. end
  183. end)
  184. return
  185. end
  186. --计算实际压力数据
  187. CompensatePressure=function ()
  188. sys.taskInit(function()
  189. if not i2copen_flag then
  190. if i2c.setup(i2cid,100000) ~= 100000 then
  191. print("init fail")
  192. return
  193. end
  194. else
  195. i2c.send(i2cid,i2cslaveaddr, {0x74, ctrl_meas})
  196. sys.wait(10)
  197. i2c.send(i2cid,i2cslaveaddr,0x8E)
  198. local dig_p1=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  199. dig_p1=tonumber(string.sub(dig_p1,3,4)..string.sub(dig_p1,1,2),16)
  200. i2c.send(i2cid,i2cslaveaddr,0x90)
  201. local dig_p2=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  202. dig_p2=tonumber(string.sub(dig_p2,3,4)..string.sub(dig_p2,1,2),16)
  203. i2c.send(i2cid,i2cslaveaddr,0x92)
  204. local dig_p3=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  205. dig_p3=tonumber(dig_p3,16)
  206. i2c.send(i2cid,i2cslaveaddr,0x94)
  207. local dig_p4=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  208. dig_p4=tonumber(string.sub(dig_p4,3,4)..string.sub(dig_p4,1,2),16)
  209. i2c.send(i2cid,i2cslaveaddr,0x96)
  210. local dig_p5=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  211. dig_p5=tonumber(string.sub(dig_p5,3,4)..string.sub(dig_p5,1,2),16)
  212. i2c.send(i2cid,i2cslaveaddr,0x99)
  213. local dig_p6=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  214. dig_p6=tonumber(dig_p6,16)
  215. i2c.send(i2cid,i2cslaveaddr,0x98)
  216. local dig_p7=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  217. dig_p7=tonumber(dig_p7,16)
  218. i2c.send(i2cid,i2cslaveaddr,0x9C)
  219. local dig_p8=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  220. dig_p8=tonumber(string.sub(dig_p8,3,4)..string.sub(dig_p8,1,2),16)
  221. i2c.send(i2cid,i2cslaveaddr,0x9E)
  222. local dig_p9=string.toHex(i2c.recv(i2cid,i2cslaveaddr,2))
  223. dig_p9=tonumber(string.sub(dig_p9,3,4)..string.sub(dig_p9,1,2),16)
  224. i2c.send(i2cid,i2cslaveaddr,0xA0)
  225. local dig_p10=string.toHex(i2c.recv(i2cid,i2cslaveaddr,1))
  226. dig_p10=tonumber(dig_p10,16)
  227. i2c.send(i2cid,i2cslaveaddr,0x1F)
  228. local adcCode=string.toHex(i2c.recv(i2cid,i2cslaveaddr,3))
  229. adcCode=tonumber(string.sub(adcCode,1,5),16)
  230. --log.debug("测试","dig_p1",dig_p1.."\n","dig_p2",dig_p2.."\n","dig_p3",dig_p3.."\n","dig_p4",dig_p4.."\n","dig_p5",dig_p5.."\n","dig_p6",dig_p6.."\n","dig_p7",dig_p7.."\n","dig_p8",dig_p8.."\n","dig_p9",dig_p9.."\n","dig_p10",dig_p10.."\n","adcCode",adcCode.."\n")
  231. if temperature and adcCode and dig_p1 then
  232. local pressure_min = 30000.0
  233. local pressure_max = 110000.0
  234. local var1,var2,var3,t_fine
  235. t_fine=temperature*5120
  236. var1 = (t_fine / 2.0) - 64000.0
  237. var2 = var1 * var1 * (dig_p6) / 131072.0
  238. var2 = var2 + var1 * (dig_p5) * 2.0
  239. var2 = (var2 / 4.0) + ((dig_p4) * 65536.0)
  240. var1 = (dig_p3) * var1 * var1 / 16384.0
  241. var1 = (var1 + (dig_p2) * var1) / 524288.0
  242. var1 = (1.0 + var1 / 32768.0) * (dig_p1)
  243. pressure = 1048576.0 - adcCode
  244. pressure = ((pressure - (var2 / 4096.0)) * 6250.0 )/ var1
  245. var1 = (dig_p9 * pressure * pressure )/ 2147483648.0
  246. var2 = pressure * (dig_p8) / 32768.0
  247. var3 = ((pressure / 256) * (pressure / 256) * (pressure / 256)* (dig_p10 / 131072))
  248. pressure = pressure + (var1 + var2 +var3+ (dig_p7*128.0)) / 16.0
  249. log.info("BME280 ",(string.format("实际压力%.2f Pa",pressure)))
  250. else
  251. log.warn("BME680","需先测量当前环境温度进行校准")
  252. end
  253. end
  254. end)
  255. end