14322|17

217

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

【TI首届低功耗设计大赛】心率及脉搏信号采集及显示 [复制链接]

 
前言:通过断断续续的学习MSP340FR5969,发现这款金刚狼芯片具有很多与众不同的特性,尤其是在低功耗特性方面表现突出,比较适合用于可穿戴设备及无线传感器方面。经过几天的摸索,实现利用反射式光电容积描记传感器来采集和显示人体脉搏信号并计算出心率数值。
一、硬件组成
硬件上使用MSP340FR5969 launchpad作为主控板,完成脉搏模拟量定时采集,并将计算后的心率值和数字化的脉搏值通过串口发送到上位机显示。
此外,脉搏传感器使用购买的Pulse sensor心率传感器,该传感器使用绿光反射来探测皮肤表层血液流动,从而得到脉搏波形。传感器只有三个引脚,分别为signal out,VCC,GND。电源为3.3V和5v均可,传感器将接收到的光电路信号转化为电压信号,经过滤波放大后输出,所以输出为模拟信号。
pulse sensor模块:

硬件系统组成:

连线顺序为:
puslesensor-msp430
sigout->A10
vcc->3.6V
gnd->gnd
二、编译软件Energia
一般可使用IAR ,CCS等软件对MSP430进行编程,但是在MSP430FR5969 Launchpad开发板的说明书上看到有一种免费开源的软件Energia,其使用非常类似于arduino平台,容易上手,对于想在不过多了解底层寄存器的情况下快速开发应用是非常适合的。
目前支持MSP430FR5969 Launchpad开发板的是Energia 0101E0013版。但是在开始使用该软件时会出现一个问题,就是当你准备下载程序时,会提示你升级编程器,如下图:

