风筝
发表于: 2021-9-7 10:06:39 | 显示全部楼层

脉搏血氧仪是一种广泛使用的医疗测量仪器,它是一种无创、无痛的测试方法,可测量血液中的氧饱和度水平,可以轻松检测氧气的微小变化。在当前的Covid-19情况下,在不与患者接触的情况下同时远程跟踪多名患者的氧气水平变得很重要。


因此,在本篇文章中,我们使用MAX30100脉搏血氧仪和ESP32制作了一个心率监测器,它将跟踪血氧水平并连接到Wi-Fi网络通过互联网发送数据。通过这种方式,我们可以与患者保持社交距离来远程监控多个患者。获得的数据将显示为图表,便于跟踪和分析患者的病情。除了Covid-19应用,本文还可以广泛应用于慢性阻塞性肺病 (COPD)、哮喘、肺炎、肺癌、贫血、心脏病发作或心力衰竭等疾病的监测。


MAX30100传感器

MAX30100传感器集成了脉搏血氧仪和心率监测模块。它通过I2C数据线通信并向主机微控制器单元提供血氧饱和度(SpO2)和心率。它使用光电探测器、光学元件,其中红色、绿色IR LED调制心率。 LED电流可配置为0至50mA。下图显示了MAX30100传感器。

MAX30100-Sensor.png


上述传感器模块工作在1.8V至5.5V。模块中包含了I2C引脚的上拉电阻。


所需的组件

●    WiFi连接

●    ESP32开发板

●    MAX30100传感器

●    Adafruit IO

●    5V电源

●    USB数据线


MAX30100传感器与ESP32的连接图

下面给出了ESP32与MAX30100传感器连接完整电路图。

Interfacing-MAX30100-Oximeter-with-ESP32.png


这是一个非常简单的示意图。 ESP32开发套件引脚21和22连接到MAX30100传感器的SDA和SCL引脚。传感器也由ESP32开发板上的5V引脚供电。我使用面包板和连接线进行连接,连接后整体如下:

MAX30100-with-ESP32.jpg


配置Adafruit IO用于心率监测

我们之前已经为不同的物联网应用制作了许多Adafruit IO项目。 Adafruit IO是一个出色的平台,可以在其中创建自定义仪表板。要为基于IoT的脉搏血氧仪创建自定义仪表板,请使用以下步骤-


第1步:首先在adafruit IO网站进行注册,填写所需的姓名、电子邮件地址、用户名以及密码。

Adafruit-IO.png


第2步:登入网站后,会显示一个空白的仪表板(Dashboard)窗口。在本文中,我们将需要创建一个仪表板来以各种方式显示数据。因此,新建一个仪表板,输入名称和描述信息。

Create-Adafruit-IO-Dashboard.png

Adafruit-Dashboard.png


第3步:填写上述表格后,接下来创建图形和控制部分。


Adafruit-IO-Blocks.jpg


选择开关块。需要该块打开或关闭脉搏血氧仪传感器。

Adafruit-Switch-Block.png


第4步:写下块名称。正如我们在上图中看到的,开关功能提供两种状态,ON和OFF。选择图形块,重复该过程。


需要选择两次图形块,因为需要显示两个图形,心率和血氧饱和度。

Adafruit-Feed.png


第5步:最后一步是获取adafruit密钥。在得到adafruit密钥之后,需要将其添加到代码中。

Adafruit-IO-Key.jpg

Adafruit IO现已配置完毕。接下来就可以准备硬件和创建固件代码了。


跳转到指定楼层
风筝
发表于: 2021-9-7 10:44:31 | 显示全部楼层

代码说明

这段代码使用了许多库,而且都很重要。这些库分别是MAX30100 脉搏血氧仪传感器库、用于I2C的Wire.h、用于ESP32中WiFi相关支持的WiFi.h、Adafruit MQTT和MQTT客户端库。


首先在代码开头包含上面提到的那些库的头文件。

  1. #include <stdint.h>
  2. #include <Wire.h>
  3. #include <WiFi.h>
  4. #include "Adafruit_MQTT.h"
  5. #include "Adafruit_MQTT_Client.h"
  6. #include "MAX30100_PulseOximeter.h"  //used arduino builtin MAX30100 lib (https://github.com/oxullo/Arduino-MAX30100)
复制代码

接下来定义无线名称WLAN SSID和密码WLAN_PASS 。ESP32使用这些定义来连接WiFi网络。

  1. #define WLAN_SSID  "xxxxxxxxx"
  2. #define WLAN_PASS  "2581xxxxx2"
复制代码

接下来,我们定义了Adafruit io相关定义。

  1. #define AIO_UPDATE_RATE_SEC 5
  2. #define AIO_SERVER  "io.adafruit.com"
  3. #define AIO_SERVERPORT  1883               
  4. #define AIO_USERNAME  "xxxxxxxxxxxxx"
  5. #define AIO_KEY "abcdefgh"
复制代码

更新频率设置为每5秒更新一次数据,服务器是io.adafruit.com,服务器端口为1883。用户名和密码将是从adafruit IO仪表板生成的用户名和密码。所有人的配置信息都不同,需要按照 adafruit设置部分中的说明生成。


接下来定义I2C端口,如原理图所示.

  1. #define I2C_SDA 21
  2. #define I2C_SCL 22
复制代码

接下来,定义三个变量用于存储上次报告以及bpm和spo2值。

  1. uint32_t tsLastReport = 0;
  2. float bpm_dt=0;
  3. float spo2_dt = 0;
复制代码

