查看: 1387|回复: 5

Arduino获得心率带数据

[复制链接]

该用户从未签到

发表于 2019-2-7 20:58 | 显示全部楼层 |阅读模式
本帖最后由 Zoologist 于 2019-2-7 21:15 编辑

目前市面上能够测量心率的设备很多。有腕带腕表式的,也有夹在耳朵或者手指末端的。从准确性上来说,腕带式的容易松动因此没有胸带式的准确。同时,胸带式的对于运动统计来说也是最好的选择。
前一段入手了三根心率带和一个接收模块。其中的心率带是带有编码的,因此在接收端可以很容易的区分数据来源。当然,与之对应的还有不带编码的心率带,无法在多个的情况下使用。
先说说心率带模块:
1.     内部使用 CR2032 纽扣电池,据说每天工作1小时可以撑9个月;
2.     发送频率为 2.4Ghz;
3.     平时处于睡眠模式,戴上之后才开始发送数据
4.     发射数据每次 4 Bytes,3 BytesID+ 1 Byte 心率。
接收模块:
1.     模块三个引脚,GND  VCC (特别强调是 3.3V供电) TX 。使用串口通讯。波特率 9600 bps。比如:DD 20 03 04 50(个人感觉有点低,设想如果很多根在同一个空间内使用不知道会有什么问题);
2.     上面有一个LED,当收到有效数据后会闪动一次;
3.     板子上的孔间距是 2.0mm 不是 2.54,使用杜邦线会很别扭,我直接焊接上导线来使用;
image001.png

下面是一个完整的例子,使用 Arduino Leonardo 接收数据,将收到的数据总结为 A + 每分钟心跳数(bpm),或者  B +每分钟心跳数上传到USB串口,然后在上位机上显示出来。试验中使用的心率带心率带A  ID 22 05 28   心率带 B ID 22 06 58
1.     Arduino代码

kittenblock中小学创客名师推荐的图形化编程软件

void setup() {

  Serial.begin(9600);

  Serial1.begin(9600);

}

 

boolean status1=false;

boolean status2=false;

boolean status3=false;

byte    addr[3];

byte    pos=0;

char    outadd;

void loop() {

  byte c;

  while (Serial1.available())

   {

      c=Serial1.read()&0xFF;

           Serial.write(c);

      if ((status1==false)&&(c==0xdd)) {

            status1=true;

            status2=true;

        //         Serial.print("st1");

        }

      else if (status2) {

            addr[pos]=c;

            pos++;

            if (pos==3) {

                 status2=false;

                 status3=true;  

              }

          //  Serial.print("st2"); 

        }

      else if (status3) {

              //Serial.print("st3");

              if ((addr[0]==0x22)&&(addr[1]==0x05)&&(addr[2]==0x28)) {

                 Serial.write('A');

                 Serial.write(c);

                 Serial.println("");

               }

              else

              if ((addr[0]==0x22)&&(addr[1]==0x06)&&(addr[2]==0x58)) {

                 Serial.write('B');

                 Serial.write(c);

                 Serial.println("");

               }

             status1=false;

             status2=false;

             status3=false;

             pos=0; 

     }  

   } //while

 

}

 

C# 编写上位机程序,在界面上绘制当前心率曲线

完整代码