当时当你升级的时候,又会提示设备连接失败。通过上网寻找发现已经有网友解决了这个问题,关键在于Energia内部的MSP430.DLL版本太旧,具体操作可查看原帖:http://bbs.ednchina.com/BLOG_ARTICLE_3024874.HTM
更新之后Energia软件就可以正常使用了。针对原来Pulse sensor在arduino下的程序进行移植,程序上主要需要一个AD口采样,一个定时器中断来实现固定间隔采样(大约500HZ),还有一个串口(波特率115200)来实现数据上传。在实验过程中发现,energia软件还是存在一些问题,相比arduino来说不够完善,定时器并没有提供接口出来使用,最后在外国专业的430h论坛上提问,有老外提供了一个RTC_B的库文件,该文件可提供一个周期性中断功能,才最终实现了整个程序,程序如下:

  1. /*
  2. >> Pulse Sensor Amped 1.2 <<
  3. This code is for Pulse Sensor Amped by Joel Murphy and Yury Gitman
  4.     www.pulsesensor.com
  5.     >>> Pulse Sensor purple wire goes to Analog Pin 10 <<<
  6. Pulse Sensor sample aquisition and processing happens in the background via Timer 2 interrupt. 2mS sample rate.
  7. PWM on pins 3 and 11 will not work when using this code, because we are using Timer 2!
  8. The following variables are automatically updated:
  9. Signal :    int that holds the analog signal data straight from the sensor. updated every 2mS.
  10. IBI  :      int that holds the time interval between beats. 2mS resolution.
  11. BPM  :      int that holds the heart rate value, derived every beat, from averaging previous 10 IBI values.
  12. QS  :       boolean that is made true whenever Pulse is found and BPM is updated. User must reset.
  13. Pulse :     boolean that is true when a heartbeat is sensed then false in time with pin13 LED going out.

  14. This code is designed with output serial data to Processing sketch "PulseSensorAmped_Processing-xx"
  15. The Processing sketch is a simple data visualizer.
  16. All the work to find the heartbeat and determine the heartrate happens in the code below.
  17. Pin 13 LED will blink with heartbeat.
  18. If you want to use pin 13 for something else, adjust the interrupt handler
  19. It will also fade an LED on pin fadePin with every beat. Put an LED and series resistor from fadePin to GND.
  20. Check here for detailed code walkthrough:
  21. http://pulsesensor.myshopify.com/pages/pulse-sensor-amped-arduino-v1dot1

  22. Code Version 1.2 by Joel Murphy & Yury Gitman  Spring 2013
  23. This update fixes the firstBeat and secondBeat flag usage so that realistic BPM is reported.

  24. */

  25. #include <RTC_B.h>
  26. //  VARIABLES
  27. int pulsePin = A10;                 // Pulse Sensor purple wire connected to analog pin A10
  28. int blinkPin = RED_LED;                // pin to blink led at each beat,pin P4.6
  29. int fadePin = GREEN_LED;                  // pin to do fancy classy fading blink at each beat,pin P1.0
  30. int fadeRate = 0;                 // used to fade LED on with PWM on fadePin


  31. // these variables are volatile because they are used during the interrupt service routine!
  32. volatile int BPM;                   // used to hold the pulse rate
  33. volatile int Signal;                // holds the incoming raw data
  34. volatile int IBI = 600;             // holds the time between beats, must be seeded!
  35. volatile boolean Pulse = false;     // true when pulse wave is high, false when it's low
  36. volatile boolean QS = false;        // becomes true when Arduoino finds a beat.

  37. volatile int rate[10];                    // array to hold last ten IBI values
  38. volatile unsigned long sampleCounter = 0;          // used to determine pulse timing
  39. volatile unsigned long lastBeatTime = 0;           // used to find IBI
  40. volatile int Peak =512;                      // used to find peak in pulse wave, seeded
  41. volatile int Trough = 512;                     // used to find trough in pulse wave, seeded
  42. volatile int thresh = 512;                // used to find instant moment of heart beat, seeded
  43. volatile int amp = 100;                   // used to hold amplitude of pulse waveform, seeded
  44. volatile boolean firstBeat = true;        // used to seed rate array so we startup with reasonable BPM
  45. volatile boolean secondBeat = false;      // used to seed rate array so we startup with reasonable BPM

  46. void setup(){
  47.   boolean t;
  48.   pinMode(blinkPin,OUTPUT);         // pin that will blink to your heartbeat!
  49.   pinMode(fadePin,OUTPUT);          // pin that will fade to your heartbeat!
  50.   Serial.begin(115200);             // we agree to talk fast!
  51.   rtc.begin();                 // sets up to the RTC_B
  52.   t = rtc.attachPeriodicInterrupt(512,timer_do);  // Runs RTC_ISR() every 1/512 Second
  53.   if (!t) {
  54.     Serial.println("ERROR: Could not register a 2ms Periodic Interrupt!");
  55.   }
  56.    // UN-COMMENT THE NEXT LINE IF YOU ARE POWERING The Pulse Sensor AT LOW VOLTAGE,
  57.    // AND APPLY THAT VOLTAGE TO THE A-REF PIN
  58.    //analogReference(EXTERNAL);   
  59. }



  60. void loop(){
  61.   sendDataToProcessing('S', Signal);     // send Processing the raw Pulse Sensor data
  62.   if (QS == true){                       // Quantified Self flag is true when arduino finds a heartbeat
  63.         fadeRate = 255;                  // Set 'fadeRate' Variable to 255 to fade LED with pulse
  64.         sendDataToProcessing('B',BPM);   // send heart rate with a 'B' prefix
  65.         sendDataToProcessing('Q',IBI);   // send time between beats with a 'Q' prefix
  66.         QS = false;                      // reset the Quantified Self flag for next time   
  67.      }
  68.   
  69.   ledFadeToBeat();
  70.   
  71.   delay(20);                             //  take a break
  72. }


  73. void ledFadeToBeat(){
  74.     fadeRate -= 15;                         //  set LED fade value
  75.     fadeRate = constrain(fadeRate,0,255);   //  keep LED fade value from going into negative numbers!
  76.     analogWrite(fadePin,fadeRate);          //  fade LED
  77.   }


  78. void sendDataToProcessing(char symbol, int data ){
  79.     Serial.print(symbol);                // symbol prefix tells Processing what type of data is coming
  80.     Serial.println(data);                // the data to send culminating in a carriage return
  81.   }

  82. // THIS IS THE TIMER 2 INTERRUPT SERVICE ROUTINE.
  83. // Timer 2 makes sure that we take a reading every 2 miliseconds
  84. void timer_do(){                        // triggered when Timer2 counts to 124
  85.   noInterrupts();                                      // disable interrupts while we do this
  86.   Signal = analogRead(pulsePin)>>2;              // read the Pulse Sensor,10-bit solution
  87.   sampleCounter += 2;                         // keep track of the time in mS with this variable
  88.   int Num = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise

  89.     //  find the peak and trough of the pulse wave
  90.   if(Signal < thresh && Num > (IBI/5)*3){       // avoid dichrotic noise by waiting 3/5 of last IBI
  91.     if (Signal < Trough){                        // T is the trough
  92.       Trough = Signal;                         // keep track of lowest point in pulse wave
  93.     }
  94.   }

  95.   if(Signal > thresh && Signal > Peak){          // thresh condition helps avoid noise
  96.     Peak = Signal;                             // P is the peak
  97.   }                                        // keep track of highest point in pulse wave

  98.   //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
  99.   // signal surges up in value every time there is a pulse
  100.   if (Num > 250){                                   // avoid high frequency noise
  101.     if ( (Signal > thresh) && (Pulse == false) && (Num > (IBI/5)*3) ){        
  102.       Pulse = true;                               // set the Pulse flag when we think there is a pulse
  103.       digitalWrite(blinkPin,HIGH);                // turn on pin 13 LED
  104.       IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
  105.       lastBeatTime = sampleCounter;               // keep track of time for next pulse

  106.       if(secondBeat){                        // if this is the second beat, if secondBeat == TRUE
  107.         secondBeat = false;                  // clear secondBeat flag
  108.         for(int i=0; i<=9; i++){             // seed the running total to get a realisitic BPM at startup
  109.           rate[i] = IBI;                     
  110.         }
  111.       }

  112.       if(firstBeat){                         // if it's the first time we found a beat, if firstBeat == TRUE
  113.         firstBeat = false;                   // clear firstBeat flag
  114.         secondBeat = true;                   // set the second beat flag
  115.         interrupts();                               // enable interrupts again
  116.         return;                              // IBI value is unreliable so discard it
  117.       }   


  118.       // keep a running total of the last 10 IBI values
  119.       word runningTotal = 0;                  // clear the runningTotal variable   

  120.       for(int i=0; i<=8; i++){                // shift data in the rate array
  121.         rate[i] = rate[i+1];                  // and drop the oldest IBI value
  122.         runningTotal += rate[i];              // add up the 9 oldest IBI values
  123.       }

  124.       rate[9] = IBI;                          // add the latest IBI to the rate array
  125.       runningTotal += rate[9];                // add the latest IBI to runningTotal
  126.       runningTotal /= 10;                     // average the last 10 IBI values
  127.       BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
  128.       QS = true;                              // set Quantified Self flag
  129.       // QS FLAG IS NOT CLEARED INSIDE THIS ISR
  130.     }                       
  131.   }

  132.   if (Signal < thresh && Pulse == true){   // when the values are going down, the beat is over
  133.     digitalWrite(blinkPin,LOW);            // turn off pin 13 LED
  134.     Pulse = false;                         // reset the Pulse flag so we can do it again
  135.     amp = Peak - Trough;                           // get amplitude of the pulse wave
  136.     thresh = amp/2 + Trough;                    // set thresh at 50% of the amplitude
  137.     Peak = thresh;                            // reset these for next time
  138.     Trough = thresh;
  139.   }

  140.   if (Num > 2500){                           // if 2.5 seconds go by without a beat
  141.     thresh = 512;                          // set thresh default
  142.     Peak = 512;                               // set P default
  143.     Trough = 512;                               // set T default
  144.     lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date        
  145.     firstBeat = true;                      // set these to avoid noise
  146.     secondBeat = false;                    // when we get the heartbeat back
  147.   }

  148.   interrupts();                                   // enable interrupts when youre done!
  149. }// end isr