MQTT使用发布-订阅模型。在此工作模型中,向Adafruit服务器提交数据的设备保持发布模式,其中Adafruit IO服务器订阅相同的数据点。每当设备发布任何新数据时,服务器接收数据并执行必要的动作。


当服务器发布数据并且设备订阅它时,也会发生同样的事情。在我们的应用中,设备将SPO2和BPM的数据发送到服务器,因此它发布该数据并从服务器接收ON-OFF状态,从而需要订阅该状态。下面代码中配置了MQTT。

  1. WiFiClient client;
  2. Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);         
  3. Adafruit_MQTT_Subscribe sw_sub = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/switch");
  4. // Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
  5. Adafruit_MQTT_Publish bpm_pub = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/bpm");
  6. Adafruit_MQTT_Publish spo2_pub = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/SpO2");
复制代码

setup()函数中,我们启动I2C,使用预定义的SSID和密码连接WiFi,启动MQTT,订阅开关状态。

  1. void setup()
  2. {
  3.             Serial.begin(115200);
  4.             Wire.begin(I2C_SDA, I2C_SCL);
  5.             WiFi.begin(WLAN_SSID, WLAN_PASS);
  6.             while (WiFi.status() != WL_CONNECTED) {
  7.             delay(500);
  8.             Serial.print(".");
  9.             }
  10.             Serial.println();
  11.             Serial.println("WiFi connected");
  12.             Serial.println("IP address: "); Serial.println(WiFi.localIP());
  13.             mqtt.subscribe(&sw_sub);
  14.             Serial.print("Initializing pulse oximeter..");
  15.             // Initialize the PulseOximeter instance
  16.             // Failures are generally due to an improper I2C wiring, missing power supply
  17.             // or wrong target chip
  18.             if (!pox.begin()) {
  19.             Serial.println("FAILED");
  20.             for(;;);
  21.             } else {
  22.             Serial.println("SUCCESS");
  23.             }
  24.             // The default current for the IR LED is 50mA and it could be changed
  25.             //   by uncommenting the following line. Check MAX30100_Registers.h for all the
  26.             //   available options.
  27.             pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
  28.             // Register a callback for the beat detection
  29.             pox.setOnBeatDetectedCallback(onBeatDetected);
  30.             stopReadPOX();
  31. }
复制代码

在所有这些之后,max30100以LED电流设置启动。 MAX30100头文件中还提供了不同的电流设置,用于不同的配置。心跳检测回调函数也启动。 在所有这些设置之后,血氧计传感器开始工作。


loop()函数中,启动MQTT连接,每5000毫秒检查一次订阅。如果开关打开,它开始读取血氧计传感器并发布心率和氧饱和度值的数据。 如果开关关闭,它将暂停与脉搏血氧仪传感器相关的所有任务。

  1. void loop() {
  2.   MQTT_connect();
  3.   Adafruit_MQTT_Subscribe *subscription;
  4.   while ((subscription = mqtt.readSubscription(5000)))
  5.   {
  6.             if (subscription == &sw_sub)
  7.             {
  8.             Serial.print(F("Got: "));
  9.             Serial.println((char *)sw_sub.lastread);
  10.             if (!strcmp((char*) sw_sub.lastread, "ON"))
  11.             {
  12.             Serial.print(("Starting POX... "));
  13.             startReadPOX();
  14.             BaseType_t xReturned;
  15.             if(poxReadTaskHld == NULL){
  16.             xReturned = xTaskCreate(
  17.                         poxReadTask, /* Function that implements the task. */
  18.                         "pox_read", /* Text name for the task. */
  19.                         1024*3,    /* Stack size in words, not bytes. */
  20.                         NULL,  /* Parameter passed into the task. */
  21.                         2,/* Priority at which the task is created. */
  22.                         &poxReadTaskHld ); /* Used to pass out the created task's handle. */
  23.             }
  24.             delay(100);
  25.             if(mqttPubTaskHld == NULL){
  26.             xReturned = xTaskCreate(
  27.                         mqttPubTask, /* Function that implements the task. */
  28.                         "mqttPub",  /* Text name for the task. */
  29.                         1024*3,    /* Stack size in words, not bytes. */
  30.                         NULL, /* Parameter passed into the task. */
  31.                         2,/* Priority at which the task is created. */
  32.                         &mqttPubTaskHld ); /* Used to pass out the created task's handle. */
  33.             }
  34.             }
  35.             else
  36.             {
  37.             Serial.print(("Stoping POX... "));
  38.             // Detele POX read task
  39.             if(poxReadTaskHld != NULL)
  40.             vTaskDelete(poxReadTaskHld);
  41.             poxReadTaskHld = NULL;
  42.             }
  43.             // Delete the MQTT Pub Task
  44.             if(mqttPubTaskHld != NULL){
  45.             vTaskDelete(mqttPubTaskHld);
  46.             mqttPubTaskHld = NULL;
  47.             }
  48.             stopReadPOX();
  49.             }
  50.             }
  51.   }
  52. }
复制代码

基于物联网的脉搏血氧仪演示

在面包板上正确连接电路,将代码上传到ESP32。 确保在代码中相应地更改Wi-Fi和Adafruit凭据。

IoT-Based-Pulse-Oximeter.jpg


与WiFi和Adafruit IO服务器连接后,它开始按预期工作。

Heart-Rate-Monitoring-Dashboard.png


如上图所示,氧饱和度值显示为96%,心跳显示为每分钟78到81次。 它还提供捕获数据的时间。当开关处于关闭状态时,数据为0。


希望你喜欢这篇文章并学到了一些有用的东西,如果你有任何问题,请随时在本贴下面进行回复。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1482



手机版|

GMT+8, 2024-4-28 13:49 , Processed in 0.040480 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表