luat_lib_max30102.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. @module max30102
  3. @summary 红外测温(MAX30102)
  4. @version 1.0
  5. @date 2023.2.28
  6. @tag LUAT_USE_MAX30102
  7. */
  8. #include "luat_base.h"
  9. #include "luat_malloc.h"
  10. #include "luat_timer.h"
  11. #include "luat_gpio.h"
  12. #include "luat_rtos.h"
  13. #include "MAX30102.h"
  14. #include "algorithm.h"
  15. #define LUAT_LOG_TAG "max30102"
  16. #include "luat_log.h"
  17. uint8_t max30102_i2c_id;
  18. static uint8_t max30102_int;
  19. static uint64_t max30102_idp;
  20. #define MAX30102_CHIP_ID 0x15
  21. #define SAMP_BUFF_LEN 1000
  22. #define AVG_BUFF_LEN 37
  23. /*
  24. 初始化MAX30102传感器
  25. @api MAX30102.init(i2c_id,int)
  26. @int 传感器所在的i2c总线id,默认为0
  27. @int int引脚
  28. @return bool 成功返回true, 否则返回nil或者false
  29. @usage
  30. if max30102.init(0,pin.PC05) then
  31. log.info("max30102", "init ok")
  32. else
  33. log.info("max30102", "init fail")
  34. end
  35. */
  36. static int l_max30102_init(lua_State *L){
  37. uint8_t cmd,uch_dummy;
  38. max30102_i2c_id = luaL_optinteger(L, 1 , 0);
  39. max30102_int = luaL_checkinteger(L, 2);
  40. maxim_max30102_read_reg(REG_PART_ID, &cmd);
  41. if (cmd == MAX30102_CHIP_ID){
  42. luat_gpio_mode(max30102_int,LUAT_GPIO_INPUT, LUAT_GPIO_PULLUP, LUAT_GPIO_HIGH);
  43. maxim_max30102_reset();
  44. luat_timer_mdelay(20);
  45. maxim_max30102_read_reg(REG_INTR_STATUS_1,&uch_dummy);
  46. maxim_max30102_init(); //initializes the MAX30102
  47. luat_timer_mdelay(20);
  48. lua_pushboolean(L, 1);
  49. return 1;
  50. }
  51. return 0;
  52. }
  53. luat_rtos_task_handle max30102_task_handle = NULL;
  54. static int32_t l_max30102_callback(lua_State *L, void* ptr){
  55. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  56. lua_pushboolean(L, 1);
  57. lua_pushinteger(L, msg->arg1);
  58. lua_pushinteger(L, msg->arg2);
  59. luat_cbcwait(L, max30102_idp, 3);
  60. max30102_idp = 0;
  61. return 0;
  62. }
  63. void max30102_task(void *param){
  64. uint64_t red_sum = 0, ir_sum = 0;
  65. uint8_t red_avg_len = 0,ir_avg_len = 0;
  66. int32_t red_min = 0x3FFFF, red_max = 0,ir_min = 0x3FFFF, ir_max = 0, HR = 0,SpO2 = 0;
  67. uint32_t* samples_buffer = luat_heap_malloc(sizeof(uint32_t) * SAMP_BUFF_LEN * 2);
  68. if (samples_buffer == NULL) {
  69. LLOGE("out of memory");
  70. return;
  71. }
  72. int32_t* avg_buffer = luat_heap_malloc(sizeof(int32_t) * AVG_BUFF_LEN * 2);
  73. if (avg_buffer == NULL) {
  74. LLOGE("out of memory");
  75. luat_heap_free(samples_buffer);
  76. return;
  77. }
  78. for(size_t i=0;i<SAMP_BUFF_LEN;i++){
  79. while(luat_gpio_get(max30102_int) == 1){luat_timer_mdelay(1);} //wait until the interrupt pin asserts
  80. maxim_max30102_read_fifo((samples_buffer+i), (samples_buffer+SAMP_BUFF_LEN+i)); //read from MAX30102 FIFO
  81. }
  82. for (size_t i = 0; i < AVG_BUFF_LEN; i++){
  83. int32_t sp02,heart;
  84. int8_t spo2_valid = 0,heart_valid = 0;
  85. maxim_heart_rate_and_oxygen_saturation(samples_buffer+SAMP_BUFF_LEN+i*25, 100, samples_buffer+i*25, &sp02, &spo2_valid, &heart, &heart_valid);
  86. if (heart_valid == 1 && heart > 30 && heart < 150){
  87. avg_buffer[red_avg_len] = heart;
  88. red_avg_len++;
  89. if (heart<red_min) red_min = heart;
  90. if (heart>red_max) red_max = heart;
  91. red_sum += heart;
  92. }
  93. if (spo2_valid == 1 && sp02 > 90 && sp02 < 100){
  94. avg_buffer[ir_avg_len + AVG_BUFF_LEN] = sp02;
  95. ir_avg_len++;
  96. if (sp02<ir_min) ir_min = sp02;
  97. if (sp02>ir_max) ir_max = sp02;
  98. ir_sum += sp02;
  99. }
  100. }
  101. if (red_avg_len){
  102. HR = (red_sum - red_min - red_max) / (red_avg_len-2);
  103. }
  104. if (ir_avg_len){
  105. SpO2 = (ir_sum - ir_min - ir_max) / (ir_avg_len-2);
  106. }
  107. luat_heap_free(samples_buffer);
  108. luat_heap_free(avg_buffer);
  109. if (HR!=0 && SpO2!=0){
  110. rtos_msg_t msg = {
  111. .handler = l_max30102_callback,
  112. .arg1 = HR,
  113. .arg2 = SpO2
  114. };
  115. luat_msgbus_put(&msg, 0);
  116. }else{
  117. luat_cbcwait_noarg(max30102_idp);
  118. max30102_idp = 0;
  119. }
  120. luat_rtos_task_delete(max30102_task_handle);
  121. }
  122. /*
  123. 获取心率血氧(大概需要10s时间测量)
  124. @api max30102.get().wait()
  125. @return bool 成功返回true, 否则返回nil或者false
  126. @return number 心率
  127. @return number 血氧
  128. */
  129. static int l_max30102_get(lua_State *L) {
  130. if (max30102_idp){
  131. lua_pushboolean(L, 0);
  132. luat_pushcwait_error(L,1);
  133. }else{
  134. max30102_idp = luat_pushcwait(L);
  135. luat_rtos_task_create(&max30102_task_handle, 1024, 50, "max30102", max30102_task, NULL, 0);
  136. }
  137. return 1;
  138. }
  139. // /*
  140. // 获取max30102温度
  141. // @api max30102.temp()
  142. // @return number 温度
  143. // */
  144. // static int l_max30102_temp(lua_State *L) {
  145. // int8_t temp_intr,temp_frac;
  146. // float temp;
  147. // maxim_max30102_read_reg(REG_TEMP_INTR, &temp_intr);
  148. // maxim_max30102_read_reg(REG_TEMP_FRAC, &temp_frac);
  149. // LLOGD("l_max30102_temp %d %d",temp_intr,temp_frac);
  150. // temp = temp_intr + temp_frac * 0.0625;
  151. // lua_pushnumber(L, temp);
  152. // return 1;
  153. // }
  154. /*
  155. 关闭max30102
  156. @api max30102.shutdown()
  157. */
  158. static int l_max30102_shutdown(lua_State *L) {
  159. maxim_max30102_shutdown();
  160. return 0;
  161. }
  162. #include "rotable2.h"
  163. static const rotable_Reg_t reg_max30102[] =
  164. {
  165. {"init", ROREG_FUNC(l_max30102_init)},
  166. {"get", ROREG_FUNC(l_max30102_get)},
  167. // {"temp", ROREG_FUNC(l_max30102_temp)},
  168. {"shutdown", ROREG_FUNC(l_max30102_shutdown)},
  169. { NULL, ROREG_INT(0) }
  170. };
  171. LUAMOD_API int luaopen_max30102( lua_State *L ) {
  172. luat_newlib2(L, reg_max30102);
  173. return 1;
  174. }