kittenblock中小学创客名师推荐的图形化编程软件

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace WindowsFormsApplication9
{
    public partial class Form1 : Form
    {
        private Queue<double> dataQueue = new Queue<double>(100);
        private Queue<double> dataQueue2 = new Queue<double>(100);

        private int num = 5;//每次删除增加几个点
        private int heartA;
        private int heartB;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //textBox1.AppendText("start");
            Form2 f2 = new Form2();
            f2.ShowDialog();
            serialPort1.PortName = "COM" + f2.SelectedPort.ToString();
           // MessageBox.Show(f2.SelectedPort.ToString());
            button3.Enabled = true;
            button4.Enabled = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //设置窗体为无边框样式
            this.FormBorderStyle = FormBorderStyle.None;
            //最大化窗体    
            this.WindowState = FormWindowState.Maximized;     

            InitChart();
            chart1.Width = this.Width - 20;
            chart1.Height = this.Height - 100;
            button3.Enabled = false;
            button4.Enabled = false;

            //如果没有这句话,串口收到的只有0-128 的 ASCII
            serialPort1.Encoding = System.Text.Encoding.GetEncoding(28591);
            serialPort1.DtrEnable = true;
            serialPort1.RtsEnable = true;
        }

        /// <summary>
        /// 初始化图表
        /// </summary>
        private void InitChart()
        {
            //定义图表区域
            this.chart1.ChartAreas.Clear();
            ChartArea chartArea1 = new ChartArea("C1");
            this.chart1.ChartAreas.Add(chartArea1);
            //定义存储和显示点的容器
            this.chart1.Series.Clear();
            Series series1 = new Series("S1");
            series1.ChartArea = "C1";
            this.chart1.Series.Add(series1);

            Series series2 = new Series("S2");
            this.chart1.Series.Add(series2);
            //设置图表显示样式
            this.chart1.ChartAreas[0].AxisY.Minimum = 50;
            this.chart1.ChartAreas[0].AxisY.Maximum = 170;
            this.chart1.ChartAreas[0].AxisY.Interval = 10;
            this.chart1.ChartAreas[0].AxisX.Interval = 5;
            this.chart1.ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver;
            this.chart1.ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver;
            //设置标题
            this.chart1.Titles.Clear();
            this.chart1.Titles.Add("Red");
            this.chart1.Titles[0].Text = "Heart";
            this.chart1.Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
            this.chart1.Titles[0].ForeColor = Color.Red;
            //设置图表显示样式
            this.chart1.Series[0].Color = Color.Red;
            this.chart1.Series[0].ChartType = SeriesChartType.Line;
            this.chart1.Series[0].Points.Clear();

            this.chart1.Series[1].Color = Color.Blue;
            this.chart1.Series[1].ChartType = SeriesChartType.Line;

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            UpdateQueueValue();
            this.chart1.Series[0].Points.Clear();
            this.chart1.Series[1].Points.Clear();
            for (int i = 0; i < dataQueue.Count; i++)
            {
                this.chart1.Series[0].Points.AddXY((i + 1), dataQueue.ElementAt(i));
                this.chart1.Series[1].Points.AddXY((i + 1), dataQueue2.ElementAt(i));
            }
        }

        //更新队列中的值
        private void UpdateQueueValue()
        {
            int heart=0;
            if (dataQueue.Count >= 100)
            {
                //先出列
                for (int i = 0; i < num; i++)
                {
                    dataQueue.Dequeue();
                    dataQueue2.Dequeue();
                }
            }

                //Random r = new Random();
                for (int i = 0; i < num; i++)
                {
                    //heart = r.Next(50, 170);
                    dataQueue.Enqueue(heartA);
                    //heart = r.Next(50, 170);
                    dataQueue2.Enqueue(heartB);
                }

                chart1.Titles[0].Text = "Heart"+ heart.ToString();

        }

        private void button3_Click(object sender, EventArgs e)
        {
            this.serialPort1.Open();
            this.timer1.Enabled = true;
            this.timer2.Enabled = true;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            this.timer1.Enabled = false;
            this.timer2.Enabled = false;
            serialPort1.Close();
            this.timer1.Stop();
            this.timer2.Stop();
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {

        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            if (serialPort1.BytesToRead!=0) {
                
                String s=serialPort1.ReadLine();
                if (s.Length>=2) { 
                if (s[0] == 'A') {
                        heartA = s[1]; // Convert.ToInt32(s[1]);
                    textBox1.AppendText(heartA.ToString());
                }
                else
                    if (s[0] == 'B')
                      {
                        heartB = s[1];
                        //textBox1.AppendText(heartB.ToString("X2"));
                }
                }
            }
        }
    }
}



运行结果:

image004.jpg






该用户从未签到

发表于 2019-2-27 15:50 | 显示全部楼层
楼主,我最近也在弄串口,我做的是通过串口接收一个二维数组,想问下你的数据是一位一位传的吗,我想传输比如AAA保存在V[0][0-2],然后传输BBB保存在v[1][0-2],一直没弄对,想问下有什么好的建议。

该用户从未签到

发表于 2019-2-27 16:05 | 显示全部楼层
谢谢分享,根据你的状态机的思路完成了二维数组的输入保存

点评

不错  发表于 2019-2-27 16:34

该用户从未签到

发表于 2019-9-16 11:13 | 显示全部楼层
想知道楼主入手了三根心率带和一个接收模块的类型  谢谢楼主

该用户从未签到

 楼主| 发表于 2019-9-16 13:08 | 显示全部楼层
Liao13996137263 发表于 2019-9-16 11:13
想知道楼主入手了三根心率带和一个接收模块的类型  谢谢楼主

https://shop572006360.taobao.com ... umber_id=3431146879

这个店铺买的
您需要登录后才可以回帖 登录 | 立即注册  

本版积分规则

热门推荐

Blynk与m5stack basic以及uiflow的交互玩法
Blynk与m5stack basic以及
Blynk与m5stack basic以及uiflow的交互玩法 [准备工作我们假设玩家已经熟悉下面的准备
求助oled显示屏 中间有一条不显示 折腾好久没明白是咋回事
求助oled显示屏 中间有一
以下是源代码,课程做东西需要,卡在了这一环节,求大神指教(跪 #include #i
中文 字库 的8针 OLED 12864模块 arduino
中文 字库 的8针 OLED 128
屏幕电路SPI连线: 中文字库OLED Arduino UNO GND GND
DIY X-Y 平面激光器
DIY X-Y 平面激光器
DIY X-Y 平面激光器 总成本不到50元,性能一点不比市面的差. Arduino UNO x1 舵机 x2
【干货分享】mega2560原理图PCB图纸altium designer18
【干货分享】mega2560原理
分享一下mega2560的板子 AD版本 **** 本内容被作者隐藏 **** ergo
Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
快速回复 返回顶部 返回列表