基于 Hi3861 的 OpenHarmony 物联网健康监测实验
如图是普中-Hi3861开发板,
一、实物
1、HI3861
如图是普中-Hi3861开发板,
(1)标号「3」的金属屏蔽罩模块
这个模块就是普中 - Hi3861 开发板的核心大脑,不是单纯的 WiFi 模块,而是主控 + WiFi + 蓝牙三合一的系统级芯片模组,型号是Hi3861L。核心功能:
- 主控单元:负责运行你的 C 语言代码,执行传感器数据采集、预处理、MQTT 通信等所有逻辑,是整个系统的 “CPU”。
- 内置 WiFi 功能:它自带完整的 WiFi 电路和协议栈,通过左上角那个金色小圆点(天线)发射和接收信号。你在代码里配置好路由器的 SSID 和密码,它就能自动连接 WiFi,实现联网,完全不用额外接网卡。
- 内置蓝牙功能:同时支持蓝牙通信
- 低功耗控制:作为鸿蒙 IoT 芯片,它自带休眠 / 唤醒控制,适合物联网低功耗场景。
(2)标号「9」的黄色排针
这排黄色的引脚是通用 GPIO(通用输入输出)扩展接口,大多传感器(MAX30102、DS18B20)都是通过它和主控连接的。
为什么它能连接传感器?
- 引脚定义清晰:每一个引脚都对应着 Hi3861 芯片的一个功能接口,板子上丝印标注了每个引脚的功能,比如:
3V3:3.3V 电源,给传感器供电GND:接地,构成完整电路GPIO0~GPIO14:通用输入输出引脚,可配置为 I2C、单总线等通信模式ADC:模数转换引脚,可接模拟传感器
- 通信协议支持:通过代码配置,这些引脚可以变成不同的通信接口:
- MAX30102,就是通过配置
GPIO13和GPIO14为I2C 通信模式,实现数据读写; - DS18B20 则是用
GPIO10配置为单总线模式,实现温度数据采集。
- MAX30102,就是通过配置
- 扩展能力强:除了你的两个传感器,还可以接 LED、按键、舵机等其他外设,这就是它叫 “扩展口” 的原因。
2、传感器
(1)MAX30102
核心原理:光电容积描记法 (PPG)。这是一种利用光来监测血管中血容量变化的技术。它会向皮肤发射特定波长的光,然后检测反射回来的光强度信号,可以无创地测量心率和血氧饱和度。
工作流程详解:
-
发射:内置的红光 (~660nm) 和红外光 (~880nm) LED交替或同时发光,穿透皮肤表层。
-
吸收与反射:血液中的血红蛋白对不同波长光的吸收能力不同。氧合血红蛋白 (HbO2) 吸收更多红外光,而脱氧血红蛋白 (Hb) 吸收更多红光。
-
检测:光电探测器接收未被吸收而反射回来的光信号。由于每次心脏搏动都伴随着动脉血容量和含氧量的周期性变化,反射光强度也会随之波动。
-
计算:MAX30102 内部的 AFE(模拟前端)将光信号转换为原始的 PPG 数字量(红光和红外光的ADC采样值)。Hi3861 通过 I2C 读取这些原始数据后,再运行心率、血氧算法(如FFT、峰值检测、比率法),最终计算出心率和血氧值。
主要特点:
-
高度集成光学模块,专为可穿戴设备设计。
-
超低功耗,支持关断模式(典型值0.7µA)。
-
拥有强大的环境光抑制能力,能提升测量准确性。
(2)DS18B20
核心技术:片内集成的一个 温度-频率转换模块,它会:
-
使用两个特性差异巨大的振荡器:一个频率非常稳定,几乎不受温度影响;另一个的频率则对温度极其敏感,会随温度升高而升高。
-
通过一系列复杂的脉冲计数与逻辑运算,将温度值转换为一个16位的数字量,直接输出。
-
最终,Hi3861只需通过简单指令,就能从DS18B20中读出这个已经完成模数转换的温度数值。
使用指南:
-
连接:其最大特色是采用 单总线 (1-Wire) 协议,只需一根数据线(加上电源和地)就能与Hi3861通信,可以大大节省MCU的引脚资源。
-
操作:主机(Hi3861)必须严格按照复位脉冲、存在脉冲、读/写时隙等特定时序来操作总线(对烧录到板子中的代码的要求)。
-
读取:在转换完成后,只需向传感器发送
0xBE[读取暂存器] 命令,即可读出9到12位的数字化温度值。 -
分辨率:可以根据需要在9到12位之间调整,默认12位模式下,最高分辨率可达 0.0625°C。
主要特点:
-
测量范围宽:-55°C ~ +125°C,在 -10°C ~ +85°C 范围内精度高达 ±0.5°C。
-
无需任何外部元件,可直接与微控制器连接。
-
支持多点组网,一根总线上可挂载多个传感器。
-
支持“寄生电源”模式,可以不接外部电源,直接从数据线上获取工作电力。
从Hi3861的视角看,I2C和单总线这两种通信方式虽然原理不同,但在逻辑上都遵循了标准的软件操作流程(即所谓“通信协议”或“时序”),通过读写寄存器来完成数据交换,这为你连接和处理这两类传感器提供了清晰的技术路径。
二、接线
1、MAX30102(I2C 通信)
代码中 I2C 引脚定义(核心代码片段)
hi_void code_io_init(hi_void)
{
hi_gpio_init();
// IIC
hi_io_set_func(HI_IO_NAME_GPIO_0, HI_IO_FUNC_GPIO_0_I2C1_SDA);
hi_io_set_func(HI_IO_NAME_GPIO_1, HI_IO_FUNC_GPIO_1_I2C1_SCL);
if (hi_i2c_init(1, 400000) == HI_ERR_SUCCESS)
printf("I2C INIT END P0 P1\r\n");
}
| MAX30102 引脚 | Hi3861 引脚 | 功能 |
|---|---|---|
| VCC | 3.3V | 供电 |
| GND | GND | 接地 |
| SDA | GPIO0 | I2C 数据 |
| SCL | GPIO1 | I2C 时钟 |
2、 DS18B20(单总线 1-Wire)
1. 代码中隐含的单总线引脚
DS18B20 是单总线温度传感器,通过 1-Wire 单总线 通信,普中 Hi3861 开发板的 DS18B20 单总线默认映射到 GPIO9(普中官方驱动默认引脚为 GPIO9)
2. 硬件接线对应关系
| Hi3861 引脚 | DS18B20 引脚 | 功能说明 | 补充说明 |
|---|---|---|---|
| GPIO9 | DQ | 单总线数据引脚 | 需外接 4.7K~10K 上拉电阻 到 3.3V |
| 3.3V | VDD | 电源(3.3) | DS18B20 支持寄生电源 / 外部电源,推荐外部 3.3V 供电 |
| GND | GND | 地 | 必须共地 |
三、核心代码
1、头文件与全局配置(基础依赖)
#include <Arduino.h>// MAX30102依赖(需安装Adafruit MAX3010x库)
...
/********************* 配置参数 *********************/
// WiFi配置
const char* WIFI_SSID = "你的WiFi名称";
const char* WIFI_PWD = "你的WiFi密码";
// MQTT配置
const char* MQTT_BROKER = "MQTT服务器IP"; // 如192.168.1.100或公网地址
const int MQTT_PORT = 1883; // MQTT默认端口
const char* MQTT_TOPIC = "sensor/data"; // 上传数据的主题
const char* MQTT_CLIENT_ID = "esp32_sensor_001"; // 客户端唯一ID
// 引脚定义
#define DS18B20_PIN 4 // DS18B20数据引脚
/********************* 全局对象 *********************/
// MAX30102对象
MAX30105 particleSensor;
// DS18B20对象
OneWire oneWire(DS18B20_PIN);
DallasTemperature sensors(&oneWire);
// WiFi+MQTT对象
WiFiClient espClient;
PubSubClient mqttClient(espClient);
2、MAX30102 模块(心率 / 血氧采集)
核心功能:初始化传感器、采集红外 / 红光值、计算心率。
// 心率计算缓存
uint32_t irValue = 0; // 红外光值
int beatAvg; // 平均心率
// 初始化MAX30102
void initMAX30102() {
Serial.println("初始化MAX30102...");
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) { // I2C高速模式
Serial.println("MAX30102初始化失败!");
while (1); // 卡死等待排查
}
// 配置传感器参数(官方推荐默认配置)
particleSensor.setup(60, 4, 2, 411, 11); // 采样率、脉宽、增益等
particleSensor.setPulseAmplitudeRed(0x0A); // 红光强度
particleSensor.setPulseAmplitudeIR(0x0A); // 红外光强度
particleSensor.setPulseAmplitudeGreen(0); // 关闭绿光(仅测心率/血氧)
Serial.println("MAX30102初始化完成");
}
// 读取MAX30102数据(心率)
float readMAX30102HeartRate() {
long irValue = particleSensor.getIR(); // 读取红外光值(核心:心率由红外光波动计算)
// 心率算法(heartRate库内置)
if (checkForBeat(irValue)) { // 检测到心跳脉冲
beatAvg = getHeartRate(); // 获取平均心率
}
// 过滤无效值(心率范围:30-200)
if (beatAvg < 30 || beatAvg > 200) {
return -1; // 无效值标记
}
return (float)beatAvg;
}
核心逻辑: MAX30102 通过红外光(IR)检测血液流动的光反射变化,checkForBeat() 检测心跳脉冲,getHeartRate() 累计计算平均心率;血氧需同时读取红光 + 红外光的比值,逻辑类似但需校准公式(可扩展,计算血氧逻辑太复杂,就把代码放到另一个文章了)。
3、DS18B20 模块(温度采集)
核心功能:初始化单总线、触发温度转换、读取精准温度值。
// 初始化DS18B20
void initDS18B20() {
Serial.println("初始化DS18B20...");
sensors.begin(); // 初始化单总线
Serial.println("DS18B20初始化完成");
}
// 读取DS18B20温度(℃)
float readDS18B20Temperature() {
sensors.requestTemperatures(); // 触发温度转换(必须调用)
float temp = sensors.getTempCByIndex(0); // 读取第一个传感器的温度(℃)
// 过滤无效值(DS18B20默认返回-127℃表示故障)
if (temp == -127.00) {
Serial.println("DS18B20读取失败");
return -1;
}
return temp;
}
核心逻辑: DS18B20 是单总线协议,requestTemperatures() 是 “触发转换” 指令(传感器需要时间采集温度),getTempCByIndex(0) 读取转换后的温度(支持多传感器级联,index 区分)。
4、MQTT+WiFi 模块(数据上传)
核心功能:WiFi 重连、MQTT 重连、封装传感器数据为 JSON 并发布。
// 连接WiFi
void connectWiFi() {
Serial.print("连接WiFi: ");
Serial.println(WIFI_SSID);
WiFi.mode(WIFI_STA); // 客户端模式(非AP模式)
WiFi.begin(WIFI_SSID, WIFI_PWD);
// 等待连接(超时10秒)
int retry = 0;
while (WiFi.status() != WL_CONNECTED && retry < 10) {
delay(500);
Serial.print(".");
retry++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi连接成功!");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("\nWiFi连接失败!");
ESP.restart(); // 重启重试
}
}
// 重连MQTT(断连自动重连)
void reconnectMQTT() {
while (!mqttClient.connected()) {
Serial.print("连接MQTT...");
// 连接MQTT服务器(无账号密码版,有密码则加参数:mqttClient.connect(CLIENT_ID, USER, PWD))
if (mqttClient.connect(MQTT_CLIENT_ID)) {
Serial.println("MQTT连接成功!");
// 可选:订阅主题(如需接收服务器指令)
// mqttClient.subscribe("sensor/control");
} else {
Serial.print("失败,错误码:");
Serial.print(mqttClient.state()); // 打印错误码(如-4=超时,-2=拒绝)
Serial.println(",5秒后重试...");
delay(5000);
}
}
}
// 封装传感器数据并发布到MQTT
void publishSensorData() {
// 读取传感器数据
float temp = readDS18B20Temperature();
float heartRate = readMAX30102HeartRate();
// 封装JSON(便于服务器解析)
char payload[128]; // 缓存JSON字符串
snprintf(payload, sizeof(payload),
"{\"temperature\":%.2f, \"heartRate\":%.1f}",
temp, heartRate);
// 发布数据
if (mqttClient.publish(MQTT_TOPIC, payload)) {
Serial.print("MQTT发布成功: ");
Serial.println(payload);
} else {
Serial.println("MQTT发布失败!");
}
}
5、主函数(整合所有模块)
void setup() {
Serial.begin(115200); // 串口调试
// 初始化所有模块
initMAX30102();
initDS18B20();
connectWiFi();
mqttClient.setServer(MQTT_BROKER, MQTT_PORT); // 设置MQTT服务器地址+端口
}
void loop() {
// 保证WiFi和MQTT始终连接
if (WiFi.status() != WL_CONNECTED) {
connectWiFi();
}
if (!mqttClient.connected()) {
reconnectMQTT();
}
mqttClient.loop(); // 处理MQTT心跳/消息(必须调用)
// 每2秒发布一次数据
publishSensorData();
delay(2000);
}
更多推荐
所有评论(0)