ESP32基于arduino开发的心跳体温检测系统(四)本地端系统整合

在前三篇文章了解了三个外接模块的使用方法之后,我们开始将三个模块整合起来。

头文件、宏定义与变量声明

头文件

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h> 
#include <Adafruit_MLX90614.h>
#include "stdlib.h"

宏定义

#define SCREEN_WIDTH 128 // OLED 屏幕宽, 单位像素点数
#define SCREEN_HEIGHT 64 // OLED 屏幕长, 单位像素点数
#define OLED_RESET     -1 // 重置引脚
#define pin 35 //心跳传感器引脚

变量声明

int counter = 0;//时间计数器
int Y[128];//屏幕横坐标缓存数组
int maxid=0;//后续心跳传感器使用
int second=0;//后续心跳传感器使用
double bpm;//每分钟心跳数
double Data[50];//来自心跳传感器的数据缓存
double temperature;//温度
//实例化SSD1306显示屏
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//实例化MLX90614传感器
Adafruit_MLX90614 mlx = Adafruit_MLX90614();

//这是一帧BMP格式的图片,可以在OLED上看看是什么
const uint8_t frame0 [] = {
 0x00,0x00,0x00,0x80,0x01,0x00,0xC0,0x00,0x00,0x60,0x02,0x00,0x30,0x01,0x00,0x90,
0x04,0x00,0x58,0x02,0x00,0x58,0x09,0x00,0x58,0x05,0x00,0x58,0x35,0x00,0x58,0x35,
0x00,0x58,0x05,0x00,0x58,0x09,0x00,0x58,0x02,0x00,0x90,0x04,0x00,0x30,0x01,0x00,
0x60,0x02,0x00,0xC0,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00
};

初始化函数

void setup() {
  Serial.begin(9600);
  //SSD1306配置
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  
  display.display();
  display.clearDisplay();
  //MLX90614配置
  mlx.begin();  

  for(int i=0;i<128;i++)
  {
    Y[i]=0;  
  }

  pinMode( pin, INPUT);//设置管脚为输入

}

循环体函数

void loop() {

  temperature=mlx.readObjectTempC();
  
   for(int j=0;j<50;j++)
  {
    Data[j]=analogRead(pin);
    delay(10);
  }
  for(int j=0;j<50;j++)
  {
    if(Data[j]>Data[maxid])
    {
      maxid=j;
    }
  }
  for(int j=0;j<50;j++)
  {
    if(Data[j]>Data[second]&&Data[j]<=Data[maxid]&&abs(j-maxid)>5)
    {
      second=j;
    }
  }
  if((maxid-second!=0)&&(3000/abs(maxid-second)<200))
    bpm=3000/abs(maxid-second);
  else
    bpm=bpm;
  
  Serial.println(Data[0]);
  for(int i=31;i>0;i--)
  {
    Y[i]=Y[i-1];
    Y[0]=bpm-70;//64*(Data[0]-2700)/(100);
  }
  

  display.clearDisplay();
    //display.drawString(0,0, "Counter: " + String(counter));
  display.drawLine(96,0,96,64,SSD1306_WHITE);//y
  display.drawLine(0,32,96,32,SSD1306_WHITE);
  display.drawLine(96,45,128,45,SSD1306_WHITE);
  //x坐标轴绘制
  for(int i=0;i<96;i++)
  {
    int count=i/4;
    int res=i%4;
    if(res==0)
    {
    display.drawLine(i,Y[count],i+4,Y[count+1],SSD1306_WHITE);//画线
    }
    else
    {
    
    }
  }
  display.setTextSize(1);
  display.setTextColor(WHITE);
 
  display.setCursor(100,5);
  display.println(int(temperature));
  
  display.setCursor(115,1);
  display.println("o");
 
  display.setCursor(120,5);
  display.println("C");
  
  display.setCursor(100,22);
  display.println(int(bpm));

  display.setCursor(100,30);
  display.println("BPM");
  
  //if (Blynk.getstate())
  {
    display.drawBitmap(105,48,frame0,16,16,SSD1306_WHITE);
  }
  display.fillCircle(counter,32,2,SSD1306_WHITE);
  display.display();
  

  if(counter<96)
  {
    counter=counter+4;
  }
  else
  {
    counter=0;
    }
  delay(200);

}

