bme280.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. // ***************************************************************************
  2. // BMP280 module for ESP8266 with nodeMCU
  3. //
  4. // Written by Lukas Voborsky, @voborsky
  5. //
  6. // MIT license, http://opensource.org/licenses/MIT
  7. // ***************************************************************************
  8. //#define NODE_DEBUG
  9. #include "module.h"
  10. #include "lauxlib.h"
  11. #include "platform.h"
  12. #include "c_math.h"
  13. /****************************************************/
  14. /**\name registers definition */
  15. /***************************************************/
  16. #define BME280_REGISTER_CONTROL (0xF4)
  17. #define BME280_REGISTER_CONTROL_HUM (0xF2)
  18. #define BME280_REGISTER_CONFIG (0xF5)
  19. #define BME280_REGISTER_CHIPID (0xD0)
  20. #define BME280_REGISTER_VERSION (0xD1)
  21. #define BME280_REGISTER_SOFTRESET (0xE0)
  22. #define BME280_REGISTER_CAL26 (0xE1)
  23. #define BME280_REGISTER_TEMP (0xFA)
  24. #define BME280_REGISTER_PRESS (0xF7)
  25. #define BME280_REGISTER_HUM (0xFD)
  26. #define BME280_REGISTER_DIG_T (0x88)
  27. #define BME280_REGISTER_DIG_P (0x8E)
  28. #define BME280_REGISTER_DIG_H1 (0xA1)
  29. #define BME280_REGISTER_DIG_H2 (0xE1)
  30. /****************************************************/
  31. /**\name I2C ADDRESS DEFINITIONS */
  32. /***************************************************/
  33. #define BME280_I2C_ADDRESS1 (0x76)
  34. #define BME280_I2C_ADDRESS2 (0x77)
  35. /****************************************************/
  36. /**\name POWER MODE DEFINITIONS */
  37. /***************************************************/
  38. /* Sensor Specific constants */
  39. #define BME280_SLEEP_MODE (0x00)
  40. #define BME280_FORCED_MODE (0x01)
  41. #define BME280_NORMAL_MODE (0x03)
  42. #define BME280_SOFT_RESET_CODE (0xB6)
  43. /****************************************************/
  44. /**\name OVER SAMPLING DEFINITIONS */
  45. /***************************************************/
  46. #define BME280_OVERSAMP_1X (0x01)
  47. #define BME280_OVERSAMP_2X (0x02)
  48. #define BME280_OVERSAMP_4X (0x03)
  49. #define BME280_OVERSAMP_8X (0x04)
  50. #define BME280_OVERSAMP_16X (0x05)
  51. /****************************************************/
  52. /**\name STANDBY DEFINITIONS */
  53. /***************************************************/
  54. #define BME280_STANDBY_TIME_1_MS (0x00)
  55. #define BME280_STANDBY_TIME_63_MS (0x01)
  56. #define BME280_STANDBY_TIME_125_MS (0x02)
  57. #define BME280_STANDBY_TIME_250_MS (0x03)
  58. #define BME280_STANDBY_TIME_500_MS (0x04)
  59. #define BME280_STANDBY_TIME_1000_MS (0x05)
  60. #define BME280_STANDBY_TIME_10_MS (0x06)
  61. #define BME280_STANDBY_TIME_20_MS (0x07)
  62. /****************************************************/
  63. /**\name FILTER DEFINITIONS */
  64. /***************************************************/
  65. #define BME280_FILTER_COEFF_OFF (0x00)
  66. #define BME280_FILTER_COEFF_2 (0x01)
  67. #define BME280_FILTER_COEFF_4 (0x02)
  68. #define BME280_FILTER_COEFF_8 (0x03)
  69. #define BME280_FILTER_COEFF_16 (0x04)
  70. /****************************************************/
  71. /**\data type definition */
  72. /***************************************************/
  73. #define BME280_S32_t int32_t
  74. #define BME280_U32_t uint32_t
  75. #define BME280_S64_t int64_t
  76. #define BME280_SAMPLING_DELAY 113 //maximum measurement time in ms for maximum oversampling for all measures = 1.25 + 2.3*16 + 2.3*16 + 0.575 + 2.3*16 + 0.575 ms
  77. #define r16s(reg) ((int16_t)r16u(reg))
  78. #define r16sLE(reg) ((int16_t)r16uLE(reg))
  79. #define bme280_adc_T(void) r24u(BME280_REGISTER_TEMP)
  80. #define bme280_adc_P(void) r24u(BME280_REGISTER_PRESS)
  81. #define bme280_adc_H(void) r16u(BME280_REGISTER_HUM)
  82. static const uint32_t bme280_i2c_id = 0;
  83. static uint8_t bme280_i2c_addr = BME280_I2C_ADDRESS1;
  84. static uint8_t bme280_isbme = 0; // 1 if the chip is BME280, 0 for BMP280
  85. static uint8_t bme280_mode = 0; // stores oversampling settings
  86. static uint8_t bme280_ossh = 0; // stores humidity oversampling settings
  87. os_timer_t bme280_timer; // timer for forced mode readout
  88. int lua_connected_readout_ref; // callback when readout is ready
  89. static struct {
  90. uint16_t dig_T1;
  91. int16_t dig_T2;
  92. int16_t dig_T3;
  93. uint16_t dig_P1;
  94. int16_t dig_P2;
  95. int16_t dig_P3;
  96. int16_t dig_P4;
  97. int16_t dig_P5;
  98. int16_t dig_P6;
  99. int16_t dig_P7;
  100. int16_t dig_P8;
  101. int16_t dig_P9;
  102. uint8_t dig_H1;
  103. int16_t dig_H2;
  104. uint8_t dig_H3;
  105. int16_t dig_H4;
  106. int16_t dig_H5;
  107. int8_t dig_H6;
  108. } bme280_data;
  109. static BME280_S32_t bme280_t_fine;
  110. static uint32_t bme280_h = 0;
  111. static double bme280_hc = 0.0;
  112. static uint8_t r8u(uint8_t reg) {
  113. uint8_t ret;
  114. platform_i2c_send_start(bme280_i2c_id);
  115. platform_i2c_send_address(bme280_i2c_id, bme280_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
  116. platform_i2c_send_byte(bme280_i2c_id, reg);
  117. platform_i2c_send_stop(bme280_i2c_id);
  118. platform_i2c_send_start(bme280_i2c_id);
  119. platform_i2c_send_address(bme280_i2c_id, bme280_i2c_addr, PLATFORM_I2C_DIRECTION_RECEIVER);
  120. ret = platform_i2c_recv_byte(bme280_i2c_id, 0);
  121. platform_i2c_send_stop(bme280_i2c_id);
  122. //NODE_DBG("reg:%x, value:%x \n", reg, ret);
  123. return ret;
  124. }
  125. static uint8_t w8u(uint8_t reg, uint8_t val) {
  126. platform_i2c_send_start(bme280_i2c_id);
  127. platform_i2c_send_address(bme280_i2c_id, bme280_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
  128. platform_i2c_send_byte(bme280_i2c_id, reg);
  129. platform_i2c_send_byte(bme280_i2c_id, val);
  130. platform_i2c_send_stop(bme280_i2c_id);
  131. }
  132. static uint16_t r16u(uint8_t reg) {
  133. uint8_t high = r8u(reg);
  134. uint8_t low = r8u(++reg);
  135. return (high << 8) | low;
  136. }
  137. static uint16_t r16uLE(uint8_t reg) {
  138. uint8_t low = r8u(reg);
  139. uint8_t high = r8u(++reg);
  140. return (high << 8) | low;
  141. }
  142. static uint32_t r24u(uint8_t reg) {
  143. uint8_t high = r8u(reg);
  144. uint8_t mid = r8u(++reg);
  145. uint8_t low = r8u(++reg);
  146. return (uint32_t)(((high << 16) | (mid << 8) | low) >> 4);
  147. }
  148. // Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.
  149. // t_fine carries fine temperature as global value
  150. static BME280_S32_t bme280_compensate_T(BME280_S32_t adc_T) {
  151. BME280_S32_t var1, var2, T;
  152. var1 = ((((adc_T>>3) - ((BME280_S32_t)bme280_data.dig_T1<<1))) * ((BME280_S32_t)bme280_data.dig_T2)) >> 11;
  153. var2 = (((((adc_T>>4) - ((BME280_S32_t)bme280_data.dig_T1)) * ((adc_T>>4) - ((BME280_S32_t)bme280_data.dig_T1))) >> 12) *
  154. ((BME280_S32_t)bme280_data.dig_T3)) >> 14;
  155. bme280_t_fine = var1 + var2;
  156. T = (bme280_t_fine * 5 + 128) >> 8;
  157. return T;
  158. }
  159. // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
  160. // Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
  161. static BME280_U32_t bme280_compensate_P(BME280_S32_t adc_P) {
  162. BME280_S64_t var1, var2, p;
  163. var1 = ((BME280_S64_t)bme280_t_fine) - 128000;
  164. var2 = var1 * var1 * (BME280_S64_t)bme280_data.dig_P6;
  165. var2 = var2 + ((var1*(BME280_S64_t)bme280_data.dig_P5)<<17);
  166. var2 = var2 + (((BME280_S64_t)bme280_data.dig_P4)<<35);
  167. var1 = ((var1 * var1 * (BME280_S64_t)bme280_data.dig_P3)>>8) + ((var1 * (BME280_S64_t)bme280_data.dig_P2)<<12);
  168. var1 = (((((BME280_S64_t)1)<<47)+var1))*((BME280_S64_t)bme280_data.dig_P1)>>33;
  169. if (var1 == 0) {
  170. return 0; // avoid exception caused by division by zero
  171. }
  172. p = 1048576-adc_P;
  173. p = (((p<<31)-var2)*3125)/var1;
  174. var1 = (((BME280_S64_t)bme280_data.dig_P9) * (p>>13) * (p>>13)) >> 25;
  175. var2 = (((BME280_S64_t)bme280_data.dig_P8) * p) >> 19;
  176. p = ((p + var1 + var2) >> 8) + (((BME280_S64_t)bme280_data.dig_P7)<<4);
  177. p = (p * 10) >> 8;
  178. return (BME280_U32_t)p;
  179. }
  180. // Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits).
  181. // Output value of “47445” represents 47445/1024 = 46.333 %RH
  182. static BME280_U32_t bme280_compensate_H(BME280_S32_t adc_H) {
  183. BME280_S32_t v_x1_u32r;
  184. v_x1_u32r = (bme280_t_fine - ((BME280_S32_t)76800));
  185. v_x1_u32r = (((((adc_H << 14) - (((BME280_S32_t)bme280_data.dig_H4) << 20) - (((BME280_S32_t)bme280_data.dig_H5) * v_x1_u32r)) +
  186. ((BME280_S32_t)16384)) >> 15) * (((((((v_x1_u32r * ((BME280_S32_t)bme280_data.dig_H6)) >> 10) * (((v_x1_u32r *
  187. ((BME280_S32_t)bme280_data.dig_H3)) >> 11) + ((BME280_S32_t)32768))) >> 10) + ((BME280_S32_t)2097152)) *
  188. ((BME280_S32_t)bme280_data.dig_H2) + 8192) >> 14));
  189. v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((BME280_S32_t)bme280_data.dig_H1)) >> 4));
  190. v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
  191. v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
  192. v_x1_u32r = v_x1_u32r>>12;
  193. return (BME280_U32_t)((v_x1_u32r * 1000)>>10);
  194. }
  195. static int bme280_lua_init(lua_State* L) {
  196. uint8_t sda;
  197. uint8_t scl;
  198. uint8_t config;
  199. uint8_t ack;
  200. uint8_t const bit3 = 0b111;
  201. uint8_t const bit2 = 0b11;
  202. if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) {
  203. return luaL_error(L, "wrong arg range");
  204. }
  205. sda = luaL_checkinteger(L, 1);
  206. scl = luaL_checkinteger(L, 2);
  207. bme280_mode = (!lua_isnumber(L, 6)?BME280_NORMAL_MODE:(luaL_checkinteger(L, 6)&bit2)) // 6-th parameter: power mode
  208. | ((!lua_isnumber(L, 4)?BME280_OVERSAMP_16X:(luaL_checkinteger(L, 4)&bit3)) << 2) // 4-th parameter: pressure oversampling
  209. | ((!lua_isnumber(L, 3)?BME280_OVERSAMP_16X:(luaL_checkinteger(L, 3)&bit3)) << 5); // 3-rd parameter: temperature oversampling
  210. bme280_ossh = (!lua_isnumber(L, 5))?BME280_OVERSAMP_16X:(luaL_checkinteger(L, 5)&bit3); // 5-th parameter: humidity oversampling
  211. config = ((!lua_isnumber(L, 7)?BME280_STANDBY_TIME_20_MS:(luaL_checkinteger(L, 7)&bit3))<< 4) // 7-th parameter: inactive duration in normal mode
  212. | ((!lua_isnumber(L, 8)?BME280_FILTER_COEFF_16:(luaL_checkinteger(L, 8)&bit3)) << 1); // 8-th parameter: IIR filter
  213. NODE_DBG("mode: %x\nhumidity oss: %x\nconfig: %x\n", bme280_mode, bme280_ossh, config);
  214. platform_i2c_setup(bme280_i2c_id, sda, scl, PLATFORM_I2C_SPEED_SLOW);
  215. bme280_i2c_addr = BME280_I2C_ADDRESS1;
  216. platform_i2c_send_start(bme280_i2c_id);
  217. ack = platform_i2c_send_address(bme280_i2c_id, bme280_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
  218. platform_i2c_send_stop(bme280_i2c_id);
  219. if (!ack) {
  220. NODE_DBG("No ACK on address: %x\n", bme280_i2c_addr);
  221. bme280_i2c_addr = BME280_I2C_ADDRESS2;
  222. platform_i2c_send_start(bme280_i2c_id);
  223. ack = platform_i2c_send_address(bme280_i2c_id, bme280_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
  224. platform_i2c_send_stop(bme280_i2c_id);
  225. if (!ack) {
  226. NODE_DBG("No ACK on address: %x\n", bme280_i2c_addr);
  227. return 0;
  228. }
  229. }
  230. uint8_t chipid = r8u(BME280_REGISTER_CHIPID);
  231. NODE_DBG("chip_id: %x\n", chipid);
  232. bme280_isbme = (chipid == 0x60);
  233. uint8_t reg = BME280_REGISTER_DIG_T;
  234. bme280_data.dig_T1 = r16uLE(reg); reg+=2;
  235. bme280_data.dig_T2 = r16sLE(reg); reg+=2;
  236. bme280_data.dig_T3 = r16sLE(reg);
  237. //NODE_DBG("dig_T: %d\t%d\t%d\n", bme280_data.dig_T1, bme280_data.dig_T2, bme280_data.dig_T3);
  238. reg = BME280_REGISTER_DIG_P;
  239. bme280_data.dig_P1 = r16uLE(reg); reg+=2;
  240. bme280_data.dig_P2 = r16sLE(reg); reg+=2;
  241. bme280_data.dig_P3 = r16sLE(reg); reg+=2;
  242. bme280_data.dig_P4 = r16sLE(reg); reg+=2;
  243. bme280_data.dig_P5 = r16sLE(reg); reg+=2;
  244. bme280_data.dig_P6 = r16sLE(reg); reg+=2;
  245. bme280_data.dig_P7 = r16sLE(reg); reg+=2;
  246. bme280_data.dig_P8 = r16sLE(reg); reg+=2;
  247. bme280_data.dig_P9 = r16sLE(reg);
  248. // NODE_DBG("dig_P: %d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", bme280_data.dig_P1, bme280_data.dig_P2, bme280_data.dig_P3, bme280_data.dig_P4, bme280_data.dig_P5, bme280_data.dig_P6, bme280_data.dig_P7, bme280_data.dig_P8, bme280_data.dig_P9);
  249. w8u(BME280_REGISTER_CONFIG, config);
  250. if (bme280_isbme) {
  251. reg = BME280_REGISTER_DIG_H1;
  252. bme280_data.dig_H1 = r8u(reg);
  253. reg = BME280_REGISTER_DIG_H2;
  254. bme280_data.dig_H2 = r16sLE(reg); reg+=2;
  255. bme280_data.dig_H3 = r8u(reg); reg++;
  256. bme280_data.dig_H4 = ((int16_t)r8u(reg) << 4 | (r8u(reg+1) & 0xF)); reg+=2;
  257. bme280_data.dig_H5 = ((int16_t)r8u(reg+1) << 4 | (r8u(reg) >> 4)); reg+=2;
  258. bme280_data.dig_H6 = (int8_t)r8u(reg);
  259. // NODE_DBG("dig_H: %d\t%d\t%d\t%d\t%d\t%d\n", bme280_data.dig_H1, bme280_data.dig_H2, bme280_data.dig_H3, bme280_data.dig_H4, bme280_data.dig_H5, bme280_data.dig_H6);
  260. w8u(BME280_REGISTER_CONTROL_HUM, bme280_ossh);
  261. lua_pushinteger(L, 2);
  262. } else {
  263. lua_pushinteger(L, 1);
  264. }
  265. w8u(BME280_REGISTER_CONTROL, bme280_mode);
  266. return 1;
  267. }
  268. static void bme280_readoutdone (void *arg)
  269. {
  270. NODE_DBG("timer out\n");
  271. lua_State *L = lua_getstate();
  272. lua_rawgeti (L, LUA_REGISTRYINDEX, lua_connected_readout_ref);
  273. lua_call (L, 0, 0);
  274. luaL_unref (L, LUA_REGISTRYINDEX, lua_connected_readout_ref);
  275. os_timer_disarm (&bme280_timer);
  276. }
  277. static int bme280_lua_startreadout(lua_State* L) {
  278. uint32_t delay;
  279. if (lua_isnumber(L, 1)) {
  280. delay = luaL_checkinteger(L, 1);
  281. if (!delay) {delay = BME280_SAMPLING_DELAY;} // if delay is 0 then set the default delay
  282. }
  283. if (!lua_isnoneornil(L, 2)) {
  284. lua_pushvalue(L, 2);
  285. lua_connected_readout_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  286. } else {
  287. lua_connected_readout_ref = LUA_NOREF;
  288. }
  289. w8u(BME280_REGISTER_CONTROL_HUM, bme280_ossh);
  290. w8u(BME280_REGISTER_CONTROL, (bme280_mode & 0xFC) | BME280_FORCED_MODE);
  291. NODE_DBG("control old: %x, control: %x, delay: %d\n", bme280_mode, (bme280_mode & 0xFC) | BME280_FORCED_MODE, delay);
  292. if (lua_connected_readout_ref != LUA_NOREF) {
  293. NODE_DBG("timer armed\n");
  294. os_timer_disarm (&bme280_timer);
  295. os_timer_setfn (&bme280_timer, (os_timer_func_t *)bme280_readoutdone, L);
  296. os_timer_arm (&bme280_timer, delay, 0); // trigger callback when readout is ready
  297. }
  298. return 0;
  299. }
  300. static int bme280_lua_temp(lua_State* L) {
  301. uint32_t adc_T = bme280_adc_T();
  302. if (adc_T == 0x80000 || adc_T == 0xfffff)
  303. return 0;
  304. lua_pushinteger(L, bme280_compensate_T(adc_T));
  305. lua_pushinteger(L, bme280_t_fine);
  306. return 2;
  307. }
  308. static int bme280_lua_baro(lua_State* L) {
  309. uint32_t adc_T = bme280_adc_T();
  310. uint32_t T = bme280_compensate_T(adc_T);
  311. uint32_t adc_P = bme280_adc_P();
  312. if (adc_T == 0x80000 || adc_T == 0xfffff || adc_P ==0x80000 || adc_P == 0xfffff)
  313. return 0;
  314. lua_pushinteger(L, bme280_compensate_P(adc_P));
  315. lua_pushinteger(L, T);
  316. return 2;
  317. }
  318. static int bme280_lua_humi(lua_State* L) {
  319. if (!bme280_isbme) return 0;
  320. uint32_t adc_T = bme280_adc_T();
  321. uint32_t T = bme280_compensate_T(adc_T);
  322. uint32_t adc_H = bme280_adc_H();
  323. if (adc_T == 0x80000 || adc_T == 0xfffff || adc_H == 0x8000 || adc_H == 0xffff)
  324. return 0;
  325. lua_pushinteger(L, bme280_compensate_H(adc_H));
  326. lua_pushinteger(L, T);
  327. return 2;
  328. }
  329. static int bme280_lua_qfe2qnh(lua_State* L) {
  330. if (!lua_isnumber(L, 2)) {
  331. return luaL_error(L, "wrong arg range");
  332. }
  333. int32_t qfe = luaL_checkinteger(L, 1);
  334. int32_t h = luaL_checkinteger(L, 2);
  335. double hc;
  336. if (bme280_h == h) {
  337. hc = bme280_hc;
  338. } else {
  339. hc = pow((double)(1.0 - 2.25577e-5 * h), (double)(-5.25588));
  340. bme280_hc = hc; bme280_h = h;
  341. }
  342. double qnh = (double)qfe * hc;
  343. lua_pushinteger(L, (int32_t)(qnh + 0.5));
  344. return 1;
  345. }
  346. static int bme280_lua_altitude(lua_State* L) {
  347. if (!lua_isnumber(L, 2)) {
  348. return luaL_error(L, "wrong arg range");
  349. }
  350. int32_t P = luaL_checkinteger(L, 1);
  351. int32_t qnh = luaL_checkinteger(L, 2);
  352. double h = (1.0 - pow((double)P/(double)qnh, 1.0/5.25588)) / 2.25577e-5 * 100.0;
  353. lua_pushinteger(L, (int32_t)(h + (((h<0)?-1:(h>0)) * 0.5)));
  354. return 1;
  355. }
  356. static double ln(double x) {
  357. double y = (x-1)/(x+1);
  358. double y2 = y*y;
  359. double r = 0;
  360. for (int8_t i=33; i>0; i-=2) { //we've got the power
  361. r = 1.0/(double)i + y2 * r;
  362. }
  363. return 2*y*r;
  364. }
  365. static int bme280_lua_dewpoint(lua_State* L) {
  366. const double c243 = 243.5;
  367. const double c17 = 17.67;
  368. if (!lua_isnumber(L, 2)) {
  369. return luaL_error(L, "wrong arg range");
  370. }
  371. double H = luaL_checkinteger(L, 1)/100000.0;
  372. double T = luaL_checkinteger(L, 2)/100.0;
  373. double c = ln(H) + ((c17 * T) / (c243 + T));
  374. double d = (c243 * c)/(c17 - c) * 100.0;
  375. lua_pushinteger(L, (int32_t)(d + (((d<0)?-1:(d>0)) * 0.5)));
  376. return 1;
  377. }
  378. static const LUA_REG_TYPE bme280_map[] = {
  379. { LSTRKEY( "init" ), LFUNCVAL(bme280_lua_init)},
  380. { LSTRKEY( "temp" ), LFUNCVAL(bme280_lua_temp)},
  381. { LSTRKEY( "baro" ), LFUNCVAL(bme280_lua_baro)},
  382. { LSTRKEY( "humi" ), LFUNCVAL(bme280_lua_humi)},
  383. { LSTRKEY( "startreadout" ), LFUNCVAL(bme280_lua_startreadout)},
  384. { LSTRKEY( "qfe2qnh" ), LFUNCVAL(bme280_lua_qfe2qnh)},
  385. { LSTRKEY( "altitude" ), LFUNCVAL(bme280_lua_altitude)},
  386. { LSTRKEY( "dewpoint" ), LFUNCVAL(bme280_lua_dewpoint)},
  387. { LNILKEY, LNILVAL}
  388. };
  389. NODEMCU_MODULE(BME280, "bme280", bme280_map, NULL);