复制代码
在开发板上使用了下方的红灯和绿灯来模拟心跳频率。
三,效果演示

利用Processing制作的上位机来显示脉搏波形和心率数值,最后附上上位机软件程序。 PulseSensorAmpd_Processing_1dot1.rar (17.79 KB, 下载次数: 119)

PulseSensorAmpd_Processing_1dot1.rar (17.79 KB, 下载次数: 119)

最新回复

我的传感器不知道为什么即使手离开了,还是会有波形,请问有人是这样的吗?怎么解决?  详情 回复 发表于 2017-4-8 17:14
 
点赞 关注(3)
个人签名心率传感器:https://shop108071095.taobao.com

回复
举报

3416

帖子

0

TA的资源

纯净的硅(高级)

沙发
 
这个小模块原厂还是蛮贵的,撸主的滤波可以再详细点吗?
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
ljj3166 发表于 2014-11-21 09:47
这个小模块原厂还是蛮贵的,撸主的滤波可以再详细点吗?

淘宝上国内仿制的很多了,价钱也便宜很多了。
关于具体的滤波原理,可以参考原帖:http://pulsesensor.myshopify.com ... mped-arduino-v1dot1,里面写的很详细了。
 
个人签名心率传感器:https://shop108071095.taobao.com
 
 

回复

