一、任务介绍
本次2025 Make Blocks(第二期)活动中,我选择的为任务11:数字外设、时钟-自命题。计划在第一期的基础上,添加基于IIC的数字外设,实现温度、湿度、气压、陀螺仪等传感器数据的采集与分析。
二、模块介绍
设计框图
本次硬件设计在第一期ESP32-PICO-V3-02最小系统的基础上进行了功能性优化与结构精简。一方面,针对系统资源占用情况,合理裁剪未使用的I/O引脚,提升了电路布局的紧凑性;另一方面,新增一路IIC数字传感器接口,分别接入环境温湿度(SHT30)、气压高度(BMP390)与六轴惯性(BMI323)等环境传感器模块,极大丰富了系统的数据感知维度与功能拓展能力,使系统不仅具备了对周边环境变化(温度、湿度、气压)的实时监测能力,还可基于陀螺仪与加速度信息实现更灵敏的人机交互识别。
选型介绍
高精度气压与高度传感器
BMP390是Bosch推出的一款超高精度的数字气压传感器,采用I²C或SPI通信接口,支持16位至24位输出分辨率,具备±0.03 hPa的气压精度,对应高度精度可达±2.5 cm,远优于常见的BMP180/BMP280系列。该传感器集成温度补偿和低噪声设计,适用于精准海拔变化检测等应用场景。其封装小巧、功耗极低,适合嵌入式低功耗系统部署。
环境温湿度传感器
SHT30是Sensirion公司推出的高性价比温湿度传感器,具备±2% RH湿度精度和±0.3°C温度精度,支持I²C接口输出,响应时间快,稳定性高。该传感器内置校准电路、温湿度补偿算法与CRC校验机制,保障数据准确性与可靠性,长期漂移控制在极低范围。在本项目中,SHT30可实现对办公、寝室等环境温湿状态的实时监测,为App端健康提醒、天气联动提供数据支撑。模块体积紧凑,价格适中,非常适合成本敏感型消费类电子产品。
惯性测量单元(IMU)
BMI323是Bosch Sensortec推出的一款低功耗六轴惯性传感器,集成三轴加速度计与三轴陀螺仪,支持I²C/SPI双接口输出,具备高达1600Hz的数据输出率与灵活的量程配置(±2g~±16g、±125°/s~±2000°/s)。该器件内置FIFO缓存与运动检测引擎,可实现敲击识别、拿起检测、翻转触发等智能功能,适用于智能穿戴、运动感知和静音交互等场景。
在智能水杯垫中,BMI323可用于精准检测水杯拿放、震动过滤以及用户午休后自然唤醒的微动作识别。六轴数据融合不仅提升状态识别鲁棒性,也为后续扩展手势交互等功能提供基础。其低功耗运行模式(<1mA)和小型封装使其非常适合本项目对续航与空间的双重要求。
三、模块设计
原理图
在原理图部分,主要是在第一期的基础上新增了IIC数字外设设计,包括BMP390,SHT30,BMI323,从而实现温度、湿度、气压、陀螺仪等数据的采集与分析。其中ist8310为冗余设计,在本期中并未使用到。
PCB
PCB设计中,我们将形状从之前核心板的长方形修改为了圆形,从而便于适配后期外壳的设计。
实物图
四、软件调试介绍
BMP390测试
基于 Adafruit 官方 BMP3XX 库,实现对 BMP390 气压与温度传感器的初始化、配置与数据读取,并通过串口输出温度(°C)、压力(hPa)与估算高度(m)数据,从而验证BMP390设备能否正常工作。关键代码如下:
1. I²C初始化与传感器连接
Wire.begin(SDA_PIN, SCL_PIN);
if (!bmp.begin_I2C(0x76, &Wire)) {
Serial.println("Could not find a valid BMP3 sensor, check wiring!");
while (1);
}
首先初始化 IIC 总线,指定 SDA/SCL 引脚,随后通过 begin_I2C()
尝试与 BMP390 传感器建立通信。默认地址为 0x76
,符合PCB设计中 SDO口 接地时的地址设定。
2. 传感器配置:过采样与滤波设置
bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
bmp.setOutputDataRate(BMP3_ODR_50_HZ);
接着配置传感器的工作参数,包括温度与气压的过采样倍率、IIR 滤波器系数以及数据输出频率。8倍温度过采样和4倍压力过采样有助于提高精度,适合静态或低动态场景。IIR 滤波系数设置为3,可有效滤除短时间噪声波动。数据输出频率设为 50Hz。
3. 数据读取执行
if (! bmp.performReading()) {
Serial.println("Failed to perform reading :(");
return;
}
在主循环中,每轮数据读取前调用 performReading()
函数执行一次完整采样并更新内部缓存。该函数会自动触发传感器采样并等待数据完成,是使用 Adafruit 封装库的标准调用流程。若读取失败,程序将输出提示并跳过本次打印。
4. 温度与气压打印
Serial.print("Temperature = ");
Serial.print(bmp.temperature);
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bmp.pressure / 100.0);
Serial.println(" hPa");
读取完成后,依次输出当前环境的温度与气压值,其中温度以摄氏度(°C)为单位,气压单位转换为百帕(hPa)。由于 Adafruit 库已在内部封装原始数据读取与浮点转换,因此无需开发者自行计算 LSB 转换,极大提升了开发效率与稳定性。该输出可直接用于调试对比气候变化趋势,或用于高度估算。
5. 高度估算与海平面压力补偿
Serial.print("Approx. Altitude = ");
Serial.print(bmp.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(" m");
最后,基于当前读取到的气压值,调用 readAltitude()
估算海拔高度。该方法内部基于国际标准大气公式,将当前压力与设定的海平面压力(默认 1013.25 hPa)对比换算为相对高度。
SHT30测试
基于 Sensirion 官方 SHT3x 驱动库,实现对 SHT30 温湿度传感器的初始化、采样与数据读取,并通过串口输出当前环境的温度(°C)与相对湿度(%RH)数据,从而验证 SHT30 设备的通信与传感功能是否正常。关键代码如下:
1. IIC初始化
Wire.begin(SDA_PIN, SCL_PIN);
ClosedCube_SHT31D sht3xd;
首先初始化 IIC 总线并创建传感器对象 sht3xd
,用于后续封装函数调用。
2. 传感器地址初始化与序列号读取
sht3xd.begin(0x44);
Serial.println(sht3xd.readSerialNumber());
之后将传感器初始化到地址 0x44
(SHT30 默认地址),并尝试读取其唯一序列号以确认连接是否成功。若读取失败,将输出 0
或错误码,通常意味着通信异常。
3. 启动周期性测量模式(Periodic Mode)
sht3xd.periodicStart(SHT3XD_REPEATABILITY_HIGH, SHT3XD_FREQUENCY_10HZ);
之后调用函数启动周期采样模式,设置为高重复性(即高精度)和10Hz采样频率。周期模式是 SHT3x 特有特性,能在后台自动完成采样并缓存结果,降低主控资源消耗并提升读取效率。
4. 数据读取与错误处理
SHT31D result = sht3xd.periodicFetchData();
程序循环中调用 periodicFetchData()
读取最新的温湿度数据封装结构体 SHT31D
,其中包含温度 t
、湿度 rh
以及错误码字段 error
。该机制避免手动处理原始寄存器和数据位,提升代码简洁性和安全性。若读取失败,返回的错误码会被打印到串口,方便调试定位。
5. 串口格式化输出
Serial.print(result.t);
Serial.print("C, RH=");
Serial.print(result.rh);
Serial.println("%");
一旦数据采集成功,系统会将当前温度与湿度以标准文本格式输出到串口,单位分别为摄氏度(°C)与相对湿度(%RH)。该输出适配人类可读格式,适合调试观察、实验记录或接入串口数据采集平台,验证传感器精度与环境响应特性。
BMI323测试
为验证六轴惯性传感器 BMI323 的正常通信与数据采集功能,我们编写了基于 Arduino 平台Wire 库的调试程序,实现了传感器的 IIC 通讯初始化、功能配置、数据采样与串口输出。关键代码如下:
1. IIC初始化配置
#define SDA_PIN 15
#define SCL_PIN 13
Wire.begin(SDA_PIN, SCL_PIN);
Wire.setClock(400000); // 400kHz I2C clock
首先初始化 IIC 总线,指定使用的 SDA 和 SCL 引脚,并将通信速率设置为 400kHz 的快速模式。在默认模式(100kHz)下,读取六轴数据可能存在响应滞后,因此此处通过设定较高的速率提升数据吞吐能力。SDA 和 SCL 分别对应 BMI323 的数据与时钟引脚,需确保外部已加上合适的上拉电阻(如4.7kΩ)以维持总线高电平稳定。
2. 芯片 ID 读取与地址确认
uint16_t chipID = readRegister16(CHIP_ID_REG, BMI323_I2C_ADDR_1);
if ((chipID & 0xFF) == 0x43 || (chipID & 0xFF) == 0x41) {
bmi323_i2c_addr = BMI323_I2C_ADDR_1;
}
该段用于读取 BMI323 的芯片 ID(地址 0x00)以确认器件是否连接正常。芯片的低8位 ID 预计为 0x43 或 0x41,根据官方文档判定是否为有效识别。程序使用此判断结果设置通信地址并继续后续初始化,否则中止执行。这一步用于调试判断 IIC 是否连通。
3. 软件复位指令
writeRegister16(CMD_REG, SOFT_RESET_CMD);
delay(5);
之后向 BMI323 的命令寄存器(0x7E)写入特定的软复位指令(0xDEAF),以清除传感器上电后可能存在的异常状态或历史配置。复位执行后传感器内部寄存器恢复出厂默认值,确保接下来的初始化配置具备一致的基础状态。延时5ms用于等待设备内部重启完成,这是确保可靠初始化的重要步骤。
4. Feature Engine 启动流程
writeRegister16(FEATURE_IO0_REG, 0x0000);
writeRegister16(FEATURE_IO2_REG, 0x012C);
writeRegister16(FEATURE_IO_STATUS_REG, 0x0001);
writeRegister16(FEATURE_CTRL_REG, 0x0001);
BMI323 的高级功能(如运动检测与传感融合)需要启用 Feature Engine,该段代码完成相关寄存器的设置与启动流程。首先清除状态,然后配置启动参数,最后通过控制寄存器触发功能模块。此处还包含轮询机制判断启动是否成功,是确保传感器能返回有效加速度/陀螺仪数据的前提。
5. 原始数据读取与物理单位转换
uint16_t accX = readRegister16(ACC_DATA_X_REG);
float ax = convertAccelData(accX); // 转换为 g 单位
接着就是读取 BMI323 的加速度 X 轴原始数据寄存器,并将其转换为标准重力单位(g)。传感器输出为有符号16位整数,代表 ±8g 范围内的加速度。转换函数 convertAccelData()
使用当前量程下的 LSB 值 进行归一化处理。该机制同样适用于陀螺仪数据,确保串口输出为可直接理解的物理量,便于分析与调试。
6. 串口定时输出与数据有效性检查
void loop() {
// Limit output to 20Hz
unsigned long currentTime = millis();
if (currentTime - lastPrintTime < printInterval) return;
lastPrintTime = currentTime;
// Read sensor data
uint16_t accX = readRegister16(ACC_DATA_X_REG);
uint16_t accY = readRegister16(ACC_DATA_Y_REG);
uint16_t accZ = readRegister16(ACC_DATA_Z_REG);
uint16_t gyrX = readRegister16(GYR_DATA_X_REG);
uint16_t gyrY = readRegister16(GYR_DATA_Y_REG);
uint16_t gyrZ = readRegister16(GYR_DATA_Z_REG);
uint16_t tempRaw = readRegister16(TEMP_DATA_REG);
// Convert to physical units
float ax = convertAccelData(accX);
float ay = convertAccelData(accY);
float az = convertAccelData(accZ);
float gx = convertGyroData(gyrX);
float gy = convertGyroData(gyrY);
float gz = convertGyroData(gyrZ);
float temp = convertTempData(tempRaw);
// Print valid data in CSV format
if (!isnan(ax) && !isnan(ay) && !isnan(az) &&
!isnan(gx) && !isnan(gy) && !isnan(gz)) {
Serial.print(ax, 3); Serial.print(",");
Serial.print(ay, 3); Serial.print(",");
Serial.print(az, 3); Serial.print(",");
Serial.print(gx, 2); Serial.print(",");
Serial.print(gy, 2); Serial.print(",");
Serial.print(gz, 2); Serial.print(",");
Serial.println(isnan(temp) ? "NAN" : String(temp, 1));
}
}
该段代码控制数据输出频率,并将六轴传感器数据和温度值输出至串口。通过时间差限制,从而控制数据的采集频率。
五、功能展示
BMP390测试
SHT30测试
BMI323测试
六、心得体会
感谢得捷电子与硬禾提供的这次学习的机会。本次硬件设计过程中,在第一期核心板的基础上顺利集成了三种IIC传感器,完成了温湿度、气压和六轴姿态数据的采集与调试,进一步完善了系统的环境感知能力。通过实际调试,我加深了对I²C通信与传感器配置的理解,取得了不小的收获。