Arduino-ESP32-WROOM-32E—PulseSensor传感器测心率

news/2024/10/20 15:53:09/

1、下载ESP32驱动

2、右击以管理员身份运行

3、运行完成后,即可安装成功。打开Adruino,选中如图开发板

4、双击打开.ino文件

5、 选择合适的开发板型号和端口

6、 安装库文件ESP32time、U8g2、PulseSensor Playground

 7、修改为自己的传感器S口连接的引脚,此处我选择D36。

8、修改OLED显示屏SCL和SDA的引脚。使用ESP32_WROOM_32E开发板时修改为22,21号。 

 9、定时中断启动中,可以采用按键来中断检测将数据存储到SD卡,ESP32_WROOM_32E开发板支持使用BOOT和EN口连接按键,EN为复位按键,所以此处采用BOOT IO0口,将外部中断attachInterrupt函数的第一个参数改为0。(具体选几号IO口请查阅开发板手册)。

函数功能:配置初始化外部中断

参数1:pin,外部中断所使用的引脚,ESP32所有引脚均可以配置为外部中断引脚

参数2:中断服务函数,此处填写函数名即可

参数3:中断触发方式,支持以下触发方式:

-LOW 低电平触发

-CHANGE 电平变化

-RISING 上升沿触发

-FALLING 下降沿触发

-HIGH 高电平触发

 10、若不安装SD卡,注释掉图中代码

 11、烧写成功后会出现ESP32 Sensor kit字样如图

 12将手指放入绿光保持静止,后出现

 完整代码如下:

#include "esp32-hal-cpu.h"
#include <stdio.h>
#include <string.h>
int initFlag = 0;  //硬件初始化标志
int intFlag = 0;   //按键1中断标志位
int count = 0;
char point[11];
#define USART_DEBUG 1  //使能串口打印调试信息
//RTC
#include <ESP32Time.h>
ESP32Time rtc(0);  //时间偏移量,单位ms
//OLED
#include <U8g2lib.h>
#include <Wire.h>
//SD Card
#include "FS.h"
#include "SD.h"
#include "SPI.h"
//OLED
#define OLED_SCL 22
#define OLED_SDA 21
//ADC->PulseSensor
#define USE_ARDUINO_INTERRUPTS false
#include <PulseSensorPlayground.h>
uint16_t dataHR = 0;
uint16_t data = 0;
struct Data {char HR[10] = "HR:0";char SPO2[10] = "SPO2:N/A";
} adcData;
PulseSensorPlayground pulseSensor;
const int OUTPUT_TYPE = SERIAL_PLOTTER;
const int PULSE_INPUT = 36;
#ifdef USART_DEBUG
const int THRESHOLD = 550;  // Adjust this number to avoid noise when idle
#else
const int THRESHOLD = 550;  // Adjust this number to avoid noise when idle
#endif
byte samplesUntilReport;
const byte SAMPLES_PER_SERIAL_SAMPLE = 10;
//OLED
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /*reset=*/U8X8_PIN_NONE, /*clock=*/OLED_SCL, /*data=*/OLED_SDA);  //U8G2程序库 SSD1306控制晶片 128X64_NONAME解析度和型号 F暂存区大小可以改为1或2 F_HW_I2C控制介面 u8g2(U8G2_R0代表不旋转,U8X8_PIN_NONE代表没有重置引脚)
//Timer
hw_timer_t *timer = NULL;//按键1中断服务函数
ICACHE_RAM_ATTR void INTfunction() {if (intFlag == 0)intFlag = 1;elseintFlag = 0;
}void setup() {Serial.begin(115200);setCpuFrequencyMhz(240);
#ifdef USART_DEBUGSerial.print("CpuFrequency:");Serial.print(getCpuFrequencyMhz());Serial.println("MHz");
#endif/** RTC*/rtc.setTime(0, 0, 14, 7, 11, 2022);  // 7th Nov 2021 14:0:0/** OLED*/u8g2.begin();u8g2.enableUTF8Print();  //使能UTF-8支持库u8g2.setFont(u8g2_font_unifont_t_symbols);u8g2.clear();u8g2.clearBuffer();u8g2.firstPage();do {u8g2.setCursor(0, 14);           //指定显示位置u8g2.print("ESP32 Sensor Kit");  //使用print来显示字符串u8g2.setCursor(0, 35);           //指定显示位置u8g2.print("Booting...");        //使用print来显示字符串} while (u8g2.nextPage());/** SD卡*//*if (!SD.begin()) {  //检测SD卡挂载状态u8g2.clearBuffer();u8g2.firstPage();do {u8g2.setCursor(0, 14);           //指定显示位置u8g2.print("ESP32 Sensor Kit");  //使用print来显示字符串u8g2.setCursor(0, 35);           //指定显示位置u8g2.print("Card Mount");        //使用print来显示字符串u8g2.setCursor(0, 55);           //指定显示位置u8g2.print("Failed !!!");        //使用print来显示字符串} while (u8g2.nextPage());Serial.println("Card Mount Failed !");return;}uint8_t cardType = SD.cardType();if (cardType == CARD_NONE) {Serial.println("No SD card attached");return;}Serial.print("SD Card Type: ");if (cardType == CARD_MMC) {Serial.println("MMC");} else if (cardType == CARD_SD) {Serial.println("SDSC");} else if (cardType == CARD_SDHC) {Serial.println("SDHC");} else {Serial.println("UNKNOWN");}Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));listDir(SD, "/", 0);*//** ADC->PulseSensor*/pulseSensor.analogInput(PULSE_INPUT);pulseSensor.setSerial(Serial);pulseSensor.setOutputType(OUTPUT_TYPE);pulseSensor.setThreshold(THRESHOLD);samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;if (!pulseSensor.begin()) {u8g2.clearBuffer();u8g2.firstPage();do {u8g2.setCursor(0, 14);           //指定显示位置u8g2.print("ESP32 Sensor Kit");  //使用print来显示字符串u8g2.setCursor(0, 35);           //指定显示位置u8g2.print("PulseSensor Init");  //使用print来显示字符串u8g2.setCursor(0, 55);           //指定显示位置u8g2.print("Failed !!!");        //使用print来显示字符串} while (u8g2.nextPage());Serial.println("PulseSensor Init Failed !");return;}timer = timerBegin(0, 80, true);              // 初始化定时器指针timerAttachInterrupt(timer, &onTimer, true);  // 绑定定时器timerAlarmWrite(timer, 2000, true);           // 配置报警计数器保护值(就是设置时间)单位ustimerAlarmEnable(timer);                      // 启用定时器//使能按键1中断监测
//  attachInterrupt(0, INTfunction, FALLING);//硬件初始化成功 标志置一initFlag = 1;
}void loop() {dataHR = data;data = 0;if (initFlag == 0) {  //初始化失败则退出程序Serial.print("hardware init failed !\r\n");delay(3000);ESP.restart();}
#ifdef USART_DEBUGSerial.print("HR: ");Serial.println(dataHR);
#endifchar temp[10];memset(adcData.HR, 0, sizeof(char) * 10);adcData.HR[0] = 'H';adcData.HR[1] = 'R';adcData.HR[2] = ':';itoa(dataHR, temp, 10);for (int i = 0; i < strlen(temp); i++) {adcData.HR[3 + i] = temp[i];}/** OLED*/u8g2.clearBuffer();u8g2.firstPage();do {if (adcData.HR[3] == '0') {point[count] = '.';u8g2.setCursor(0, 14);           //指定显示位置u8g2.print("ESP32 Sensor Kit");  //使用print来显示字符串u8g2.setCursor(0, 35);           //指定显示位置u8g2.print("Please keep");       //使用print来显示字符串if (intFlag == 1) {u8g2.setCursor(100, 40);  //指定显示位置u8g2.print("REC");        //使用print来显示字符串}u8g2.setCursor(0, 55);       //指定显示位置u8g2.print("touch stable");  //使用print来显示字符串u8g2.setCursor(101, 55);     //指定显示位置u8g2.print(point);           //使用print来显示字符串if (count == 2) {memset(point, 0, sizeof(char) * 10);count = 0;} elsecount++;} else {count = 0;memset(point, 0, sizeof(char) * 10);u8g2.setCursor(0, 14);           //指定显示位置u8g2.print("ESP32 Sensor Kit");  //使用print来显示字符串u8g2.setCursor(0, 35);           //指定显示位置u8g2.print(adcData.HR);          //使用print来显示字符串if (intFlag == 1) {u8g2.setCursor(100, 40);  //指定显示位置u8g2.print("REC");        //使用print来显示字符串}u8g2.setCursor(0, 55);     //指定显示位置u8g2.print(adcData.SPO2);  //使用print来显示字符串}} while (u8g2.nextPage());/** SD Card*//*if (intFlag == 1) {if (adcData.HR[3] != '0') {appendFile(SD, "/PulseSensor.txt", &(rtc.getTime("%B %d %Y %H:%M:%S"))[0]);appendFile(SD, "/PulseSensor.txt", "\t\t");appendFile(SD, "/PulseSensor.txt", adcData.HR);appendFile(SD, "/PulseSensor.txt", "\r\n");}}*/adcData.HR[3] == '0';dataHR = 0;delay(800);
}/** ADC->PulseSensor*/
void onTimer()  //PulseSensor采集数据
{if (pulseSensor.sawNewSample()) {if (--samplesUntilReport == (byte)0) {samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;pulseSensor.outputSample();if (pulseSensor.sawStartOfBeat()) {// pulseSensor.outputBeat();data = pulseSensor.getBeatsPerMinute();}}}
}/** * SD Card->Function* *//*
void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {Serial.printf("Listing directory: %s\n", dirname);File root = fs.open(dirname);if (!root) {Serial.println("Failed to open directory");return;}if (!root.isDirectory()) {Serial.println("Not a directory");return;}File file = root.openNextFile();while (file) {if (file.isDirectory()) {Serial.print("  DIR : ");Serial.println(file.name());if (levels) {listDir(fs, file.name(), levels - 1);}} else {Serial.print("  FILE: ");Serial.print(file.name());Serial.print("  SIZE: ");Serial.println(file.size());}file = root.openNextFile();}
}*/
void appendFile(fs::FS &fs, const char *path, const char *message) {
#ifdef USART_DEBUGSerial.printf("Appending to file: %s\n", path);
#endifFile file = fs.open(path, FILE_APPEND);if (!file) {Serial.println("Failed to open file for appending");return;}if (file.print(message)) {
#ifdef USART_DEBUGSerial.println("Message appended");
#endif} else {Serial.println("Append failed");}file.close();
}


http://www.ppmy.cn/news/892696.html

相关文章

(操作系统开发)从实模式---->保护模式---->IA-32e模式( 64位模式)

实模式和保护模式都是CPU的工作模式。 实模式与保护模式介绍 在实模式下&#xff0c;程序可以操作任何地址空间&#xff0c;而且无法限制程序的执行权限。尽管这种模式给设置硬件功能带来许多方便&#xff0c;但却给程序执行的安全性和稳定性带来了灾难性的后果&#xff0c;一…

构建64位操作系统-Intel架构:实模式,保护模式,实模式长寻址,IA-32e

1.Intel处理器架构-实模式 BIOS加载引导程序开始执行时&#xff0c;程序位于实模式。 实模式下特点有&#xff1a; 1.1.实模式下的物理寻址 jmp 0x1000:0x0010 实模式下上述0x1000:0x0010对应的目标位置物理地址为0x1000 << 4 0x0010 0x10010。 1.1.1.实模式下…

一文搞懂 x64 IA-64 AMD64 Inte64 IA-32e 架构之间的关系

想要搞清楚 x64、IA64、AMD64 指令集之间的关系&#xff0c;就要先了解 Intel 和 AMD 这两家公司在生产处理器上的发展历史。 x86 处理器 1978年 Intel 生产了它的第一款 16bit 处理器8086&#xff0c;之后几款处理器名字也都以86结尾&#xff0c;包括80186&#xff0c;80286&a…

ESP32系列区别—ESP32-WROOM-32和ESP32-WROOM-32E和ESP32-WROOM-32U的区别

简单来说就是32E和32U是32的升级版本&#xff0c;具有更高的稳定性 具体的区别建议官网查看&#xff1a;模组概览 | 乐鑫科技 最近有新项目要用到32E&#xff0c;要去某宝购买回来练练手&#xff0c;但是发现有芯片和开发板&#xff0c;开发板更适合新手和软件开发者&#xf…

Windows(IA-32e模式)系统调用

一、本文主题 Windows NT是一个面向分层的操作系统&#xff0c;最底层是硬件&#xff0c;最高层使用户接口&#xff0c;Windows采用这种模式来保护内核不被应用程序错误的波及&#xff0c;操作系统核心运行在内核层(Ring 0 )&#xff0c;用户模式运行在应用层(Ring 3)。这只是操…

Windows x64内核学习笔记(二)—— IA-32e模式

Windows x64内核学习笔记&#xff08;二&#xff09;—— IA-32e模式 IA-32e模式模式检测强制平坦段任务切换中断门描述符FS / GS模式切换32位程序进内核64位程序进内核 实验&#xff1a;模式切换第一步&#xff1a;编译以下代码第二步&#xff1a;运行程序至第一次暂停处第三步…

手把手教玩转你动态内存管理(InsCode Stable Diffusion 美图活动一期)

目录https://inscode.csdn.net/inscode/Stable-Diffusion 一、动态内存管理的意义 二、动态内存管理函数 1.malloc和free 1.1认识malloc和free 1.2malloc和free的作用 1.3使用malloc和free时应注意的事项 1.3.1使用malloc注意事项 1.3.2使用free注意事项 1.4使用free和…

github进不去的解决办法

github就凭运气进吧&#xff0c;偶尔能进去。 介绍几个可以快速进的办法&#xff1a; 第一个&#xff0c;安装插件&#xff1a;&#xff08;在microsoft搜索watt toolkit插件并安装&#xff09; 然后勾选github选项&#xff1a; 接着返回你github网站就可以了。 第二个&#…