1. 项目概述:STM32蓝牙温湿度声光报警系统设计
这个项目本质上是一个典型的物联网边缘节点设计案例。我去年为某农业大棚项目做过类似的方案,核心思路是通过STM32作为主控,实时采集环境温湿度数据,当数值超出预设阈值时触发声光报警,同时通过蓝牙将数据同步到手机APP端。这种系统在温室种植、仓储监控、实验室环境监测等场景都有广泛应用。
从硬件架构看,系统需要处理三个关键功能:环境感知(温湿度采集)、本地报警(声光提示)和无线通信(蓝牙传输)。这三个功能模块的协同工作,构成了完整的闭环控制系统。相比传统有线方案,蓝牙传输的优势在于部署灵活,特别适合中小型场所的临时监测需求。
2. 核心硬件选型与电路设计
2.1 主控芯片选择
STM32F103C8T6是我的首选,这个型号属于"蓝 pill"开发板常用芯片,性价比极高。72MHz主频完全足够处理温湿度数据,内置的12位ADC能保证采集精度,而且有丰富的定时器资源用于PWM控制声光设备。最重要的是,它的USART接口可以直接连接HC-05蓝牙模块。
提示:如果预算充足,可以考虑STM32F4系列,其内置浮点运算单元能简化温湿度补偿算法的实现。
2.2 温湿度传感器对比
DHT22和SHT30是最常见的两种选择:
- DHT22:单总线协议,成本低(约$3),但精度一般(±0.5℃)
- SHT30:I2C接口,精度高(±0.2℃),带温度补偿,价格是DHT22的3倍
对于大多数应用场景,DHT22已经足够。它的典型接线方式如下:
code复制VCC - 3.3V
DATA - PB12(需接4.7K上拉电阻)
GND - GND
2.3 蓝牙模块配置
HC-05模块是最经济的选择,支持SPP协议,可以直接用AT指令配置:
code复制AT+NAME=TH_Alarm // 设置设备名称
AT+PSWD=1234 // 设置配对密码
AT+UART=9600,0,0 // 设置波特率
实测传输距离在开阔场地约10米,足够大多数室内场景使用。
3. 软件架构设计
3.1 主程序流程图
系统采用前后台架构:
- 上电初始化(时钟、GPIO、USART、定时器)
- 进入主循环:
- 每2秒读取DHT22数据
- 检查阈值并控制报警设备
- 通过蓝牙发送数据
- 处理手机端指令
3.2 温湿度采集实现
DHT22的读取时序很关键,这里分享一个稳定的驱动代码:
c复制#define DHT_PIN GPIO_PIN_12
void DHT22_Start(void) {
GPIO_InitTypeDef gpio = {0};
gpio.Pin = DHT_PIN;
gpio.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOB, &gpio);
HAL_GPIO_WritePin(GPIOB, DHT_PIN, GPIO_PIN_RESET);
HAL_Delay(1); // 至少1ms低电平
HAL_GPIO_WritePin(GPIOB, DHT_PIN, GPIO_PIN_SET);
HAL_Delay(30); // 20-40us高电平
}
uint8_t DHT22_ReadByte(void) {
uint8_t data = 0;
for(int i=0; i<8; i++) {
while(!HAL_GPIO_ReadPin(GPIOB, DHT_PIN)); // 等待低电平
uint32_t start = HAL_GetTick();
while(HAL_GPIO_ReadPin(GPIOB, DHT_PIN)); // 测量高电平时间
if(HAL_GetTick()-start > 40) data |= (1<<(7-i));
}
return data;
}
3.3 报警逻辑设计
报警触发采用迟滞比较算法,避免临界值附近的频繁切换:
c复制#define TEMP_HIGH 30.0
#define TEMP_LOW 25.0
#define HUMI_HIGH 80.0
#define HUMI_LOW 60.0
void CheckAlarm(float temp, float humi) {
static uint8_t alarm_state = 0;
if(temp > TEMP_HIGH || humi > HUMI_HIGH) {
HAL_GPIO_WritePin(GPIOC, BUZZER_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, LED_PIN, GPIO_PIN_SET);
alarm_state = 1;
}
else if(temp < TEMP_LOW && humi < HUMI_LOW && alarm_state) {
HAL_GPIO_WritePin(GPIOC, BUZZER_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LED_PIN, GPIO_PIN_RESET);
alarm_state = 0;
}
}
4. 蓝牙通信协议设计
4.1 数据帧格式
采用简单的ASCII协议,方便手机端解析:
code复制$TH,25.6,68.2,0#
字段说明:
- $TH:帧头
- 25.6:温度值
- 68.2:湿度值
- 0:报警状态(0/1)
- #:帧尾
4.2 手机端配置
Android端核心代码示例(Java):
java复制private void connectBluetooth() {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = bluetoothAdapter.getRemoteDevice("00:12:34:56:78:90");
try {
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
socket.connect();
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String data;
while((data = reader.readLine()) != null) {
if(data.startsWith("$TH")) {
String[] values = data.split(",");
float temp = Float.parseFloat(values[1]);
float humi = Float.parseFloat(values[2]);
int alarm = Integer.parseInt(values[3].replace("#",""));
runOnUiThread(() -> {
tempTextView.setText(String.format("%.1f℃", temp));
humiTextView.setText(String.format("%.1f%%", humi));
if(alarm == 1) showAlarmNotification();
});
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
5. 系统优化与实测数据
5.1 低功耗设计
通过以下措施可将功耗降低至3mA@3.3V:
- 使用STM32的Stop模式,每2秒唤醒一次
- 蓝牙模块在不传输时进入AT+SLEEP模式
- 关闭未使用的GPIO时钟
5.2 精度校准方法
实测发现DHT22存在±1℃的偏差,可通过软件校准:
c复制float Temp_Calibrate(float raw) {
return raw * 0.98 + 0.5; // 实测校准系数
}
float Humi_Calibrate(float raw) {
return raw * 1.02 - 1.8;
}
5.3 抗干扰措施
- 温湿度传感器远离MCU和蓝牙模块
- 电源端加100uF+0.1uF电容滤波
- 数据线使用双绞线
- 软件上增加CRC校验
6. 常见问题排查
6.1 DHT22无响应
- 检查上拉电阻(必须4.7K)
- 确认时序严格(起始信号至少18ms低电平)
- 更换传感器(DHT22静电敏感易损坏)
6.2 蓝牙连接不稳定
- 避免2.4G频段干扰(远离WiFi路由器)
- 修改AT+POLAR指令调整发射功率
- 检查天线方向(最好垂直放置)
6.3 报警误触发
- 增加软件滤波(连续3次超限才触发)
- 调整迟滞区间(如温度±2℃)
- 检查电源纹波(建议使用LDO供电)
这个项目最让我意外的是蓝牙传输的稳定性问题。最初版本在金属机柜内测试时,通信距离不足2米。后来改用陶瓷天线并调整发射功率后,即使在有障碍物的情况下也能稳定传输8米以上。另一个教训是DHT22的防潮处理 - 在潮湿环境中,传感器接口容易氧化导致数据异常,后来改用镀金排针解决了这个问题。
