智能心率检测

操作系统 云服务/平台 技术难度 关注领域
RTOS Gizwits Cloud 中级 Healthcare,Sensors

 

任务目标

主要是将心率传感器连接到Gokit开发板提供的ADC接口以收集心率信息。 当心率值高于阈值时,LED灯亮起。

 

所需材料/所需清单/工具

  • BG96

  • Gokit4

  • Pluse Sensor

  • Led

  • Dupoint line

源码/示例/可执行的应用程序

  • Source Code

附加资料

  • 智能心率检测视频(网盘密码:6u5t​

搭建/在组装说明

使用的零件

以下是此项目中使用的项目。

1. windows7 台式机。

2. 脉搏传感器,用于收集心率信息。

3. led,当检测到的心率值超过设定的阈值时,点亮led。

4.杜邦线,用于连接其他组件作为电线。

5.示波器,示波器用于实时查看检测到的心率波形。

 

部署项目

1.根据demo需求,结合Gokit开发板板载资源,采购合适的器件。

2. 测试选购的器件是否可用。

3.搭建,调试硬件电路。

4.本地创建demo-Smart-Heart-rate-detector项目。

5. 移植相关源码。

6.开发心率计算的相关功能。

7.联调。

8.代码上传至github。

 

工作流程

现在让我们介绍一下demo-smart-heart-rate-detector的工作流程。

gagentMain---->sensorInit----->led_init---->Pulsesensor_init.

demo-Smart-Heart-rate-detector/main/main.c

void gagentMain(void)

{

     getFreeHeap();

     sensorInit();

     gizwitsInit();

     timer_init();

     timer_start();

}

 

GAgent调用了名为gagentMain的函数,GAgent的主要作用是数据转发,它是设备数据,云计算和应用程序端(APP)之间的数据交互桥梁。在函数sensorInit中,做一些传感器初始化。

 

void sensorInit(void)

{

     gizLog(LOG_INFO, "Sensor initialization ...\n");

     led_init();

     Pulsesensor_init();

}

 

void led_init()

{

     gizLog(LOG_INFO, "in led init...\n");

     led_gpio_config();

     led_on_off(false, led_red);

}

void Pulsesensor_init()

{

     qapi_Status_t status = QAPI_ERROR;

     const char *Channel_Name_ADC0 = ADC_INPUT_ADC0;

     qapi_Timer_Sleep(2, QAPI_TIMER_UNIT_SEC, true);

     status = adc_open_handle();  

     

if(status != QAPI_OK)

    {

         //IOT_DEBUG("Get ADC Handle ERROR!");

         gizLog(LOG_INFO,"adc open handle error...\n");

         return;

    }

     status = adc_get_properties(Channel_Name_ADC0, &Properties_ADC0);

    if(status != QAPI_OK)

    {

         //IOT_DEBUG("Get ADC channel-%s Configuration ERROR!", Channel_Name_ADC1);

         gizLog(LOG_INFO,"Get ADC channel-%s Configuration ERROR...\n", Channel_Name_ADC0);

         return;

    }

}

demo-Smart-Heart-rate-detector/driver/timer/timer.c

qapi_Status_t timer_init(void)      //init

{

           qapi_Status_t status = QAPI_OK;

            memset(&timer_def_attr, 0, sizeof(timer_def_attr));

     timer_def_attr.cb_type  = QAPI_TIMER_FUNC1_CB_TYPE;

     timer_def_attr.deferrable = false;

     timer_def_attr.sigs_func_ptr = timer1_handler;

     timer_def_attr.sigs_mask_data = 0x11;

     status = qapi_Timer_Def(&timer_handle, &timer_def_attr);

            return status;

}

qapi_Status_t timer_start(void)

{

    qapi_Status_t status = QAPI_OK;

    memset(&timer_set_attr, 0, sizeof(timer_set_attr));

     timer_set_attr.reload = 100;

     timer_set_attr.time = 10;

     timer_set_attr.unit = QAPI_TIMER_UNIT_MSEC;

     status = qapi_Timer_Set(timer_handle, &timer_set_attr);

            return status;

}

void timer1_handler(uint32_t data)         // timer callback

{

     static bool led_red_status = true;

     getHeartRateValue(&heartrate);            //get heartvalue

     if(!heartrate)                                           //no  value     

     {

         return;

     }

     else if(((heartrate > HEART_RATE_THRESHOLD_HIGH) || (heartrate < HEART_RATE_THRESHOLD_LOW)))   // value is not vaild

     {

         led_on_off(true, led_red);        //red on

         //led_on_off(led_red_status, led_red);     

         //led_red_status = !led_red_status;

     }

    else                           // value is vaild

     {

         led_on_off(false,led_red);      //red off

     }

}

demo-Smart-Heart-rate-detector/driver/plusensor/plusensor.c

uint8_t getHeartRateValue(uint32_t* heartrate )    //Algorithm implementation for calculating heart rate  

{

     gizLog(LOG_INFO,"in getHeartRateValue...\n");    

.......

     memset(&result, 0, sizeof(result));

     status = qapi_ADC_Read_Channel(adc_handle, &Properties_ADC0, &result);   // read the Pulse Sensor

            ........

     sampleCounter += 10;  // keep track of the time in mS with this variable

     Num = sampleCounter - lastBeatTime;    // monitor the time since the last beat to avoid noise

     //  find the peak and trough of the pulse wave

     if(Signal < thresh && Num > (IBI/5)*3)   // avoid dichrotic noise by waiting 3/5 of last IBI

     { 

         if(Signal < T)        // T is the trough 

         {                      

              T = Signal;                                                            // keep track of lowest point in pulse wave

              gizLog(LOG_INFO,"Find trough, T = %d\n", T);

         }

     }

     if(Signal > thresh && Signal > P)          // thresh condition helps avoid noise

     {         

         P = Signal;                             // P is the peak,keep track of highest point in pulse wave

         gizLog(LOG_INFO,"Find peak, P = %d\n", P);

     }                                       

     .....

     if (Num > 600)         

     {                                   // avoid high frequency noise 

         if ( (Signal > thresh) && (Pulse == false) && (Num > (IBI/5)*3) )

         {       

              Pulse = true;        // set the Pulse flag when we think there is a pulse

              IBI = sampleCounter - lastBeatTime;         // measure time 

between beats in mS

              lastBeatTime = sampleCounter;               // keep track of time for next pulse

              if(secondBeat)                       // if this is the second beat, if secondBeat == TRUE

              {                       

                   secondBeat = false;   // clear secondBeat flag

                   for(int i=0; i<=9; i++)

                   {            

                       rate[i] = IBI;     // seed the running total to get a realisitic BPM at startup                

                   }

              }

              if(firstBeat)           // if it's the first time we found a beat, if firstBeat == TRUE

              {                        

              firstBeat = false;          // clear firstBeat flag

              secondBeat = true;        // set the second beat flag

              return 0;                          // IBI value is unreliable so discard it

              }  

 

              // keep a running total of the last 10 IBI values

              runningTotal = 0;             // clear the runningTotal variable

              for(int i=0; i<=8; i++)

              {               

                   rate[i] = rate[i+1];           // shift data in the rate array                 

// and drop the oldest IBI value

                   runningTotal += rate[i];          // add up the 9 oldest IBI values

              }

              rate[9] = IBI;                                 // add the latest IBI to the rate array

              runningTotal += rate[9];                   // add the latest IBI to runningTotal

              runningTotal /= 10;                     // average the last 10 IBI values

              BPM = 60000/runningTotal;             // how many beats can fit into a minute? that's BPM!

              *heartrate = BPM;

              gizLog(LOG_INFO,"BPM = %d\n", *heartrate);

              QS = true;                                                  // set Quantified Self flag

               // QS FLAG IS NOT CLEARED INSIDE THIS ISR

         }                      

     }

 

     if (Signal < thresh && Pulse == true)

     {   // when the values are going down, the beat is over

         Pulse = false;                         // reset the Pulse flag so we can do it again

         amp = P - T;                           // get amplitude of the pulse wave

         thresh = amp/2 + T;                    // set thresh at 50% of the amplitude

         P = thresh;                            // reset these for next time

         T = thresh;

     }

     if (Num > 2500)

     {                           // if 2.5 seconds go by without a beat

         thresh = 512;                          // set thresh default

         P = 512;                               // set P default

         T = 512;                               // set T default

         lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date       

         firstBeat = true;                      // set these to avoid noise

         secondBeat = false;                    // when we get the heartbeat back

     }

}

1.从该github链接地址处下载代码。

2.编译代码并将镜像烧录到Gokit4开发工具包。

3.将心率传感器连接到Gokit开发板的ADC1通道。

4.将LED的一个引脚连接到开发板的D9引脚,另一个引脚连接到vcc。

5.打开示波器,调整到合适的档位,将心率传感器的脉冲信号输出引脚和GND连接到示波器。

6.USB数据线连接PC和Gokit开发板。

7.用手指触摸心率传感器的信号采集表面。

8.打开串口调试助手,可以实时查看采集到的数据。

9.当检测到的数据超过阈值时,可以看到LED点亮。

 

贡献者信息

姓名 公司

Zhen

sunzhen@thundersoft.com
Thundersoft

Rong

yangrong0925@thundersoft.com
Thundersoft

Jie

wangjie0508@thundersoft.com
Thundersoft

Kou

kouzw0723@thundersoft.com
Thundersoft

Eric

yansh0810@thundersoft.com
Thundersoft

>>浏览更多Qualcomm硬件案例:http://qualcomm.csdn.net/m/zone/qualcomm2016/project

Qualcomm 解决方案

 

高通 AI Hub

全新高通 AI Hub 包含预优化AI模型库,支持在搭载骁龙和高通平台的终端上进行无缝部署。
该模型库为开发者提供超过75个主流的AI和生成式AI模型,比如Whisper、ControlNet、Stable Diffusion和Baichuan-7B,可在不同执行环境(runtime)中打包,能够在不同形态终端中实现卓越的终端侧AI性能、降低内存占用并提升能效。所有模型均经过优化,以充分利用高通AI引擎内所有核心(NPU、CPU和GPU)的硬件加速能力,从而使推理速度提升4倍。

了解更多

SDK 下载

本版块下载 SDK,只需简单注册,就可轻松下载。