1. 项目概述
这个DIY温湿度监测系统由三个核心硬件模块组成:主控采用国产PY32F002AF15P6TU单片机,传感器选用SHT40-AD1B-R2高精度数字温湿度芯片,显示部分使用0.96寸TFT IPS屏幕。整套方案成本控制在30元以内,实测温湿度测量误差分别小于±0.2℃和±1.5%RH,刷新率可达2次/秒,特别适合需要便携监测的种植箱、实验室、仓储等场景。
我选择这个组合主要基于三点考量:首先PY32F002作为ARM Cortex-M0+内核MCU,48MHz主频完全满足数据处理需求,且QFN20封装体积仅3x3mm;其次SHT40是Sensirion第四代传感器,在-10~85℃范围内保持±1.5%RH精度;最后0.96寸IPS屏170°可视角度解决了传统OLED侧面看不清的问题。这三个器件通过I2C总线连接,硬件上仅需4根导线即可完成系统搭建。
2. 硬件选型与电路设计
2.1 主控芯片特性解析
PY32F002AF15P6TU这颗国产MCU的性价比令人惊喜。其关键参数包括:
- 32位Cortex-M0+内核@48MHz
- 16KB Flash + 2KB SRAM
- 1个12位ADC(1Msps)
- 2个USART、1个I2C、1个SPI
- 工作电压1.7-5.5V
- 待机电流仅1.5μA
实际使用中发现其I2C接口在400kHz速率下稳定性良好,配合硬件CRC校验可确保数据传输可靠。需要注意的是,该芯片的SWD调试接口与GPIO复用,建议在PCB设计时预留调试焊盘。
2.2 传感器电路设计要点
SHT40-AD1B-R2的典型应用电路如下:
code复制VDD(3.3V) --┬-- 100nF电容接地
|
SHT40 SCL -- 4.7k上拉电阻--3.3V
SDA -- 4.7k上拉电阻--3.3V
ADDR -- GND(地址0x44)
GND -- 接地
特别注意:
- 上拉电阻值需根据总线长度调整,30cm内导线用4.7kΩ即可
- VDD引脚必须并联100nF去耦电容,否则可能引起测量值跳变
- 传感器与MCU共地非常重要,我曾因接地不良导致数据异常
2.3 显示模块接口优化
0.96寸TFT IPS屏(ST7735S驱动)的硬件连接方案:
code复制屏引脚 PY32F002引脚
VCC 3.3V
GND GND
SCL PB6(I2C1_SCL)
SDA PB7(I2C1_SDA)
RES PA0(需软件控制)
DC PA1(数据/命令选择)
CS PA2(片选,可固定接地)
BLK PA3(PWM调光)
实测发现,将背光控制引脚接入PWM可实现0-100%亮度调节,在暗光环境下非常实用。屏幕初始化时需要严格按照时序发送命令序列,具体代码将在软件部分详述。
3. 软件开发与关键代码
3.1 开发环境搭建
使用Keil MDK进行开发,需要特别注意:
- 安装PY32F0xx_DFP设备支持包
- 配置Debug选项为SWD模式
- 设置优化等级为-O1(过高优化可能导致时序错误)
工程目录结构建议:
code复制/Drivers
/PY32F0xx_HAL_Driver // 官方库
/SHT40 // 传感器驱动
/ST7735 // 显示驱动
/Application
/main.c // 主程序
/i2c.c // I2C底层
/ui.c // 界面逻辑
3.2 SHT40驱动实现
传感器初始化关键代码:
c复制#define SHT40_ADDR 0x44
uint8_t sht40_init(void)
{
uint8_t cmd[1] = {0xFD}; // 高精度测量命令
if(HAL_I2C_Master_Transmit(&hi2c1, SHT40_ADDR<<1, cmd, 1, 100) != HAL_OK)
return 0;
HAL_Delay(10); // 等待测量完成
return 1;
}
数据读取处理函数:
c复制void sht40_read(float *temp, float *humi)
{
uint8_t data[6];
uint16_t raw_temp, raw_humi;
HAL_I2C_Master_Receive(&hi2c1, SHT40_ADDR<<1, data, 6, 100);
raw_temp = (data[0] << 8) | data[1];
raw_humi = (data[3] << 8) | data[4];
*temp = -45 + 175 * (float)raw_temp / 65535;
*humi = -6 + 125 * (float)raw_humi / 65535;
*humi = (*humi < 0) ? 0 : (*humi > 100) ? 100 : *humi;
}
重要提示:SHT40的CRC校验不可省略,实际使用中曾因忽略校验导致显示异常值。完整代码应包含CRC8校验函数。
3.3 显示界面设计
采用双层缓冲机制避免闪烁:
c复制uint8_t buffer1[128][80]; // 前缓冲区
uint8_t buffer2[128][80]; // 后缓冲区
void update_display(void)
{
// 在后缓冲区绘制
draw_background(buffer2);
draw_temperature(buffer2, current_temp);
draw_humidity(buffer2, current_humi);
// 交换缓冲区
ST7735_DrawBitmap(0, 0, 128, 80, (uint8_t*)buffer2);
swap_buffers();
}
温度显示采用大字体设计:
c复制void draw_big_number(uint8_t x, uint8_t y, uint8_t num)
{
const uint8_t font[10][5] = {...}; // 5x7点阵字模
for(int i=0; i<5; i++)
for(int j=0; j<7; j++)
if(font[num][i] & (1<<j))
draw_pixel(x+i, y+j, COLOR_WHITE);
}
4. 系统优化与实测数据
4.1 低功耗设计技巧
通过以下措施将系统平均功耗降至1.2mA:
- 设置MCU在测量间隙进入STOP模式
- 显示屏开启30%亮度PWM调光
- 传感器采用单次测量模式(非连续模式)
关键代码实现:
c复制void enter_low_power(void)
{
HAL_SuspendTick();
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
SystemClock_Config(); // 唤醒后需重新配置时钟
}
4.2 精度校准方法
通过三点校准提升测量精度:
- 冰水混合物(0℃)校准低温点
- 沸水(100℃)校准高温点
- 饱和盐溶液(75%RH)校准湿度
校准公式:
code复制T_calibrated = 0.98 * T_raw + 0.5
H_calibrated = 1.02 * H_raw - 1.8
实测数据对比:
| 环境条件 | 传感器读数 | 标准值 | 误差 |
|---|---|---|---|
| 25℃/50%RH | 25.1℃/51%RH | 25.0℃/50%RH | +0.1℃/+1%RH |
| 35℃/80%RH | 34.8℃/81%RH | 35.0℃/80%RH | -0.2℃/+1%RH |
| 10℃/30%RH | 9.9℃/29%RH | 10.0℃/30%RH | -0.1℃/-1%RH |
4.3 抗干扰措施
遇到过的典型问题及解决方案:
- I2C总线受干扰导致数据错误
- 解决方法:将SCL/SDA走线缩短至10cm内,并加4.7kΩ上拉
- 显示屏在低温下出现残影
- 解决方法:在初始化序列后增加0x36命令设置BGR模式
- 电池供电时电压波动影响ADC
- 解决方法:增加LC滤波电路,软件端采用滑动平均滤波
5. 进阶功能扩展
5.1 数据记录功能
利用PY32F002内部Flash模拟EEPROM:
c复制#define LOG_START_ADDR 0x08003C00 // Flash最后一页
void save_log(float temp, float humi)
{
uint32_t data = ((uint16_t)(temp*10)<<16) | (uint16_t)(humi*10);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, LOG_START_ADDR + log_index*4, data);
log_index = (log_index + 1) % 256; // 循环存储
}
5.2 无线传输方案
通过预留的USART接口可连接蓝牙模块(如HC-05):
code复制PY32F002 HC-05
PA9(TX) RX
PA10(RX) TX
3.3V VCC
GND GND
需注意蓝牙模块的启动电流可能达到40mA,建议单独供电或增加大容量电容。
5.3 外壳设计与安装
推荐采用3D打印外壳,关键设计参数:
- 主体尺寸:45mm×30mm×15mm
- 屏幕开孔:24.5mm×14.5mm(需留0.5mm余量)
- 散热孔:直径1mm,间距3mm阵列
- 安装孔:M2螺丝孔位
实际安装时,建议在传感器周围填充导热硅胶以提升温度响应速度,同时避免阳光直射显示屏。