下面针对循环体函数进行简单的说明:

temperature=mlx.readObjectTempC();
  
   for(int j=0;j<50;j++)
  {
    Data[j]=analogRead(pin);
    delay(10);
  }

这几行是从传感器端读取数据。温度传感器由于使用了库函数,所以读出来的temperature值为摄氏度数值,这个很方便。
而心跳传感器就比较麻烦了,在此处,心跳传感器的读出值为电压。在此略带提一下心跳传感器的工作原理。本质上它是一个光电传感器,通过指尖脉搏时光通过率的不同,输出不同电压,进而计算出脉搏数。由于没有合适的库,计算的过程只能我们自己来了。
计算的思想很简单,我们先读取若干个数据,从这些数据里找出两个电压最大值,这两个最大值就对应着心脏收缩的最大时刻输出电压,然后求得这两个电压最大值之间的时间间隔,从而可以计算出脉搏频率。
下面是计算过程:

  for(int j=0;j<50;j++)
  {
    if(Data[j]>Data[maxid])
    {
      maxid=j;
    }
  }
  for(int j=0;j<50;j++)
  {
    if(Data[j]>Data[second]&&Data[j]<=Data[maxid]&&abs(j-maxid)>5)
    {
      second=j;
    }
  }

上述语句块,我们在读取的50个心跳电压值中,找出最大值和次大值。为了减少噪声误差,简单的将时间间隔拉开(不写这句话会造成次大值一直在最大值的相邻位):

abs(j-maxid)>5

之后计算脉搏数值

  if((maxid-second!=0)&&(3000/abs(maxid-second)<200))
    bpm=3000/abs(maxid-second);
  else
    bpm=bpm;

我们设置一个采样处理周期是500ms,所以一分钟的心跳数需要乘上3000。
之后是在OLED上显示心跳频率

  for(int i=31;i>0;i--)
  {
    Y[i]=Y[i-1];
    Y[0]=bpm-70;//64*(Data[0]-2700)/(100);
  }
  display.clearDisplay();
    //display.drawString(0,0, "Counter: " + String(counter));
  display.drawLine(96,0,96,64,SSD1306_WHITE);//y
  display.drawLine(0,32,96,32,SSD1306_WHITE);
  display.drawLine(96,45,128,45,SSD1306_WHITE);
  //x坐标轴绘制
  for(int i=0;i<96;i++)
  {
    int count=i/4;
    int res=i%4;
    if(res==0)
    {
    display.drawLine(i,Y[count],i+4,Y[count+1],SSD1306_WHITE);//画线
    }
    else
    {
    
    }
  }
  display.setTextSize(1);
  display.setTextColor(WHITE);
 
  display.setCursor(100,5);
  display.println(int(temperature));
  
  display.setCursor(115,1);
  display.println("o");
 
  display.setCursor(120,5);
  display.println("C");
  
  display.setCursor(100,22);
  display.println(int(bpm));

  display.setCursor(100,30);
  display.println("BPM");
  
  //if (Blynk.getstate())
  {
    display.drawBitmap(105,48,frame0,16,16,SSD1306_WHITE);
  }
  display.fillCircle(counter,32,2,SSD1306_WHITE);
  display.display();
  

  if(counter<96)
  {
    counter=counter+4;
  }
  else
  {
    counter=0;
    }

下面这句话是把测出来的心跳值平移下来,因为心跳数值会比64稍大,溢出了屏幕,所以需要进行向下平移。

  for(int i=31;i>0;i--)
  {
    Y[i]=Y[i-1];
    Y[0]=bpm-70;//64*(Data[0]-2700)/(100);
  }

之后的语句都是画线的部分了,有兴趣的朋友可以自己改改。最后的显示效果如下图所示:
在这里插入图片描述
本地端的配置就算完成了,之后我们要将本地端的数据上传到Blynk服务器上,从而实现在手机上监测心跳和体温。

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值