3、ESP32基础:芯片特性、开发板类型、GPIO、ADC、I2C、WiFi、蓝牙等核心资源
在老人看护场景中,ESP32之所以成为首选主控,是因为它在一颗芯片上集成了双核处理器、WiFi、蓝牙、丰富的模拟与数字外设,并且功耗可控、价格低廉。理解ESP32的硬件资源边界,是后续实现久坐检测(依赖ADC与GPIO)、跌倒风险判断(依赖IMU传感器与I2C总线)以及远程提醒(依赖WiFi/蓝牙通信)的基石。本节将系统梳理ESP32的芯片特性、常见开发板选型、GPIO/ADC/I2C等核心外设的使用要点,并结合老人看护项目给出具体的资源分配建议。
上图展示了ESP32在老人看护项目中的核心资源分布。左侧为传感器与执行器接口,右侧为通信与电源管理模块,中央为芯片本体。在实际项目中,我们需要根据外设的电气特性和通信协议,合理分配GPIO、ADC和I2C资源,避免冲突(例如ADC2与WiFi不能同时使用)。下面从芯片特性开始逐一展开。
3.1 芯片特性与开发板选型
ESP32系列由乐鑫(Espressif)推出,目前主流型号包括经典ESP32(WROOM-32)、ESP32-S3、ESP32-C3等。对于老人看护场景,ESP32-WROOM-32 是最稳妥的选择,因为它拥有最多的GPIO(34个可编程)、双核240MHz主频、520KB SRAM,且社区资料丰富。ESP32-C3是单核RISC-V架构,功耗更低但GPIO较少,适合极简传感器节点;ESP32-S3增加了AI加速指令,适合需要本地语音识别的场景,但价格略高。
| 开发板型号 | 核心/主频 | GPIO数量 | ADC通道 | 适用场景 |
|---|---|---|---|---|
| ESP32-WROOM-32 | 双核 240MHz | 34 | 18 (ADC1+ADC2) | 综合看护节点(推荐) |
| ESP32-S3-WROOM-1 | 双核 240MHz + AI | 45 | 20 | 需要语音/图像识别 |
| ESP32-C3-MINI-1 | 单核 160MHz | 22 | 6 | 低功耗简单传感器 |
| ESP32-PICO-D4 | 双核 240MHz | 34 | 18 | 极小体积穿戴设备 |
开发板选择上,NodeMCU-32S 和 ESP32-DevKitC 是最常见的两种。NodeMCU-32S自带USB转串口芯片(CP2102或CH340),直接插线即可烧录,适合快速原型验证;DevKitC则更接近官方参考设计,引脚标注清晰,适合教学和调试。无论选择哪款,务必确认板载稳压器输出电流≥500mA,因为WiFi发射瞬间电流可达300-400mA,若供电不足会导致反复重启。
3.2 GPIO:数字输入输出与中断
GPIO(General Purpose Input/Output)是ESP32与外界交互的最基本方式。在老人看护场景中,GPIO主要用于:读取跌倒检测按钮(数字输入)、驱动蜂鸣器报警(数字输出)、控制LED指示灯(PWM输出)、读取门磁传感器(中断触发)。ESP32的GPIO支持多种功能复用,但需要注意以下几点:
- 输入模式:可配置为浮空输入、上拉输入或下拉输入。对于按键,建议使用上拉输入(内部上拉电阻约45kΩ),按键另一端接地,按下时读到低电平。
- 输出模式:推挽输出可驱动LED(串联220Ω限流电阻)或蜂鸣器(需三极管或MOS管驱动,因为GPIO最大输出电流约40mA)。
- 中断触发:支持上升沿、下降沿、低电平、高电平触发。跌倒检测按钮应使用下降沿触发,并配合软件消抖(延时20-50ms再确认)。
- PWM输出:所有GPIO均可输出PWM信号,用于LED呼吸灯或蜂鸣器音调控制。ESP32的LEDC控制器提供16个通道,频率可调(1Hz-40MHz)。
// GPIO按键输入 + 中断示例(Arduino框架)
const int buttonPin = 4; // GPIO4 连接跌倒按钮
volatile bool fallDetected = false;
void IRAM_ATTR isr() {
fallDetected = true; // 中断服务函数中只置标志位
}
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), isr, FALLING);
}
void loop() {
if (fallDetected) {
delay(50); // 软件消抖
if (digitalRead(buttonPin) == LOW) {
// 确认跌倒,触发报警流程
activateAlarm();
}
fallDetected = false;
}
}
3.3 ADC:模拟信号采集与压力检测
ADC(模数转换器)用于将模拟电压转换为数字值。在老人看护中,ADC最典型的应用是坐垫压力检测——通过薄膜压力传感器(FSR)感知老人是否长时间坐在椅子上。ESP32内置两个ADC:ADC1(8通道,GPIO32-39)和ADC2(10通道,GPIO0-27)。关键限制:ADC2与WiFi不能同时使用,因为WiFi模块会占用ADC2的采样时钟。因此,所有模拟传感器必须连接到ADC1通道。
ADC的精度为12位(0-4095),默认测量范围0-3.3V。但实际使用时,建议将测量范围限制在0-2.5V,因为ESP32的ADC在接近满量程时线性度会下降。若需测量更高电压,需外接分压电阻。对于压力传感器,典型接法为:FSR一端接3.3V,另一端串联10kΩ下拉电阻到GND,中间节点接ADC引脚。当压力增大时,FSR阻值减小,ADC电压升高。
| ADC通道 | GPIO引脚 | 推荐用途 | 注意事项 |
|---|---|---|---|
| ADC1_CH0 | GPIO36 | 坐垫压力传感器 | 只能输入 |
| ADC1_CH3 | GPIO39 | 电池电压监测 | 需分压电阻 |
| ADC1_CH4 | GPIO32 | 环境光传感器 | 用于夜间模式 |
| ADC1_CH5 | GPIO33 | 备用/扩展 | 避免与I2C冲突 |
// ADC读取压力传感器示例
#define PRESSURE_PIN 36 // ADC1_CH0
void setup() {
Serial.begin(115200);
analogReadResolution(12); // 设置12位精度
analogSetPinAttenuation(PRESSURE_PIN, ADC_11db); // 衰减11dB,量程约3.3V
}
void loop() {
int raw = analogRead(PRESSURE_PIN);
float voltage = raw * (3.3f / 4095.0f);
// 根据电压值估算压力等级
if (voltage > 2.0f) {
// 有人坐在椅子上
Serial.println("Occupied");
} else {
Serial.println("Empty");
}
delay(1000);
}
3.4 I2C:连接IMU与外部传感器
I2C(Inter-Integrated Circuit)是一种两线制同步串行总线,使用SDA(数据线)和SCL(时钟线)连接多个设备。在老人看护场景中,I2C主要用于连接IMU惯性测量单元(如MPU6050/MPU9250)来检测跌倒姿态,以及连接OLED显示屏(如SSD1306)显示状态信息。ESP32的I2C接口通过软件配置,可使用任意GPIO作为SDA/SCL,但推荐使用默认引脚:SDA=GPIO21,SCL=GPIO22。
I2C通信速率支持100kHz(标准模式)和400kHz(快速模式)。对于IMU数据读取,建议使用400kHz以降低延迟。每个I2C设备有7位地址,MPU6050的地址为0x68(AD0接地)或0x69(AD0接VCC)。在连接多个设备时,需确保地址不冲突,且总线上拉电阻(通常4.7kΩ到3.3V)已正确安装。
// I2C扫描设备地址示例
#include <Wire.h>
void setup() {
Wire.begin(21, 22); // SDA=GPIO21, SCL=GPIO22
Serial.begin(115200);
Serial.println("Scanning I2C bus...");
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.print("Found device at 0x");
Serial.println(addr, HEX);
}
}
}
void loop() { }
在跌倒检测应用中,IMU通过I2C以100Hz频率输出加速度和角速度数据。ESP32作为I2C主机,需要配置时钟速率为400kHz,并在每次读取时先发送设备地址和寄存器地址,再读取6字节数据(加速度X/Y/Z各2字节)。由于I2C是半双工通信,读取过程中CPU会阻塞等待,因此建议使用DMA或任务调度来避免阻塞主循环。
3.5 WiFi与蓝牙:远程提醒的通信基础
WiFi和蓝牙是ESP32区别于普通单片机的核心优势。在老人看护系统中,WiFi用于将报警信息发送到云端或家属手机,蓝牙则用于近距离设备联动(如连接蓝牙手环)。ESP32的WiFi支持802.11 b/g/n,工作频率2.4GHz,最大发射功率20dBm(100mW)。在室内环境下,WiFi覆盖范围约30-50米,穿墙后信号衰减明显。
WiFi工作模式有三种:Station(STA)——连接路由器;Access Point(AP)——自身作为热点;混杂模式——同时作为STA和AP。在老人看护场景中,推荐使用STA模式连接家庭路由器,通过MQTT协议上报数据。若家庭网络不稳定,可启用AP模式作为备用,让家属手机直接连接ESP32查看状态。
蓝牙方面,ESP32支持经典蓝牙(BR/EDR)和低功耗蓝牙(BLE 4.2)。BLE功耗更低,适合周期性广播状态信息。例如,ESP32每5秒广播一次“老人当前状态”(坐姿/站立/跌倒),家属手机上的APP通过扫描广播包即可获取信息,无需建立连接,功耗极低。
| 通信方式 | 功耗 | 延迟 | 适用场景 | 注意事项 |
|---|---|---|---|---|
| WiFi STA + MQTT | 高(平均80mA) | 1-3秒 | 远程报警、数据上报 | 需路由器,断网需重连 |
| WiFi AP | 高(平均100mA) | 即时 | 现场调试、应急直连 | 手机需切换WiFi网络 |
| BLE 广播 | 低(平均20mA) | 1-5秒 | 近距离状态同步 | 单向通信,无法接收指令 |
| BLE 连接 | 中(平均40mA) | 10-50ms | 手环联动、参数配置 | 需配对,连接稳定 |
// WiFi连接 + MQTT上报示例(使用PubSubClient库)
#include <WiFi.h>
#include <PubSubClient.h>
const char* ssid = "Home_WiFi";
const char* password = "password123";
const char* mqttServer = "192.168.1.100";
const int mqttPort = 1883;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
client.setServer(mqttServer, mqttPort);
client.connect("ESP32_Care_Node");
}
void loop() {
if (!client.connected()) {
client.connect("ESP32_Care_Node");
}
client.loop();
// 检测到跌倒时发布消息
if (fallDetected) {
client.publish("care/alert", "FALL_DETECTED");
}
}
3.6 资源分配与常见误区
在综合老人看护项目中,合理的引脚分配能避免后期调试的诸多麻烦。以下是一个经过验证的资源分配方案:
- GPIO4:跌倒检测按钮(输入+中断)
- GPIO5:蜂鸣器驱动(PWM输出)
- GPIO21/22:I2C总线(IMU + OLED)
- GPIO36:坐垫压力传感器(ADC1_CH0)
- GPIO39:电池电压监测(ADC1_CH3)
- GPIO2:板载LED(状态指示)
- GPIO15:预留(可接门磁传感器)
常见误区包括:
- 误用ADC2通道:当WiFi开启时,ADC2读数会随机跳变。所有模拟信号必须接ADC1。
- 忽略GPIO上电状态:某些GPIO(如GPIO0、GPIO2、GPIO15)在启动时有特殊功能(下载模式、Flash电压选择等),若外部电路影响这些引脚的电平,可能导致无法正常启动。
- I2C地址冲突:多个相同型号的传感器(如两个MPU6050)需要修改AD0引脚地址,否则无法同时工作。
- 供电不足:使用USB供电时,若同时开启WiFi和驱动蜂鸣器,可能导致电压跌落至3.0V以下,系统重启。建议使用5V/2A电源适配器或锂电池+稳压模块。