luat_lib_sensor.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. /*
  2. @module sensor
  3. @summary 传感器操作库
  4. @version 1.0
  5. @date 2020.03.30
  6. @tag LUAT_USE_SENSOR
  7. @demo dht11
  8. @usage
  9. -- 请查阅demo/dht11 demo/ds18b20
  10. */
  11. #include "luat_base.h"
  12. #include "luat_timer.h"
  13. #include "luat_mem.h"
  14. #include "luat_gpio.h"
  15. #include "luat_zbuff.h"
  16. #ifdef LUAT_USE_SENSOR
  17. #ifdef LUAT_USE_DRV_GPIO
  18. #include "luat/drv_gpio.h"
  19. #endif
  20. #define LUAT_LOG_TAG "sensor"
  21. #include "luat_log.h"
  22. #define CONNECT_SUCCESS 0
  23. #define CONNECT_FAILED 1
  24. static void w1_reset(int pin)
  25. {
  26. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  27. luat_gpio_set(pin, Luat_GPIO_LOW);
  28. luat_timer_us_delay(550); /* 480us - 960us */
  29. luat_gpio_set(pin, Luat_GPIO_HIGH);
  30. luat_timer_us_delay(40); /* 15us - 60us*/
  31. }
  32. static uint8_t w1_connect(int pin)
  33. {
  34. uint8_t retry = 0;
  35. luat_gpio_mode(pin, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 0);
  36. while (luat_gpio_get(pin) && retry < 200)
  37. {
  38. retry++;
  39. luat_timer_us_delay(1);
  40. };
  41. if (retry >= 200)
  42. return CONNECT_FAILED;
  43. else
  44. retry = 0;
  45. while (!luat_gpio_get(pin) && retry < 240)
  46. {
  47. retry++;
  48. luat_timer_us_delay(1);
  49. };
  50. if (retry >= 240)
  51. return CONNECT_FAILED;
  52. return CONNECT_SUCCESS;
  53. }
  54. static uint8_t w1_read_bit(int pin){
  55. uint8_t data;
  56. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
  57. luat_gpio_set(pin, Luat_GPIO_LOW);
  58. luat_timer_us_delay(2);
  59. // luat_gpio_set(pin, Luat_GPIO_HIGH);
  60. luat_gpio_mode(pin, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 0);
  61. data = (uint8_t)luat_gpio_get(pin);
  62. luat_timer_us_delay(60);
  63. return data;
  64. }
  65. static uint8_t w1_read_byte(int pin)
  66. {
  67. uint8_t i, j, dat;
  68. dat = 0;
  69. luat_timer_us_delay(90);
  70. //rt_base_t level;
  71. //level = rt_hw_interrupt_disable();
  72. for (i = 1; i <= 8; i++)
  73. {
  74. j = w1_read_bit(pin);
  75. dat = (j << 7) | (dat >> 1);
  76. }
  77. //rt_hw_interrupt_enable(level);
  78. return dat;
  79. }
  80. static void w1_write_byte(int pin, uint8_t dat)
  81. {
  82. uint8_t j;
  83. uint8_t testb;
  84. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  85. for (j = 1; j <= 8; j++)
  86. {
  87. testb = dat & 0x01;
  88. dat = dat >> 1;
  89. if (testb)
  90. {
  91. luat_gpio_set(pin, Luat_GPIO_LOW);
  92. luat_timer_us_delay(2);
  93. luat_gpio_set(pin, Luat_GPIO_HIGH);
  94. luat_timer_us_delay(60);
  95. }
  96. else
  97. {
  98. luat_gpio_set(pin, Luat_GPIO_LOW);
  99. luat_timer_us_delay(60);
  100. luat_gpio_set(pin, Luat_GPIO_HIGH);
  101. luat_timer_us_delay(2);
  102. }
  103. }
  104. }
  105. static const uint8_t crc8_maxim[256] = {
  106. 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
  107. 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
  108. 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
  109. 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
  110. 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
  111. 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
  112. 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
  113. 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
  114. 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
  115. 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
  116. 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
  117. 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
  118. 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
  119. 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
  120. 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
  121. 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
  122. static int32_t ds18b20_get_temperature(int pin, int32_t *val, int check_crc)
  123. {
  124. uint8_t TL, TH;
  125. int32_t tem;
  126. uint8_t data[9] = {0};
  127. //ds18b20_start(pin);
  128. w1_reset(pin);
  129. if (w1_connect(pin)){
  130. // LLOGD("ds18b20 connect fail");
  131. return -1;
  132. }
  133. w1_write_byte(pin, 0xcc); /* skip rom */
  134. w1_write_byte(pin, 0x44); /* convert */
  135. //ds18b20_init(pin);
  136. w1_reset(pin);
  137. if (w1_connect(pin)){
  138. // LLOGD("ds18b20 connect fail");
  139. return -2;
  140. }
  141. w1_write_byte(pin, 0xcc);
  142. w1_write_byte(pin, 0xbe);
  143. data[0] = w1_read_byte(pin); /* LSB first */
  144. data[1] = w1_read_byte(pin);
  145. // if (data[0] == 0xFF || data[1] == 0xFF)
  146. // {
  147. // //LLOGD("ds18b20 bad data, skip");
  148. // return -3;
  149. // }
  150. // 9个字节都读出来,校验CRC
  151. if (check_crc)
  152. {
  153. for (size_t i = 2; i < 9; i++){
  154. data[i] = w1_read_byte(pin);
  155. }
  156. uint8_t crc = 0;
  157. for (size_t i = 0; i < 8; i++){
  158. crc = crc8_maxim[crc ^ data[i]];
  159. }
  160. // LLOGD("ds18b20 %02X%02X%02X%02X%02X%02X%02X%02X [%02X %02X]",
  161. // data[0], data[1], data[2], data[3],
  162. // data[4], data[5], data[6], data[7],
  163. // data[8], crc);
  164. if (data[8] != crc){
  165. // LLOGD("ds18b20 bad crc");
  166. return -4;
  167. }
  168. }
  169. TL = data[0];
  170. TH = data[1];
  171. if (TH > 7){
  172. TH = ~TH;
  173. TL = ~TL;
  174. tem = TH;
  175. tem <<= 8;
  176. tem += TL;
  177. tem = (int32_t)(tem * 0.0625 * 10 + 0.5);
  178. *val = -tem;
  179. return 0;
  180. }else{
  181. tem = TH;
  182. tem <<= 8;
  183. tem += TL;
  184. tem = (int32_t)(tem * 0.0625 * 10 + 0.5);
  185. *val = tem;
  186. return 0;
  187. }
  188. }
  189. /*
  190. 获取DS18B20的温度数据
  191. @api sensor.ds18b20(pin, check_crc)
  192. @int gpio端口号
  193. @boolean 是否校验crc值,默认为true. 不校验crc值能提高读取成功的概率,但可能会读取到错误的值
  194. @return int 温度数据,单位0.1摄氏度,读取失败时返回错误码
  195. @return boolean 成功返回true,否则返回false
  196. @usage
  197. while 1 do
  198. sys.wait(5000)
  199. local val,result = sensor.ds18b20(17, true) -- GPIO17且校验CRC值
  200. -- val 301 == 30.1摄氏度
  201. -- result true 读取成功
  202. log.info("ds18b20", val, result)
  203. end
  204. */
  205. static int l_sensor_ds18b20(lua_State *L)
  206. {
  207. int32_t val = 0;
  208. int check_crc = lua_gettop(L) > 1 ? lua_toboolean(L, 2) : 1;
  209. int pin = luaL_checkinteger(L, 1);
  210. #ifdef LUAT_USE_MOBILE
  211. #else
  212. luat_os_entry_cri();
  213. #endif
  214. int32_t ret = ds18b20_get_temperature(pin, &val, check_crc);
  215. #ifdef LUAT_USE_MOBILE
  216. #else
  217. luat_os_exit_cri();
  218. #endif
  219. // -55°C ~ 125°C
  220. if (ret || !(val <= 1250 && val >= -550))
  221. {
  222. LLOGI("ds18b20 read fail");
  223. lua_pushinteger(L, ret);
  224. lua_pushboolean(L, 0);
  225. return 2;
  226. }
  227. //rt_kprintf("temp:%3d.%dC\n", temp/10, temp%10);
  228. lua_pushinteger(L, val);
  229. lua_pushboolean(L, 1);
  230. return 2;
  231. }
  232. //-------------------------------------
  233. // W1 单总线协议, 暴露w1_xxx方法
  234. //-------------------------------------
  235. /*
  236. 单总线协议,复位设备
  237. @api sensor.w1_reset(pin)
  238. @int gpio端口号
  239. @return nil 无返回
  240. */
  241. static int l_w1_reset(lua_State *L)
  242. {
  243. w1_reset((int)luaL_checkinteger(L, 1));
  244. return 0;
  245. }
  246. /*
  247. 单总线协议,连接设备
  248. @api sensor.w1_connect(pin)
  249. @int gpio端口号
  250. @return boolean 成功返回true,失败返回false
  251. */
  252. static int l_w1_connect(lua_State *L)
  253. {
  254. if (w1_connect((int)luaL_checkinteger(L, 1)) == CONNECT_SUCCESS)
  255. {
  256. lua_pushboolean(L, 1);
  257. }
  258. else
  259. {
  260. lua_pushboolean(L, 0);
  261. }
  262. return 1;
  263. }
  264. /*
  265. 单总线协议,往总线写入数据
  266. @api sensor.w1_write(pin, data1,data2)
  267. @int gpio端口号
  268. @int 第一个数据
  269. @int 第二个数据, 可以写N个数据
  270. @return nil 无返回值
  271. */
  272. static int l_w1_write_byte(lua_State *L)
  273. {
  274. int pin = luaL_checkinteger(L, 1);
  275. int top = lua_gettop(L);
  276. if (top > 1)
  277. {
  278. for (int i = 2; i <= top; i++)
  279. {
  280. uint8_t data = luaL_checkinteger(L, i);
  281. w1_write_byte(pin, data);
  282. }
  283. }
  284. return 0;
  285. }
  286. /*
  287. 单总线协议,从总线读取数据
  288. @api sensor.w1_read(pin, len)
  289. @int gpio端口号
  290. @int 读取的长度
  291. @return int 按读取的长度返回N个整数
  292. */
  293. static int l_w1_read_byte(lua_State *L)
  294. {
  295. int pin = luaL_checkinteger(L, 1);
  296. int len = luaL_checkinteger(L, 2);
  297. for (int i = 0; i < len; i++)
  298. {
  299. lua_pushinteger(L, w1_read_byte(pin));
  300. }
  301. return len;
  302. }
  303. unsigned long ReadCount(int date,int clk) //增益128
  304. {
  305. unsigned long count = 0;
  306. unsigned char i = 0;
  307. luat_gpio_mode(date, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
  308. luat_gpio_set(date, Luat_GPIO_HIGH);
  309. luat_timer_us_delay(1);
  310. luat_gpio_mode(clk, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
  311. luat_gpio_set(clk, Luat_GPIO_LOW);
  312. luat_gpio_mode(date, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 0);
  313. luat_timer_us_delay(1);
  314. count = 0;
  315. int retry = 50; // 最多等待5ms == 50 * 100us
  316. while (retry > 0 && luat_gpio_get(date)) {
  317. luat_timer_us_delay(100);
  318. retry --;
  319. }
  320. for (i = 0; i < 24; i++)
  321. {
  322. luat_gpio_set(clk, Luat_GPIO_HIGH);
  323. count = count << 1;
  324. luat_gpio_set(clk, Luat_GPIO_LOW);
  325. if (luat_gpio_get(date))
  326. count++;
  327. }
  328. luat_gpio_set(clk, Luat_GPIO_HIGH);
  329. luat_timer_us_delay(1);
  330. luat_gpio_set(clk, Luat_GPIO_LOW);
  331. return count;
  332. }
  333. /*
  334. 获取Hx711的压力传感数据
  335. @api sensor.hx711(pin_date,pin_clk)
  336. @int 数据的gpio端口号
  337. @int 时钟的gpio端口号
  338. @return int hx711读到的数据
  339. @usage
  340. -- 如果设备不存在会卡在读取接口
  341. sys.taskInit(
  342. function()
  343. sys.wait(1000)
  344. local maopi = sensor.hx711(0,7)
  345. while true do
  346. sys.wait(2000)
  347. a = sensor.hx711(0,7) - maopi
  348. if a > 0 then
  349. log.info("tag", a / 4.6)
  350. end
  351. end
  352. end
  353. )
  354. */
  355. static int l_sensor_hx711(lua_State *L)
  356. {
  357. // unsigned int j;
  358. unsigned long hx711_dat = 0;
  359. unsigned int temp = 0;
  360. int date = luaL_checkinteger(L, 1);
  361. int clk = luaL_checkinteger(L, 2);
  362. //for (j = 0; j < 5; j++)
  363. // luat_timer_us_delay(5000);
  364. hx711_dat = ReadCount(date,clk); //HX711AD转换数据处理
  365. temp = (unsigned int)(hx711_dat / 100); //缩放long数据为int型,方便处理
  366. //LLOGI("hx711:%d",temp);
  367. lua_pushinteger(L, temp);
  368. return 1;
  369. }
  370. /*
  371. 获取cs1237传感数据
  372. @api sensor.cs1237(pin_date,pin_clk)
  373. @int 数据的gpio端口号
  374. @int 时钟的gpio端口号
  375. @return int cs1237读到的数据
  376. @usage
  377. -- 如果设备不存在会卡在读取接口
  378. sys.taskInit(
  379. function()
  380. sys.wait(1000)
  381. local cs1237_data = sensor.cs1237(0,7)
  382. while true do
  383. sys.wait(2000)
  384. cs1237_data = sensor.cs1237(0,7) - maopi
  385. log.info("cs1237_data:", cs1237_data)--得到原始数据
  386. end
  387. end
  388. )
  389. */
  390. static int l_sensor_cs1237(lua_State *L)
  391. {
  392. // unsigned int j;
  393. unsigned long cs1237_dat = 0;
  394. unsigned int temp = 0;
  395. int date = luaL_checkinteger(L, 1);
  396. int clk = luaL_checkinteger(L, 2);
  397. //for (j = 0; j < 5; j++)
  398. // luat_timer_us_delay(5000);
  399. cs1237_dat = ReadCount(date,clk);
  400. temp = (unsigned int)cs1237_dat;
  401. //LLOGI("cs1237:%d",temp);
  402. lua_pushinteger(L, temp);
  403. return 1;
  404. }
  405. /*
  406. 设置ws2812b输出(gpio驱动方式)
  407. @api sensor.ws2812b(pin,data,T0H,T0L,T1H,T1L)
  408. @int ws2812b的gpio端口号
  409. @string/zbuff 待发送的数据(如果为zbuff数据,则会无视指针位置始终从0偏移开始)
  410. @int T0H时间,表示延时多少个nop,每个型号不一样,自己调
  411. @int T0L时间,表示延时多少个nop
  412. @int T1H时间,表示延时多少个nop
  413. @int T1L时间,表示延时多少个nop
  414. @usage
  415. local buff = zbuff.create({8,8,24})
  416. buff:drawLine(1,2,5,6,0x00ffff)
  417. sensor.ws2812b(7,buff,300,700,700,700)
  418. */
  419. const unsigned char xor_bit_table[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  420. #define WS2812B_BIT_0() \
  421. t0h_temp = t0h; t0l_temp = t0l; \
  422. luat_gpio_pulse(pin,&pulse_level,2,t0h); \
  423. while(t0l_temp--)
  424. #define WS2812B_BIT_1() \
  425. t1h_temp = t1h; t1l_temp = t1l; \
  426. luat_gpio_pulse(pin,&pulse_level,2,t1h); \
  427. while(t1l_temp--)
  428. static int l_sensor_ws2812b(lua_State *L)
  429. {
  430. int j;
  431. size_t len,i;
  432. uint8_t pulse_level = 0x80;
  433. const char *send_buff = NULL;
  434. int pin = luaL_checkinteger(L, 1);
  435. if (lua_isuserdata(L, 2))
  436. {
  437. luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  438. send_buff = (const char*)buff->addr;
  439. len = buff->len;
  440. }
  441. else
  442. {
  443. send_buff = lua_tolstring(L, 2, &len);
  444. }
  445. #ifdef LUAT_WS2812B_MAX_CNT
  446. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_DEFAULT, Luat_GPIO_LOW);
  447. uint8_t bit0h = luaL_optinteger(L, 3, 10);
  448. uint8_t bit0l = luaL_optinteger(L, 4, 0);
  449. uint8_t bit1h = luaL_optinteger(L, 5, 10);
  450. uint8_t bit1l = luaL_optinteger(L, 6, 0);
  451. uint32_t frame_cnt = luaL_optinteger(L, 7, 0);
  452. luat_gpio_driver_ws2812b(pin, send_buff, len, frame_cnt, bit0h, bit0l, bit1h, bit1l);
  453. #else
  454. volatile uint32_t t0h_temp,t0h = luaL_checkinteger(L, 3);
  455. volatile uint32_t t0l_temp,t0l = luaL_checkinteger(L, 4);
  456. volatile uint32_t t1h_temp,t1h = luaL_checkinteger(L, 5);
  457. volatile uint32_t t1l_temp,t1l = luaL_checkinteger(L, 6);
  458. (void)t1h_temp;(void)t0h_temp;
  459. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  460. pulse_level = 0 ;
  461. luat_gpio_pulse(pin,&pulse_level,2,t0h);
  462. pulse_level = 0x80;
  463. luat_os_entry_cri();
  464. for(i=0;i<len;i++)
  465. {
  466. for(j=7;j>=0;j--)
  467. {
  468. if(send_buff[i]&xor_bit_table[j])
  469. {
  470. WS2812B_BIT_1();
  471. }
  472. else
  473. {
  474. WS2812B_BIT_0();
  475. }
  476. }
  477. }
  478. luat_os_exit_cri();
  479. #endif
  480. return 0;
  481. }
  482. #ifdef LUAT_USE_PWM
  483. #include "luat_pwm.h"
  484. static luat_pwm_conf_t ws2812b_pwm_conf = {
  485. .pnum = 1,
  486. .period = 800*1000,
  487. .precision = 100
  488. };
  489. /*
  490. 设置ws2812b输出(pwm驱动方式,需要pwm能输出800k频率,否则无法使用此方法)
  491. @api sensor.ws2812b_pwm(pin,data)
  492. @int pwm端口号
  493. @string/zbuff 待发送的数据(如果为zbuff数据,则会无视指针位置始终从0偏移开始)
  494. @usage
  495. local buff = zbuff.create({8,8,24})
  496. buff:setFrameBuffer(8,8,24,0x0000ff)
  497. sensor.ws2812b_pwm(7,buff)
  498. */
  499. static int l_sensor_ws2812b_pwm(lua_State *L)
  500. {
  501. int ret = 0;
  502. int j = 0;
  503. size_t len,i;
  504. const char *send_buff = NULL;
  505. ws2812b_pwm_conf.channel = luaL_checkinteger(L, 1);
  506. if (lua_isuserdata(L, 2)){
  507. luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  508. send_buff = (const char*)buff->addr;
  509. len = buff->len;
  510. }else if(lua_isstring(L, 2)){
  511. send_buff = lua_tolstring(L, 2, &len);
  512. }else return 0;
  513. //ws2812b_pwm_conf.pulse = 0;
  514. //luat_pwm_setup(&ws2812b_pwm_conf);
  515. for(i=0;i<len;i++){
  516. for(j=7;j>=0;j--){
  517. if(send_buff[i]>>j&0x01){
  518. ws2812b_pwm_conf.pulse = 200/3;
  519. ret = luat_pwm_setup(&ws2812b_pwm_conf);
  520. }else{
  521. ws2812b_pwm_conf.pulse = 100/3;
  522. ret = luat_pwm_setup(&ws2812b_pwm_conf);
  523. }
  524. if (ret) {
  525. LLOGW("luat_pwm_setup ret %d, end of PWM output", ret);
  526. return 0;
  527. }
  528. }
  529. }
  530. return 0;
  531. }
  532. #endif
  533. #ifdef LUAT_USE_SPI
  534. #include "luat_spi.h"
  535. static luat_spi_t ws2812b_spi_conf = {
  536. .cs = 255,
  537. .CPHA = 0,
  538. .CPOL = 0,
  539. .dataw = 8,
  540. .bandrate = 5*1000*1000,
  541. .bit_dict = 1,
  542. .master = 1,
  543. .mode = 1,
  544. };
  545. /*
  546. 设置ws2812b输出(spi驱动方式,需要spi能输出5M频率,否则无法使用此方法)
  547. @api sensor.ws2812b_spi(pin,data)
  548. @int spi端口号
  549. @string/zbuff 待发送的数据(如果为zbuff数据,则会无视指针位置始终从0偏移开始)
  550. @usage
  551. local buff = zbuff.create({8,8,24})
  552. buff:setFrameBuffer(8,8,24,0x0000ff)
  553. sensor.ws2812b_spi(2,buff)
  554. */
  555. static int l_sensor_ws2812b_spi(lua_State *L)
  556. {
  557. int j,m;
  558. size_t len,i;
  559. const char *send_buff = NULL;
  560. ws2812b_spi_conf.id = luaL_checkinteger(L, 1);
  561. if (lua_isuserdata(L, 2)){
  562. luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  563. send_buff = (const char*)buff->addr;
  564. len = buff->len;
  565. }else if(lua_isstring(L, 2)){
  566. send_buff = lua_tolstring(L, 2, &len);
  567. }else return 0;
  568. const char res_buff = 0x00;
  569. const char low_buff = 0xc0;
  570. const char high_buff = 0xf8;
  571. luat_spi_setup(&ws2812b_spi_conf);
  572. luat_spi_send(ws2812b_spi_conf.id, &res_buff, 1);
  573. char *gbr_buff = luat_heap_malloc(len*8);
  574. m=0;
  575. for(i=0;i<len;i++){
  576. for(j=7;j>=0;j--){
  577. if(send_buff[i]>>j&0x01){
  578. gbr_buff[m]=high_buff;
  579. }else{
  580. gbr_buff[m]=low_buff;
  581. }
  582. m++;
  583. }
  584. }
  585. luat_spi_send(ws2812b_spi_conf.id, gbr_buff, len*8);
  586. luat_spi_close(ws2812b_spi_conf.id);
  587. luat_heap_free(gbr_buff);
  588. return 0;
  589. }
  590. #endif
  591. //总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒
  592. static void dht_reset(int pin)
  593. {
  594. luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_HIGH);
  595. luat_gpio_set(pin, Luat_GPIO_HIGH);
  596. luat_timer_mdelay(100);
  597. luat_gpio_set(pin, Luat_GPIO_LOW);
  598. luat_timer_mdelay(20);
  599. luat_gpio_set(pin, Luat_GPIO_HIGH);
  600. }
  601. //主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号
  602. static uint8_t dht_connect(int pin)
  603. {
  604. luat_gpio_mode(pin, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, Luat_GPIO_HIGH);
  605. luat_timer_us_delay(10);
  606. uint8_t retry = 0;
  607. while (luat_gpio_get(pin) && retry < 100)
  608. {
  609. retry++;
  610. luat_timer_us_delay(1);
  611. };
  612. if (retry >= 100)
  613. return CONNECT_FAILED;
  614. retry = 0;
  615. while (!luat_gpio_get(pin) && retry < 100)
  616. {
  617. retry++;
  618. luat_timer_us_delay(1);
  619. };
  620. if (retry >= 100)
  621. return CONNECT_FAILED;
  622. //相应完后等变低
  623. while (luat_gpio_get(pin) && retry < 200)
  624. {
  625. retry++;
  626. luat_timer_us_delay(1);
  627. };
  628. return CONNECT_SUCCESS;
  629. }
  630. //总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短决定了数据位是0还是1
  631. static uint8_t dht_read_bit(int pin)
  632. {
  633. uint8_t retry=0,d=0;
  634. while (!luat_gpio_get(pin) && retry < 200)
  635. {
  636. retry++;
  637. luat_timer_us_delay(1);
  638. };
  639. luat_timer_us_delay(30);
  640. d = luat_gpio_get(pin);
  641. retry=0;
  642. while (luat_gpio_get(pin) && retry < 200)
  643. {
  644. retry++;
  645. luat_timer_us_delay(1);
  646. };
  647. return d;
  648. }
  649. static uint8_t dht_read_byte(int pin)
  650. {
  651. uint8_t i, dat;
  652. dat = 0;
  653. for (i = 0; i < 8; i++)//MSB
  654. {
  655. dat<<=1;
  656. dat+=dht_read_bit(pin);
  657. }
  658. return dat;
  659. }
  660. /*
  661. 获取DHT11/DHT12的温湿度数据
  662. @api sensor.dht1x(pin)
  663. @int gpio端口号
  664. @boolean 是否校验crc值,默认为true. 不校验crc值能提高读取成功的概率,但可能会读取到错误的值
  665. @return int 湿度数据,单位0.01%,读取失败时返回错误值
  666. @return int 温度数据,单位0.01摄氏度,读取失败时返回错误值
  667. @return boolean 成功返回true,否则返回false
  668. @usage
  669. while 1 do
  670. sys.wait(1000)
  671. local h,t,r = sensor.dht1x(17, true) -- GPIO17且校验CRC值
  672. log.info("dht11", h/100,t/100,r)--90.1 23.22
  673. end
  674. */
  675. static int dht1x_read(lua_State *L)
  676. {
  677. int pin = luaL_checkinteger(L,1);
  678. int check = lua_toboolean(L,2);
  679. dht_reset(pin);
  680. luat_os_entry_cri();
  681. if(dht_connect(pin) != CONNECT_SUCCESS)//没连上
  682. {
  683. luat_os_exit_cri();
  684. lua_pushinteger(L,0);
  685. lua_pushinteger(L,0);
  686. lua_pushboolean(L,0);
  687. return 3;
  688. }
  689. uint8_t buff[5];
  690. buff[0] = dht_read_byte(pin);
  691. buff[1] = dht_read_byte(pin);//小数部分
  692. buff[2] = dht_read_byte(pin);
  693. buff[3] = dht_read_byte(pin);//小数部分
  694. buff[4] = dht_read_byte(pin);//这是crc
  695. luat_os_exit_cri();
  696. int temp = (buff[0] & 0x7F) *100 + buff[1];
  697. int humi = (buff[2] & 0x7F) *100 + buff[3];
  698. if (buff[0] & 0x80)
  699. {
  700. temp = -temp;
  701. }
  702. lua_pushinteger(L, temp);
  703. lua_pushinteger(L, humi);
  704. if(check)
  705. {
  706. uint8_t check_r = 0;
  707. check_r = buff[0]+buff[1]+buff[2]+buff[3];
  708. lua_pushboolean(L,check_r == buff[4]);
  709. }
  710. else
  711. {
  712. lua_pushboolean(L,1);
  713. }
  714. return 3;
  715. }
  716. static unsigned char sc12a_wait_ack(int sda, int scl)
  717. {
  718. luat_gpio_set(sda, Luat_GPIO_HIGH);
  719. luat_gpio_mode(sda, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 1);
  720. luat_timer_us_delay(5);
  721. luat_gpio_set(scl, Luat_GPIO_HIGH);
  722. luat_timer_us_delay(5 * 3);
  723. int max_wait_time = 3000;
  724. while (max_wait_time--)
  725. {
  726. if (luat_gpio_get(sda) == Luat_GPIO_LOW)
  727. {
  728. luat_gpio_set(scl, Luat_GPIO_LOW);
  729. return 1;
  730. }
  731. luat_timer_us_delay(1);
  732. }
  733. // 停止信号
  734. luat_gpio_mode(sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  735. luat_gpio_set(scl, Luat_GPIO_LOW);
  736. luat_timer_us_delay(5);
  737. luat_gpio_set(sda, Luat_GPIO_LOW);
  738. luat_timer_us_delay(5);
  739. luat_gpio_set(scl, Luat_GPIO_HIGH);
  740. luat_timer_us_delay(5);
  741. luat_gpio_set(sda, Luat_GPIO_HIGH);
  742. luat_timer_us_delay(5);
  743. return 0;
  744. }
  745. static unsigned int read_sc12akey(int sda, int scl)
  746. {
  747. unsigned int data=0 ;
  748. unsigned char sc12a_addr = 0x81;
  749. // 发送开始信号
  750. luat_gpio_mode(scl, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  751. luat_gpio_mode(sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  752. luat_timer_us_delay(5);
  753. luat_gpio_set(scl, Luat_GPIO_HIGH);
  754. luat_timer_us_delay(5);
  755. luat_gpio_set(sda, Luat_GPIO_LOW);
  756. luat_timer_us_delay(5);
  757. luat_gpio_set(scl, Luat_GPIO_LOW);
  758. luat_timer_us_delay(5);
  759. // 发送地址
  760. unsigned char i = 8;
  761. luat_gpio_mode(sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
  762. while (i--)
  763. {
  764. luat_gpio_set(scl, Luat_GPIO_LOW);
  765. luat_timer_us_delay(5 * 2);
  766. if (sc12a_addr & 0x80)
  767. {
  768. luat_gpio_set(sda, Luat_GPIO_HIGH);
  769. }
  770. else
  771. {
  772. luat_gpio_set(sda, Luat_GPIO_LOW);
  773. }
  774. luat_timer_us_delay(5);
  775. sc12a_addr <<= 1;
  776. luat_gpio_set(scl, Luat_GPIO_HIGH);
  777. luat_timer_us_delay(5);
  778. luat_gpio_set(scl, Luat_GPIO_LOW);
  779. luat_timer_us_delay(5);
  780. }
  781. // 等待回应ack
  782. if (!sc12a_wait_ack(sda, scl))
  783. {
  784. luat_gpio_mode(sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  785. luat_gpio_set(scl, Luat_GPIO_LOW);
  786. luat_timer_us_delay(5);
  787. luat_gpio_set(sda, Luat_GPIO_LOW);
  788. luat_timer_us_delay(5);
  789. luat_gpio_set(scl, Luat_GPIO_HIGH);
  790. luat_timer_us_delay(5);
  791. luat_gpio_set(sda, Luat_GPIO_HIGH);
  792. luat_timer_us_delay(5);
  793. return -1;
  794. }
  795. i = 16;
  796. luat_gpio_set(sda, Luat_GPIO_HIGH);
  797. luat_gpio_mode(sda, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 1);
  798. while (i--)
  799. {
  800. data <<= 1;
  801. luat_gpio_set(scl, Luat_GPIO_LOW);
  802. luat_timer_us_delay(5);
  803. luat_gpio_set(scl, Luat_GPIO_HIGH);
  804. luat_timer_us_delay(5);
  805. if (luat_gpio_get(sda))
  806. data |= 0x01;
  807. }
  808. //发送NOACK
  809. luat_gpio_set(scl, Luat_GPIO_LOW);
  810. luat_gpio_mode(sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  811. luat_timer_us_delay(5);
  812. luat_gpio_set(scl, Luat_GPIO_HIGH);
  813. luat_timer_us_delay(5);
  814. luat_gpio_set(scl, Luat_GPIO_LOW);
  815. //发送STOP
  816. luat_gpio_mode(sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  817. luat_gpio_set(scl, Luat_GPIO_LOW);
  818. luat_timer_us_delay(5);
  819. luat_gpio_set(sda, Luat_GPIO_LOW);
  820. luat_timer_us_delay(5);
  821. luat_gpio_set(scl, Luat_GPIO_HIGH);
  822. luat_timer_us_delay(5);
  823. luat_gpio_set(sda, Luat_GPIO_HIGH);
  824. luat_timer_us_delay(5);
  825. return (data);
  826. }
  827. /*
  828. 获取sc12a被触摸的通道数据
  829. @api sensor.sc12a(sda,scl)
  830. @int 数据的gpio端口号
  831. @int 时钟的gpio端口号
  832. @return int 读取成功返回整形数据,读取失败时返回错误值
  833. @usage
  834. while true do
  835. local temp1=sensor.sc12a(4,7)
  836. if bit.rshift(bit.band( temp1, 0x8000), 15 )==0x01 then
  837. log.info("被按下的有通道0")
  838. end
  839. if bit.rshift(bit.band( temp1, 0x4000), 14 )==0x01 then
  840. log.info("被按下的有通道1")
  841. end
  842. if bit.rshift(bit.band( temp1, 0x2000), 13 )==0x01 then
  843. log.info("被按下的有通道2")
  844. end
  845. if bit.rshift(bit.band( temp1, 0x1000), 12 )==0x01 then
  846. log.info("被按下的有通道3")
  847. end
  848. if bit.rshift(bit.band( temp1, 0x800), 11 )==0x01 then
  849. log.info("被按下的有通道4")
  850. end
  851. if bit.rshift(bit.band( temp1, 0x400), 10 )==0x01 then
  852. log.info("被按下的有通道5")
  853. end
  854. if bit.rshift(bit.band( temp1, 0x200), 9 )==0x01 then
  855. log.info("被按下的有通道6")
  856. end
  857. if bit.rshift(bit.band( temp1, 0x100), 8 )==0x01 then
  858. log.info("被按下的有通道7")
  859. end
  860. if bit.rshift(bit.band( temp1, 0x80), 7 )==0x01 then
  861. log.info("被按下的有通道8")
  862. end
  863. if bit.rshift(bit.band( temp1, 0x40), 6 )==0x01 then
  864. log.info("被按下的有通道9")
  865. end
  866. if bit.rshift(bit.band( temp1, 0x20), 5 )==0x01 then
  867. log.info("被按下的有通道10")
  868. end
  869. if bit.rshift(bit.band( temp1, 0x10), 4 )==0x01 then
  870. log.info("被按下的有通道11")
  871. end
  872. sys.wait(200)
  873. end
  874. */
  875. static int l_sensor_sc12a(lua_State *L)
  876. {
  877. unsigned int sc12a_data = 0xffff;
  878. int sda = luaL_checkinteger(L, 1);
  879. int scl = luaL_checkinteger(L, 2);
  880. sc12a_data = read_sc12akey(sda,scl);
  881. sc12a_data =sc12a_data^0xffff;
  882. lua_pushinteger(L, sc12a_data);
  883. return 1;
  884. }
  885. /*
  886. 单总线命令读写YHM27XX
  887. @api sensor.yhm27xxx(pin, chip_id, reg, data)
  888. @int gpio端口号
  889. @int 芯片ID
  890. @int 寄存器地址
  891. @int 要写入的数据,如果没填,则表示从寄存器读取数据
  892. @return boolean 成功返回true,失败返回false
  893. @return int 读取成功返回寄存器值,写入成功无返回
  894. @usage
  895. while 1 do
  896. sys.wait(1000)
  897. local result, data = sensor.yhm27xxx(15, 0x04, 0x05)
  898. log.info("yhm27xxx", result, data)
  899. end
  900. */
  901. #ifdef LUAT_USE_YHM27XX
  902. static int l_sensor_yhm27xx(lua_State *L)
  903. {
  904. uint8_t pin = luaL_checkinteger(L, 1);
  905. uint8_t chip_id = luaL_checkinteger(L, 2);
  906. uint8_t reg = luaL_checkinteger(L, 3);
  907. uint8_t data = 0;
  908. uint8_t is_read = 1;
  909. if (!lua_isnone(L, 4))
  910. {
  911. is_read = 0;
  912. data = luaL_checkinteger(L, 4);
  913. }
  914. #ifdef LUAT_USE_DRV_GPIO
  915. if(luat_drv_gpio_driver_yhm27xx(pin, chip_id, reg, is_read, &data))
  916. #else
  917. if(luat_gpio_driver_yhm27xx(pin, chip_id, reg, is_read, &data))
  918. #endif
  919. {
  920. lua_pushboolean(L, 0);
  921. return 1;
  922. }
  923. lua_pushboolean(L, 1);
  924. if (is_read)
  925. {
  926. lua_pushinteger(L, data);
  927. return 2;
  928. }
  929. return 1;
  930. }
  931. #endif
  932. #include "rotable2.h"
  933. static const rotable_Reg_t reg_sensor[] =
  934. {
  935. {"w1_reset", ROREG_FUNC(l_w1_reset)},
  936. {"w1_connect", ROREG_FUNC(l_w1_connect)},
  937. {"w1_write", ROREG_FUNC(l_w1_write_byte)},
  938. {"w1_read", ROREG_FUNC(l_w1_read_byte)},
  939. {"ds18b20", ROREG_FUNC(l_sensor_ds18b20)},
  940. {"hx711", ROREG_FUNC(l_sensor_hx711)},
  941. {"cs1237", ROREG_FUNC(l_sensor_cs1237)},
  942. {"ws2812b", ROREG_FUNC(l_sensor_ws2812b)},
  943. {"dht1x", ROREG_FUNC(dht1x_read)},
  944. {"sc12a", ROREG_FUNC(l_sensor_sc12a)},
  945. #ifdef LUAT_USE_PWM
  946. {"ws2812b_pwm", ROREG_FUNC(l_sensor_ws2812b_pwm)},
  947. #endif
  948. #ifdef LUAT_USE_SPI
  949. {"ws2812b_spi", ROREG_FUNC(l_sensor_ws2812b_spi)},
  950. #endif
  951. #ifdef LUAT_USE_YHM27XX
  952. {"yhm27xx", ROREG_FUNC(l_sensor_yhm27xx)},
  953. #endif
  954. {NULL, ROREG_INT(0) }
  955. };
  956. LUAMOD_API int luaopen_sensor(lua_State *L)
  957. {
  958. luat_newlib2(L, reg_sensor);
  959. return 1;
  960. }
  961. #endif