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

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

头文件

#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);elsebpm=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);//ydisplay.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);elsebpm=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);//ydisplay.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服务器上,从而实现在手机上监测心跳和体温。

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

  1. ESP32基于arduino开发的心跳体温检测系统(一)项目介绍及准备

    本文为被北邮信息系统设计课程摧残的同学们(包括但不限于作者的室友)提供一个可行的方案及模板. 本项目使用Arduino作为开发环境,使用ESP32开发一个心跳体温检测系统. 系统通过心跳传感器--pu ...

  2. ESP32基于arduino开发的心跳体温检测系统(二)传感器的使用

    在上篇文章里,我们配置好了开发需要的环境.接下来就开始尝试使用传感器. 测温传感器 连接元件 我们使用的是MLX90614 gy906测温传感器,有4个引脚,分别为VCC.GND.SCL.SDA.其中 ...

  3. c语言pm2.5检测系统,基于Arduino的PM2.5实时检测系统

    沈华刚 洪香勤 都兴隆 摘 要:文章针对城市中PM2.5进行分析监视,并把数据实行显示在下位机和网络端.有利于相关部门或个人获得PM2.5数据信息,及时对恶劣污染作出反应,减少恶劣环境对人们的侵害.本 ...

  4. 基于STM32开发可燃气体智慧检测系统

    开发环境:Keil uVision5 \ STM32CubeMX 硬件型号:STM32F051K8(芯片), NB-iot(核心板) 涉及技术:ADC/SPI/UART/DMA/巴法云/AT命令/QT ...

  5. arduino编码器计数_基于Arduino开发环境的光电编码器检测仪设计方案 - 全文

    0 引言 Arduino是一款基于单片机系统的电子产品开发平台,它的软硬件系统都具有高度的模块化,而且软件系统是完全开源的.其硬件系统也是高度模块化的,在核心控制板的外围有开关量输入/输出模块.各种模 ...

  6. 基于ARM RK3568的红外热成像体温检测系统

    得益于我国政府有力的新冠疫情防控手段,人民群众的生产和生活没有受到过多影响.而放眼全球,疫情防控形势依旧严峻,这提醒着我们仍不能掉以轻心,除做好个人防护之外,公共场所的体温检测成为基础但重要的疫情防控 ...

  7. 基于Arduino开发板的火焰报警器

    ** 基于Arduino开发板的火焰报警器* 概述 本文将通过使用火焰传感器与Arduino UNO组成一个简单的火灾报警系统.该火焰传感器是基于IR(红外线 Infrared Radiation)的 ...

  8. 查看gpio状态_基于Arduino开发,借助blinker平台,让NodeMCU实现8路继电器APP端状态监视和控制...

    基于Arduino开发,借助blinker物联网平台,让NodeMCU实现8路继电器APP端状态监视和控制 先上开发板功能图: 本文利用了NodeMCU上的D0-D3,D5-D9,总共 8个 GPIO ...

  9. 利用HFS软件一分钟搭建好ESP8266基于Arduino开发环境

    利用HFS一分钟搭建好ESP8266基于Arduino开发环境

最新文章

  1. 关于学习Python的一点学习总结(33->继承中内置方法及多继承)
  2. linux监控http连接数,zabbix监控linux tcp连接数
  3. Dump程序运行中的状态,变量值,等到文件
  4. MySQL 是怎么死锁的?
  5. KND数控系统PLC开发环境
  6. spss可以关键词词频分析吗_有什么自动分词做词频分析的工具?
  7. NPN和PNP三极管做开关电路
  8. 什么教我们用计算机画画,作文:我第一次用电脑画画
  9. 黑客游戏系列--------第二关
  10. React-native android App项目搭建
  11. 建诗筑画 文/奥斯·科特林
  12. python QQ邮件发送
  13. 【php】empty()详解
  14. Quartus II与Modelsim软件安装教程
  15. 终于找到阻止360文件粉碎机的源代码了
  16. Jmeter压力测试报告案例
  17. 微信小程序点击复制文本至剪切板
  18. 昂达平板装linux系统下载,平板电脑安装Ubuntu教程-以V975w为例,Z3735系列CPU通用...
  19. 从键盘接收一百分制成绩( 0~100),要求输出其对应的成绩等级 A~E。其中,90 分以上为'A',80~89 分为'B', 70~79分为'C', 60~69分为'D', 60 分以下为'E'。
  20. 突发丨BSV暴涨200% 澳本聪又搞事情了!

热门文章

  1. SQL执行计划--HIT、SQLPLAN
  2. GEF原理及实现系列(二、模型)
  3. 学习分享:RNN(持续更新)
  4. 电话号码被标记了怎么取消?标记取消最强攻略来了
  5. C++STL之string类
  6. 循环 计算机英语,计算机英语词汇解释
  7. UE5/C++ 基于GAS创建攻击伤害 5.1.1准备碰撞体
  8. ubuntu18.04 升级内核后,进入系统页面卡在“started gnome display manager“的解决方案
  9. java自旋锁使用_10.Java锁之自旋锁
  10. 走着走着,就剩下了沉默