ESP32从DIY到智能穿戴:3行代码搞定心率+体温实时监测

点击蓝字 关注我们


在智能可穿戴浪潮里,打造一款能实时监测心率与体温的手环,似乎需要复杂电路与繁琐开发。但这款以 ESP32 为核心的 DIY 项目,通过 MAX30102 和 ADT7320 传感器,以极简线路与 Arduino 编程,即可轻松实现精准监测。无论你是创客小白,还是硬核工程师,只需简短几行代码,就能让手环“动”起来,值得每个爱折腾的小伙伴一试!

1


硬件选型和电路设计


本设计基于ESP32芯片,刚好使用上之前做项目学习用到的ESP32手环开发板——T_Wristband。 该开发板基于ESP32主芯片,板载tp4056锂电池充电管理芯片和50mAh锂电池,pcf8563时钟芯片,mpu9250多轴陀螺仪芯片,以及支持fpc接插座扩展外部传感器。

为了达到测量心率血氧的功能,选用了美信的MAX30102集成芯片。MAX30102是美信的一款用于可穿戴健康设备的高灵敏度脉搏血氧仪和心率传感器,传感器自带红光/红外光发射管和接收管,只需很少的外部器件便可完成心率血氧检测,为小型可穿戴产品的一个非常合适的传感器产品。

温度检测则选型了adi 的 adt7320高精度温度传感器。其参数和优点如下:

  • 高性能
    温度精度
    ±0.20°C:-10°C至+85°C
    ±0.25°C(-20°C至+105°C,3.3 V)
    16位分辨率:0.0078℃
    超低温漂:0.0073°C

  • 易于实现

    用户无需校准或校正温度

    无需线性校正

  • 低功率

    1 SPS(每秒采样率)省电模式

    正常模式下为700 μW(3.3 V,典型值)

    关断模式下为7 μW(3.3 V,典型值)

  • 宽工作范围

    工作温度范围:-40°C至+150°C

    电压范围:2.7 V至5.5 V

  • 可编程中断

    临界过温指示器

    过温/欠温中断

  • SPI兼容型接口

  • 16引脚、4 mm × 4 mm LFCSP封装,符合RoHS标准

欲了解更多特性,请参考数据手册

    在adt7320的电路设计中,为了兼容adt7420芯片,故在电路上设计了对I2C总线的上拉电阻,方便测试时更换芯片使用。


2


软件使用和程序编程


ESP32开发方式支持arduino 和 官方 ESP-IDF 软件,在易用性上,arduino更好,而且有众多的开源库的支持,让esp32开发体验更好。因此选择使用arduino进行程序开发。

arduino软件的安装和esp32开发板管理的设置就不在些赘述了,网上有太多的介绍。注意,根据开发板管理网址的更新,可能在选择开发板时 找不到对应的开发板型号,那么可以按以下图示中进行选择,只要在软件编程时不使用到板载芯片没有的功能,就能正常编程开发了。

软件开发需要使用到库支持,可以在库管理界面下载,也可以从网页下方的附件中下载后放置到arduino库所在文件夹,即可使用。

为什么使用库?因为使用库可以提高开发效率,当然如果你是大牛,自己写驱动库也是一样的,可以让程序功能更高效。

使用库开发的好处就在于,只需要再编写很少的程序,即可达到所想的功能。以下为max30102的心率读取程序示例。可以看到,短短几行,就已经完成了心率读取计算和OLED屏幕显示的功能了,简直不要太爽。

(以下程序在原文附件里有,下载后可直接编译)

#include<TFT_eSPI.h> // Graphics and font library for ST7735 driver chip#include<Wire.h>
#define LED_PIN             4#define HEATRATE_SDA        15#define HEATRATE_SCL        13#define HEATRATE_INT        4TFT_eSPI tft = TFT_eSPI();  // Invoke library, pins defined in User_Setup.h#include"MAX30105.h"#include"heartRate.h"MAX30105 particleSensor;constuint8_t RATE_SIZE = 4; //Increase this for more averaging. 4 is good.uint8_t rates[RATE_SIZE]; //Array of heart ratesuint8_t rateSpot = 0;long lastBeat = 0; //Time at which the last beat occurredfloat beatsPerMinute;int beatAvg;char buff[256];voidsetup(void){    Serial.begin(115200);    tft.init();    tft.setRotation(1);    tft.setTextColor(TFT_GREEN, TFT_BLACK); // Note: the new fonts do not draw the background colour    tft.fillScreen(TFT_BLACK);    tft.setCursor(0, 0);    pinMode(LED_PIN, OUTPUT);    Wire1.begin(HEATRATE_SDA, HEATRATE_SCL);    // Initialize sensor    if (!particleSensor.begin(Wire1, 400000)) { //Use default I2C port, 400kHz speed        tft.setTextColor(TFT_RED, TFT_BLACK); // Note: the new fonts do not draw the background colour        tft.println("MAX30105 was not found");        delay(10000);   //delay ten sec to restart        esp_restart();    }    particleSensor.setup(); //Configure sensor with default settings    particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running    particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED}voidloop(){    long irValue = particleSensor.getIR();    if (checkForBeat(irValue) == true) {        //We sensed a beat!        long delta = millis() - lastBeat;        lastBeat = millis();        beatsPerMinute = 60 / (delta / 1000.0);        if (beatsPerMinute < 255 && beatsPerMinute > 20) {            rates[rateSpot++] = (uint8_t)beatsPerMinute; //Store this reading in the array            rateSpot %= RATE_SIZE; //Wrap variable            //Take average of readings            beatAvg = 0;            for (uint8_t x = 0 ; x < RATE_SIZE ; x++)                beatAvg += rates[x];            beatAvg /= RATE_SIZE;        }    }    tft.fillScreen(TFT_BLACK);    snprintf(buff, sizeof(buff), "IR=%lu BPM=%.2f", irValue, beatsPerMinute);    tft.drawString(buff, 0, 0);    snprintf(buff, sizeof(buff), "Avg BPM=%d", beatAvg);    tft.drawString(buff, 0, 16);    if (irValue < 50000)        digitalWrite(LED_PIN, 0);    else        digitalWrite(LED_PIN, !digitalRead(LED_PIN));}

点击 “阅读原文” 查看项目

发表评论