1. 项目概述
最近在做一个挺有意思的小项目——用单片机实现无接触测温。这种技术现在应用场景特别多,从疫情防控到工业检测都能用得上。我用的是一块常见的STM32开发板加上红外温度传感器,整套成本不到200块钱,但精度能达到±0.5℃以内。
这个方案最大的优势是实现了真正的非接触测量。传统的水银温度计或者电子测温枪都需要接触被测物体,在很多场景下既不卫生也不方便。比如在食品加工线上检测产品温度,或者在医院做初步体温筛查,无接触方案明显更实用。
2. 硬件选型与电路设计
2.1 核心器件选型
主控芯片我选了STM32F103C8T6,也就是常说的"蓝莓派"。这款MCU性价比极高,自带12位ADC,完全能满足我们的需求。更重要的是它的开发社区非常活跃,遇到问题很容易找到解决方案。
传感器方面对比了几款常见的红外测温模块:
- MLX90614:精度高(±0.5℃),I2C接口,但价格较贵
- AMG8833:8x8像素阵列,可以测温度分布,但单点精度稍差
- TMP006:价格便宜,但需要复杂的校准
最终选择了MLX90614ESF-BAA,它的测量范围是-40℃~125℃,正好覆盖人体温度范围。这个传感器内部已经做了环境温度补偿,输出就是经过校准的目标物体温度值,省去了很多麻烦。
2.2 电路连接方案
整个系统的电路非常简单:
- MLX90614的SCL接PB6,SDA接PB7(I2C1)
- 3.3V和GND分别接开发板对应引脚
- 加了一个0.1uF的去耦电容
- 为了调试方便,还接了一个0.96寸OLED屏(I2C)
注意:MLX90614的工作电压是3V,千万不要接到5V上,会烧毁传感器!
3. 软件设计与实现
3.1 开发环境搭建
使用STM32CubeMX快速生成工程框架:
- 配置I2C1为标准模式,时钟100kHz
- 开启USART1用于调试输出
- 配置一个定时器用于周期测量
代码主要在Keil MDK中编写,也可以用免费的TrueSTUDIO。我习惯用STM32 HAL库,虽然效率不如LL库高,但开发速度更快。
3.2 关键代码实现
MLX90614的读取流程比较固定:
c复制#define MLX90614_ADDR 0x5A
float readTemp() {
uint8_t data[3];
uint16_t tempData;
float temp;
// 读取RAM中0x07地址的数据(物体温度)
HAL_I2C_Mem_Read(&hi2c1, MLX90614_ADDR<<1, 0x07,
I2C_MEMADD_SIZE_8BIT, data, 3, 100);
tempData = (data[1] << 8) | data[0];
temp = tempData * 0.02 - 273.15; // 转换为摄氏度
return temp;
}
3.3 温度补偿算法
实测发现环境温度对测量结果影响很大,特别是在户外使用时。我加入了二阶补偿算法:
c复制float compensateTemp(float rawTemp, float ambientTemp) {
// 一阶补偿
float compTemp = rawTemp + 0.1*(ambientTemp-25);
// 二阶补偿
if(ambientTemp < 10) {
compTemp += 0.05*(10-ambientTemp);
} else if(ambientTemp > 35) {
compTemp -= 0.03*(ambientTemp-35);
}
return compTemp;
}
这个补偿系数是通过大量实测数据反推出来的,不同传感器可能需要微调。
4. 系统校准与测试
4.1 校准方法
虽然MLX90614出厂时已经校准过,但为了达到最佳精度,建议做两点校准:
- 冰点校准:用冰水混合物(0℃)作为参考
- 体温校准:用标准体温计测量人体温度(约36.5℃)
校准流程:
- 将传感器对准校准源,保持稳定5分钟
- 记录10次测量值取平均
- 计算偏移量并写入EEPROM
4.2 实测数据对比
测试环境:室温25℃,测量距离5cm
| 标准值(℃) | 测量值(℃) | 误差(℃) |
|---|---|---|
| 36.5 | 36.7 | +0.2 |
| 38.0 | 38.2 | +0.2 |
| 40.0 | 40.3 | +0.3 |
| 25.0 | 25.1 | +0.1 |
| 0.0 | -0.2 | -0.2 |
从数据看,在人体温度范围内精度确实能达到±0.3℃以内,完全满足日常使用需求。
5. 实际应用中的问题与解决
5.1 测量距离的影响
红外测温的精度受距离影响很大。MLX90614的最佳测量距离是2-5cm,但实际使用时很难保持这么精确的距离。我通过实验得出了一个距离补偿公式:
c复制float distanceCompensate(float temp, float distance) {
// 距离单位是cm
if(distance > 5) {
return temp - 0.1*(distance-5);
}
return temp;
}
5.2 环境光干扰
强光直射会导致测量值偏高。解决方法:
- 加装遮光罩
- 避开阳光直射的环境使用
- 多次测量取中值
5.3 发射率设置
不同材料的发射率不同,默认设置(0.95)适合大多数有机物。如果测量金属等低发射率物体,需要通过修改传感器配置寄存器来调整。
6. 系统优化与扩展
6.1 低功耗设计
为了做成便携设备,我做了以下优化:
- 将STM32切换到Sleep模式,每2秒唤醒一次
- 关闭不用的外设时钟
- 使用中断唤醒代替轮询
这样整机电流可以从20mA降到3mA左右,用200mAh的电池可以连续工作约60小时。
6.2 无线传输功能
通过加上ESP8266模块,可以实现数据上传到手机APP。关键点:
- 使用AT指令配置WiFi连接
- 采用MQTT协议上传数据
- 手机端用MIT App Inventor快速开发监控界面
6.3 外壳设计与人机交互
3D打印了一个带扳机的外壳,测量时:
- 扣动扳机开始测温
- OLED显示实时温度
- 蜂鸣器提示测量完成
- 超过37.3℃会红灯报警
7. 项目总结与改进方向
这个项目从硬件搭建到软件调试总共花了约两周时间,中间遇到了不少坑。最大的收获是理解了红外测温的各种影响因素,特别是环境温度和距离的补偿算法,这些在芯片手册里都不会详细说明。
下一步计划:
- 加入人脸检测功能,自动定位额头区域
- 开发多目标同时测量功能
- 研究更高精度的校准方法
整个系统的BOM成本约180元,如果量产的话可以控制在100元以内。相比市面上的同类产品,这个方案完全开源可定制,特别适合二次开发。