luat_lib_sensor.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. /*
  2. @module sensor
  3. @summary 传感器操作库
  4. @version 1.0
  5. @date 2020.03.30
  6. */
  7. #include "luat_base.h"
  8. #include "luat_timer.h"
  9. #include "luat_malloc.h"
  10. #include "luat_gpio.h"
  11. #include "luat_zbuff.h"
  12. #define LUAT_LOG_TAG "sensor"
  13. #include "luat_log.h"
  14. #define CONNECT_SUCCESS 0
  15. #define CONNECT_FAILED 1
  16. unsigned int temp;
  17. static void w1_reset(int pin)
  18. {
  19. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  20. luat_gpio_set(pin, Luat_GPIO_LOW);
  21. luat_timer_us_delay(550); /* 480us - 960us */
  22. luat_gpio_set(pin, Luat_GPIO_HIGH);
  23. luat_timer_us_delay(40); /* 15us - 60us*/
  24. }
  25. static uint8_t w1_connect(int pin)
  26. {
  27. uint8_t retry = 0;
  28. luat_gpio_mode(pin, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 0);
  29. while (luat_gpio_get(pin) && retry < 200)
  30. {
  31. retry++;
  32. luat_timer_us_delay(1);
  33. };
  34. if (retry >= 200)
  35. return CONNECT_FAILED;
  36. else
  37. retry = 0;
  38. while (!luat_gpio_get(pin) && retry < 240)
  39. {
  40. retry++;
  41. luat_timer_us_delay(1);
  42. };
  43. if (retry >= 240)
  44. return CONNECT_FAILED;
  45. return CONNECT_SUCCESS;
  46. }
  47. static uint8_t w1_read_bit(int pin)
  48. {
  49. uint8_t data;
  50. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
  51. luat_gpio_set(pin, Luat_GPIO_LOW);
  52. luat_timer_us_delay(2);
  53. luat_gpio_set(pin, Luat_GPIO_HIGH);
  54. luat_gpio_mode(pin, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 0);
  55. luat_timer_us_delay(5);
  56. if (luat_gpio_get(pin))
  57. data = 1;
  58. else
  59. data = 0;
  60. luat_timer_us_delay(50);
  61. return data;
  62. }
  63. static uint8_t w1_read_byte(int pin)
  64. {
  65. uint8_t i, j, dat;
  66. dat = 0;
  67. //rt_base_t level;
  68. //level = rt_hw_interrupt_disable();
  69. for (i = 1; i <= 8; i++)
  70. {
  71. j = w1_read_bit(pin);
  72. dat = (j << 7) | (dat >> 1);
  73. }
  74. //rt_hw_interrupt_enable(level);
  75. return dat;
  76. }
  77. static void w1_write_byte(int pin, uint8_t dat)
  78. {
  79. uint8_t j;
  80. uint8_t testb;
  81. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  82. for (j = 1; j <= 8; j++)
  83. {
  84. testb = dat & 0x01;
  85. dat = dat >> 1;
  86. if (testb)
  87. {
  88. luat_gpio_set(pin, Luat_GPIO_LOW);
  89. luat_timer_us_delay(2);
  90. luat_gpio_set(pin, Luat_GPIO_HIGH);
  91. luat_timer_us_delay(60);
  92. }
  93. else
  94. {
  95. luat_gpio_set(pin, Luat_GPIO_LOW);
  96. luat_timer_us_delay(60);
  97. luat_gpio_set(pin, Luat_GPIO_HIGH);
  98. luat_timer_us_delay(2);
  99. }
  100. }
  101. }
  102. static uint8_t crc8_maxim[256] = {
  103. 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
  104. 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
  105. 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
  106. 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
  107. 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
  108. 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
  109. 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
  110. 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
  111. 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
  112. 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
  113. 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
  114. 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
  115. 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
  116. 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
  117. 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
  118. 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
  119. static int32_t ds18b20_get_temperature(int pin, int32_t *val, int check_crc)
  120. {
  121. uint8_t TL, TH;
  122. int32_t tem;
  123. uint8_t data[9] = {0};
  124. //ds18b20_start(pin);
  125. w1_reset(pin);
  126. if (w1_connect(pin))
  127. {
  128. //LLOGD("ds18b20 connect fail");
  129. return -1;
  130. }
  131. w1_write_byte(pin, 0xcc); /* skip rom */
  132. w1_write_byte(pin, 0x44); /* convert */
  133. //ds18b20_init(pin);
  134. w1_reset(pin);
  135. if (w1_connect(pin))
  136. {
  137. //LLOGD("ds18b20 connect fail");
  138. return -2;
  139. }
  140. w1_write_byte(pin, 0xcc);
  141. w1_write_byte(pin, 0xbe);
  142. data[0] = w1_read_byte(pin); /* LSB first */
  143. data[1] = w1_read_byte(pin);
  144. if (data[0] == 0xFF || data[1] == 0xFF)
  145. {
  146. //LLOGD("ds18b20 bad data, skip");
  147. return -3;
  148. }
  149. // 9个字节都读出来,校验CRC
  150. if (check_crc)
  151. {
  152. for (size_t i = 2; i < 9; i++)
  153. {
  154. data[i] = w1_read_byte(pin);
  155. }
  156. uint8_t crc = 0;
  157. for (size_t i = 0; i < 8; i++)
  158. {
  159. crc = crc8_maxim[crc ^ data[i]];
  160. }
  161. // LLOGD("ds18b20 %02X%02X%02X%02X%02X%02X%02X%02X [%02X %02X]",
  162. // data[0], data[1], data[2], data[3],
  163. // data[4], data[5], data[6], data[7],
  164. // data[8], crc);
  165. if (data[8] != crc)
  166. {
  167. //LLOGD("ds18b20 bad crc");
  168. return -4;
  169. }
  170. }
  171. TL = data[0];
  172. TH = data[1];
  173. if (TH > 7)
  174. {
  175. TH = ~TH;
  176. TL = ~TL;
  177. tem = TH;
  178. tem <<= 8;
  179. tem += TL;
  180. tem = (int32_t)(tem * 0.0625 * 10 + 0.5);
  181. *val = tem;
  182. return 0;
  183. }
  184. else
  185. {
  186. tem = TH;
  187. tem <<= 8;
  188. tem += TL;
  189. tem = (int32_t)(tem * 0.0625 * 10 + 0.5);
  190. *val = tem;
  191. return 0;
  192. }
  193. }
  194. /*
  195. 获取DS18B20的温度数据
  196. @api sensor.ds18b20(pin)
  197. @int gpio端口号
  198. @boolean 是否校验crc值,默认为true. 不校验crc值能提高读取成功的概率,但可能会读取到错误的值
  199. @return int 温度数据,单位0.1摄氏度,读取失败时返回错误码
  200. @return boolean 成功返回true,否则返回false
  201. @usage
  202. while 1 do
  203. sys.wait(5000)
  204. local val,result = sensor.ds18b20(17, true) -- GPIO17且校验CRC值
  205. -- val 301 == 30.1摄氏度
  206. -- result true 读取成功
  207. log.info("ds18b20", val, result)
  208. end
  209. */
  210. static int l_sensor_ds18b20(lua_State *L)
  211. {
  212. int32_t val = 0;
  213. int check_crc = lua_gettop(L) > 1 ? lua_toboolean(L, 2) : 1;
  214. int pin = luaL_checkinteger(L, 1);
  215. luat_os_entry_cri();
  216. int32_t ret = ds18b20_get_temperature(pin, &val, check_crc);
  217. luat_os_exit_cri();
  218. // -55°C ~ 125°C
  219. if (ret || !(val <= 1250 && val >= -550))
  220. {
  221. LLOGI("ds18b20 read fail");
  222. lua_pushinteger(L, ret);
  223. lua_pushboolean(L, 0);
  224. return 2;
  225. }
  226. //rt_kprintf("temp:%3d.%dC\n", temp/10, temp%10);
  227. lua_pushinteger(L, val);
  228. lua_pushboolean(L, 1);
  229. return 2;
  230. }
  231. //-------------------------------------
  232. // W1 单总线协议, 暴露w1_xxx方法
  233. //-------------------------------------
  234. /*
  235. 单总线协议,复位设备
  236. @api sensor.w1_reset(pin)
  237. @int gpio端口号
  238. @return nil 无返回
  239. */
  240. static int l_w1_reset(lua_State *L)
  241. {
  242. w1_reset((int)luaL_checkinteger(L, 1));
  243. return 0;
  244. }
  245. /*
  246. 单总线协议,连接设备
  247. @api sensor.w1_connect(pin)
  248. @int gpio端口号
  249. @return boolean 成功返回true,失败返回false
  250. */
  251. static int l_w1_connect(lua_State *L)
  252. {
  253. if (w1_connect((int)luaL_checkinteger(L, 1)) == CONNECT_SUCCESS)
  254. {
  255. lua_pushboolean(L, 1);
  256. }
  257. else
  258. {
  259. lua_pushboolean(L, 0);
  260. }
  261. return 1;
  262. }
  263. /*
  264. 单总线协议,往总线写入数据
  265. @api sensor.w1_write(pin, data1,data2)
  266. @int gpio端口号
  267. @int 第一个数据
  268. @int 第二个数据, 可以写N个数据
  269. @return nil 无返回值
  270. */
  271. static int l_w1_write_byte(lua_State *L)
  272. {
  273. int pin = luaL_checkinteger(L, 1);
  274. int top = lua_gettop(L);
  275. if (top > 1)
  276. {
  277. for (size_t i = 2; i <= top; i++)
  278. {
  279. uint8_t data = luaL_checkinteger(L, i);
  280. w1_write_byte(pin, data);
  281. }
  282. }
  283. return 0;
  284. }
  285. /*
  286. 单总线协议,从总线读取数据
  287. @api sensor.w1_read(pin, len)
  288. @int gpio端口号
  289. @int 读取的长度
  290. @return int 按读取的长度返回N个整数
  291. */
  292. static int l_w1_read_byte(lua_State *L)
  293. {
  294. int pin = luaL_checkinteger(L, 1);
  295. int len = luaL_checkinteger(L, 2);
  296. for (size_t i = 0; i < len; i++)
  297. {
  298. lua_pushinteger(L, w1_read_byte(pin));
  299. }
  300. return len;
  301. }
  302. unsigned long ReadCount(int date,int clk) //增益128
  303. {
  304. unsigned long count;
  305. unsigned char i;
  306. luat_gpio_mode(date, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
  307. luat_gpio_set(date, Luat_GPIO_HIGH);
  308. luat_timer_us_delay(1);
  309. luat_gpio_mode(clk, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
  310. luat_gpio_set(clk, Luat_GPIO_LOW);
  311. luat_gpio_mode(date, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 0);
  312. luat_timer_us_delay(1);
  313. count = 0;
  314. while (luat_gpio_get(date))
  315. ; // TODO 用tick或者us_delay统计timeout
  316. for (i = 0; i < 24; i++)
  317. {
  318. luat_gpio_set(clk, Luat_GPIO_HIGH);
  319. count = count << 1;
  320. luat_gpio_set(clk, Luat_GPIO_LOW);
  321. if (luat_gpio_get(date))
  322. count++;
  323. }
  324. luat_gpio_set(clk, Luat_GPIO_HIGH);
  325. luat_timer_us_delay(1);
  326. luat_gpio_set(clk, Luat_GPIO_LOW);
  327. return count;
  328. }
  329. /*
  330. 获取Hx711的温度数据
  331. @api sensor.hx711(pin_date,pin_clk)
  332. @int 数据的gpio端口号
  333. @int 时钟的gpio端口号
  334. @return int hx711读到的数据
  335. @usage
  336. -- 如果设备不存在会卡在读取接口
  337. sys.taskInit(
  338. function()
  339. sys.wait(1000)
  340. local maopi = sensor.hx711(0,7)
  341. while true do
  342. sys.wait(2000)
  343. a = sensor.hx711(0,7) - maopi
  344. if a > 0 then
  345. log.info("tag", a / 4.6)
  346. end
  347. end
  348. end
  349. )
  350. */
  351. static int l_sensor_hx711(lua_State *L)
  352. {
  353. // unsigned int j;
  354. unsigned long hx711_dat;
  355. int date = luaL_checkinteger(L, 1);
  356. int clk = luaL_checkinteger(L, 2);
  357. //for (j = 0; j < 5; j++)
  358. // luat_timer_us_delay(5000);
  359. hx711_dat = ReadCount(date,clk); //HX711AD转换数据处理
  360. temp = (unsigned int)(hx711_dat / 100); //缩放long数据为int型,方便处理
  361. //LLOGI("hx711:%d",temp);
  362. lua_pushinteger(L, temp);
  363. return 1;
  364. }
  365. /*
  366. 设置ws2812b输出
  367. @api sensor.ws2812b(pin,data,T0H,T0L,T1H,T1L)
  368. @int ws2812b的gpio端口号
  369. @string/zbuff 待发送的数据(如果为zbuff数据,则会无视指针位置始终从0偏移开始)
  370. @int T0H时间,表示延时多少个nop,每个型号不一样,自己调
  371. @int T0L时间,表示延时多少个nop
  372. @int T1H时间,表示延时多少个nop
  373. @int T1L时间,表示延时多少个nop
  374. @usage
  375. local buff = zbuff.create({8,8,24})
  376. buff:drawLine(1,2,5,6,0x00ffff)
  377. sensor.ws2812b(7,buff,300,700,700,700)
  378. */
  379. #define WS2812B_BIT_0() \
  380. t0h_temp = t0h; t0l_temp = t0l; \
  381. luat_gpio_set(pin, Luat_GPIO_HIGH); \
  382. while(t0h_temp--); \
  383. luat_gpio_set(pin, Luat_GPIO_LOW); \
  384. while(t0l_temp--)
  385. #define WS2812B_BIT_1() \
  386. t1h_temp = t1h; t1l_temp = t1l; \
  387. luat_gpio_set(pin, Luat_GPIO_HIGH); \
  388. while(t1h_temp--); \
  389. luat_gpio_set(pin, Luat_GPIO_LOW); \
  390. while(t1l_temp--)
  391. static int l_sensor_ws2812b(lua_State *L)
  392. {
  393. int j;
  394. size_t len,i;
  395. const char *send_buff = NULL;
  396. int pin = luaL_checkinteger(L, 1);
  397. if (lua_isuserdata(L, 2))
  398. {
  399. luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  400. send_buff = (const char*)buff->addr;
  401. len = buff->len;
  402. }
  403. else
  404. {
  405. send_buff = lua_tolstring(L, 2, &len);
  406. }
  407. uint32_t t0h_temp,t0h = luaL_checkinteger(L, 3);
  408. uint32_t t0l_temp,t0l = luaL_checkinteger(L, 4);
  409. uint32_t t1h_temp,t1h = luaL_checkinteger(L, 5);
  410. uint32_t t1l_temp,t1l = luaL_checkinteger(L, 6);
  411. luat_os_entry_cri();
  412. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  413. //luat_gpio_set(pin, Luat_GPIO_LOW);
  414. luat_timer_us_delay(1);
  415. //luat_gpio_set(pin, Luat_GPIO_HIGH);
  416. for(i=0;i<len;i++)
  417. {
  418. for(j=7;j>=0;j--)
  419. {
  420. if(send_buff[i]>>j&0x01)
  421. {
  422. WS2812B_BIT_1();
  423. }
  424. else
  425. {
  426. WS2812B_BIT_0();
  427. }
  428. }
  429. }
  430. luat_os_exit_cri();
  431. return 0;
  432. }
  433. #include "rotable2.h"
  434. static const rotable_Reg_t reg_sensor[] =
  435. {
  436. {"w1_reset", ROREG_FUNC(l_w1_reset)},
  437. {"w1_connect", ROREG_FUNC(l_w1_connect)},
  438. {"w1_write", ROREG_FUNC(l_w1_write_byte)},
  439. {"w1_read", ROREG_FUNC(l_w1_read_byte)},
  440. {"ds18b20", ROREG_FUNC(l_sensor_ds18b20)},
  441. {"hx711", ROREG_FUNC(l_sensor_hx711)},
  442. {"ws2812b", ROREG_FUNC(l_sensor_ws2812b)},
  443. {NULL, ROREG_INT(0) }
  444. };
  445. LUAMOD_API int luaopen_sensor(lua_State *L)
  446. {
  447. luat_newlib2(L, reg_sensor);
  448. return 1;
  449. }