去年夏天,我卧室的窗帘控制系统经历了一次彻底的技术升级。原本手动拉合的窗帘被我改造成了一套基于STM32的智能控制系统,现在无论是烈日当空还是突然下雨,窗帘都能自动调节,甚至能通过语音指令控制开合。这个项目不仅解决了日常生活中的实际问题,更让我深入理解了嵌入式系统在智能家居中的应用逻辑。
这套系统的核心设计理念是环境感知与自动响应。通过光敏电阻实时监测光照强度,雨滴传感器检测降水情况,DHT11采集温湿度数据,系统能够自主判断何时该打开窗帘通风透光,何时该关闭窗帘防雨防潮。在自动模式下,当检测到环境温度超过30℃或湿度高于70%时,系统会启动风扇进行降温除湿;光照强度低于100lux时则自动关闭窗帘。所有环境参数和工作状态都实时显示在1.8寸TFT液晶屏上,用户也可以通过按键、红外遥控、语音识别或手机APP等多种方式进行交互控制。
选择STM32F103C8T6作为主控芯片主要基于三点考虑:首先是72MHz的主频足以处理多传感器数据融合和实时控制需求;其次是内置的64KB Flash和20KB SRAM能满足程序存储和运行需求;最重要的是其丰富的外设接口(5个USART、2个SPI、2个I2C)可以轻松连接各类传感器和显示模块。实际电路设计中,我在芯片的NRST引脚添加了10kΩ上拉电阻和0.1μF电容组成复位电路,并在晶振电路并联了1MΩ的反馈电阻以提高起振可靠性。
关键提示:STM32的BOOT0引脚必须通过10kΩ电阻接地或接3.3V,否则可能导致程序无法正常运行。我在初期调试时就因为忘记连接这个电阻,浪费了半天时间排查问题。
光照检测采用GL5528光敏电阻,其光谱响应特性与人眼非常接近。电路设计上,我将光敏电阻与10kΩ固定电阻组成分压电路,输出端接入STM32的PA0引脚(ADC1通道0)。实际测试发现,在室内自然光环境下,ADC值通常在800-3000之间波动(12位ADC,3.3V参考电压)。雨滴传感器选用的是常见的LM393比较器模块,直接输出数字信号给STM32的PA1引脚,当雨滴触发电极时输出低电平。
温湿度模块选用DHT11而非更精确的DHT22,主要考虑其响应速度更快(1Hz采样率)且成本更低。接线时特别注意数据线需要上拉4.7kΩ电阻,且每次读取间隔不得小于1秒。我在程序中使用GPIO的推挽输出模式驱动数据线,读取时切换为浮空输入模式,通过精确的时序控制实现数据采集。
窗帘开合控制采用SG90舵机,其工作角度为0-180度,对应窗帘的全闭到全开状态。舵机控制信号线连接STM32的PA8引脚(TIM1_CH1),通过PWM信号控制位置。实际调试中发现,舵机在动作瞬间会产生约300mA的电流冲击,因此必须单独供电,不能直接使用STM32开发板的3.3V输出。
风扇驱动采用5V继电器模块,由STM32的PA4引脚通过S8050三极管驱动。电路设计时,我在继电器线圈两端并联了1N4148续流二极管,防止关断时产生的反向电动势损坏三极管。继电器的常开触点连接12V直流风扇,当温湿度超过设定阈值时启动。
系统软件采用模块化设计,主程序通过状态机实现模式切换。上电后首先初始化各硬件模块,然后进入主循环不断检测模式切换标志。三种工作模式对应不同的处理函数:
c复制while(1){
switch(System_Mode){
case AUTO_MODE: AutoMode_Process(); break;
case MANUAL_MODE:ManualMode_Process();break;
case TIMER_MODE: TimerMode_Process();break;
}
Sensor_Update(); // 更新传感器数据
Display_Refresh(); // 刷新TFT显示
Voice_Process(); // 处理语音指令
WiFi_Process(); // 处理网络数据
}
在自动模式下,系统每500ms检测一次环境参数,根据预设阈值决定执行机构动作。为提高系统稳定性,我采用了软件滤波算法:对光照值进行滑动平均滤波(窗口大小=5),对雨滴信号进行防抖处理(连续3次检测到才确认状态变化)。
虽然STM32F103没有RTOS支持,但通过合理设计依然实现了准并行的多任务处理。关键点在于:
红外遥控解码采用了外部中断+定时器捕获的方式。当红外接收头输出下降沿时触发EXTI中断,在中断服务函数中启动TIM3计时,通过测量脉冲宽度判断NEC协议的数据位。实测发现,在距离遥控器2米范围内,解码成功率可达100%。
系统需要保存的配置参数包括:
这些参数存储在STM32内部的Flash最后一页(Page 127)。为防止频繁擦写导致Flash损坏,我设计了双缓冲机制:只有当参数确实发生变化时才会执行擦除写入操作,且两次写入间隔不得小于10秒。写入前会先计算CRC16校验码,读取时进行校验确认数据完整性。
1.8寸TFT液晶(ST7735S驱动)采用SPI接口与STM32连接,时钟频率设置为18MHz。显示内容分为三个区域:
为提高刷新效率,我实现了局部刷新机制:只有当某区域数据发生变化时才重绘该区域,而非全屏刷新。例如温度值更新时,仅重绘温度数字所在的矩形区域(使用LCD_SetWindows函数设定刷新范围)。
LD3322语音识别模块通过并行总线与STM32连接,关键配置步骤如下:
实际使用中发现,在环境噪声超过60dB时识别率会明显下降。为此,我在软件中添加了二次确认机制:当识别到指令后,系统会语音提示"是否执行XX操作",需用户再次确认才执行。
WiFi通信基于ESP8266模块,工作模式配置为STA+AP双模式。手机APP通过TCP协议与模块通信,数据格式采用自定义的JSON协议:
json复制{
"type": "control",
"cmd": "set_curtain",
"value": "open",
"time": "2023-07-15 14:30:00"
}
为降低功耗,ESP8266在无操作时进入轻度睡眠模式(通过AT+GSLP=1000设置1秒唤醒间隔)。当收到手机指令或本地传感器触发异常时才会完全激活。
光敏电阻的ADC值需要转换为实际照度(lux)。我采用分段线性拟合方法:
温湿度阈值设定需要考虑人体舒适区:
在初期测试中,发现以下干扰问题:
系统在不同工作模式下的电流消耗:
通过优化,将自动模式下的平均功耗降至15mA左右(18650电池可续航约一周):
这套系统在实际使用半年后,我又进行了几项功能增强:
一个特别实用的改进是增加了"场景模式":比如设置"影院模式"时,窗帘会自动关闭、灯光调暗、风扇设为静音。这通过定义一组预设参数实现,用户可以通过语音或APP快速切换。