973

帖子

15

TA的资源

纯净的硅(高级)

4
 
想 问 下 楼 主 , 这 个 传 感 器 多 少 钱 。
                           
                                                        












                                    

点评

淘宝上有,搜“心率传感器“就可以了,我的那个78.  详情 回复 发表于 2014-11-24 22:40
 
个人签名我来到这个世界,就是为了遇见你。在某天我们会相遇,然后在一起,直到最后一起离去。
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

5
 
一个小白 发表于 2014-11-21 12:03
想 问 下 楼 主 , 这 个 传 感 器 多 少 钱 。
                           
                          ...

淘宝上有,搜“心率传感器“就可以了,我的那个78.

点评

略 贵 呀 。 效 果 如 何 , 好 用 吗 ?  详情 回复 发表于 2014-11-25 00:13
 
个人签名心率传感器:https://shop108071095.taobao.com
 
 

回复

973

帖子

15

TA的资源

纯净的硅(高级)

6
 
anning865 发表于 2014-11-24 22:40
淘宝上有,搜“心率传感器“就可以了,我的那个78.

略 贵 呀 。
效 果 如 何 , 好 用 吗 ?
                                            


点评

资料比较全。现在已经降价了。  详情 回复 发表于 2014-11-25 21:09
 
个人签名我来到这个世界,就是为了遇见你。在某天我们会相遇,然后在一起,直到最后一起离去。
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

7
 
一个小白 发表于 2014-11-25 00:13
略 贵 呀 。
效 果 如 何 , 好 用 吗 ?

资料比较全。现在已经降价了。
 
个人签名心率传感器:https://shop108071095.taobao.com
 
 

回复

241

帖子

0

TA的资源

一粒金砂(高级)

8
 
mark一下,
 
 
 

回复

9

帖子

0

TA的资源

一粒金砂(初级)

9
 
在么? 请问 你还有pulsesensor 心率传感器的程序资料么 可以发我一份么

点评

开源的东西,资料一搜就出来了啊  详情 回复 发表于 2015-6-5 10:08
 
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

10
 
maswzd911 发表于 2015-6-2 22:20
在么? 请问 你还有pulsesensor 心率传感器的程序资料么 可以发我一份么

开源的东西,资料一搜就出来了啊
 
个人签名心率传感器:https://shop108071095.taobao.com
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

11
 
我用STM32 移植后 发现有时准 有时不准  求解  楼主的准吗?

 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

12
 
请问汤哥,cc3200怎么移植这个代码

点评

哪里来的汤哥?  详情 回复 发表于 2015-7-20 21:31
 
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

13
 
LIUQIU 发表于 2015-7-19 16:43
请问汤哥,cc3200怎么移植这个代码

哪里来的汤哥?
 
个人签名心率传感器:https://shop108071095.taobao.com
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

14
 
for(i=0; i<=9; i++){       rate[i] = IBI}这里的rate【0】到rate【9】都是一样的呢?,下边的runningTotal和BPM的计算
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

15
 
LIUQIU 发表于 2015-7-19 16:43
请问汤哥,cc3200怎么移植这个代码

请问是怎么移植的呢
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

16
 
为什么我测的时候 数值也会乱跳啊  而且数值也不准
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

17
 
我的传感器不知道为什么即使手离开了,还是会有波形,请问有人是这样的吗?怎么解决?

点评

肯定有波形啊,因为外界光干扰一直都存在的。这个不能从硬件上处理,要从软件上处理。  详情 回复 发表于 2017-4-17 13:33
 
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

18
 
猫猫莫甘娜 发表于 2017-4-8 17:14
我的传感器不知道为什么即使手离开了,还是会有波形,请问有人是这样的吗?怎么解决?

肯定有波形啊,因为外界光干扰一直都存在的。这个不能从硬件上处理,要从软件上处理。
 
个人签名心率传感器:https://shop108071095.taobao.com
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表