1. 智能插座开发背景与需求解析
十年前我第一次接触智能家居时,就被一个简单问题困扰:如何用手机远程控制客厅的落地灯?当时市面上的智能插座动辄三四百元,而今天我们用一块STM32F103开发板就能实现相同功能。这种技术民主化进程正是嵌入式开发的魅力所在。
智能Wi-Fi插座本质上是一个带无线连接功能的继电器控制器,其核心需求可分解为:
- 可靠的电气控制(负载能力10A/220V)
- 实时状态反馈(开关状态、功耗监测)
- 低延迟远程控制(APP/云端指令响应<1s)
- 安全防护(过流保护、电气隔离)
选择STM32F103C8T6作为主控主要基于三点考量:首先是其72MHz主频足够处理网络协议栈和控制逻辑;其次是丰富的外设资源(3个USART、2个SPI、2个I2C);最重要的是其性价比——零售价仅12元左右,批量采购可低至8元。
2. 硬件架构设计要点
2.1 核心电路设计
整个硬件系统采用模块化设计,主要包含:
- 电源模块:220V转5V的AC-DC电路(选用HLK-PM01模块)
- 主控模块:STM32最小系统(8MHz晶振+复位电路)
- 继电器驱动:5V磁保持继电器+光耦隔离(TLP281-4)
- Wi-Fi模块:ESP-01S(AT指令模式)
- 计量模块:HLW8032电能计量IC
关键提示:继电器一定要选择磁保持型!普通继电器长期通电会发热严重,而磁保持型仅在状态切换时耗电,实测待机功耗可降低87%。
2.2 PCB布局注意事项
四层板设计中需特别注意:
- 强电部分(L/N线)与其他线路保持≥3mm间距
- 继电器线圈两端并联1N4148续流二极管
- Wi-Fi天线区域做净空处理(禁止铺铜和走线)
- 所有数字地通过0Ω电阻单点连接到主地
实测证明,不规范的PCB布局会导致两个典型问题:Wi-Fi信号强度波动(RSSI<-80dBm)和误触发继电器。我们的解决方案是:
- 在继电器控制线上串联100Ω电阻
- 在STM32的GPIO口添加10nF去耦电容
- 采用"日"字形地线布局
3. 嵌入式软件实现
3.1 开发环境搭建
使用Keil MDK-ARM V5进行开发,关键配置如下:
- Device选择STMicroelectronics→STM32F103C8
- Target→ARM Compiler选择V6.14
- C/C++选项卡添加宏定义:USE_STDPERIPH_DRIVER
外设驱动采用标准库开发,主要初始化流程:
c复制void Hardware_Init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
// 继电器控制引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// USART2用于Wi-Fi模块
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART2, &USART_InitStructure);
}
3.2 Wi-Fi通信协议设计
ESP-01S模块采用AT指令交互,我们设计了简化的通信协议:
| 指令类型 | 格式示例 | 说明 |
|---|---|---|
| 控制指令 | CTRL:1 | 1开启/0关闭 |
| 状态查询 | GET:STAT | 返回当前状态 |
| 功耗数据 | GET:POW | 返回当前功率 |
在STM32中实现环形缓冲区处理串口数据:
c复制#define BUF_SIZE 256
typedef struct {
uint8_t buffer[BUF_SIZE];
uint16_t head;
uint16_t tail;
} RingBuffer;
void USART2_IRQHandler(void) {
if(USART_GetITStatus(USART2, USART_IT_RXNE)) {
uint8_t data = USART_ReceiveData(USART2);
ringBuffer.buffer[ringBuffer.head] = data;
ringBuffer.head = (ringBuffer.head + 1) % BUF_SIZE;
}
}
4. 云端交互实现
4.1 MQTT协议接入
选用EMQX作为MQTT Broker,关键配置参数:
- 心跳间隔:60秒
- QoS等级:1(至少送达一次)
- 遗嘱消息:offline(异常断开时发布)
主题设计采用分层结构:
- 控制主题:device/{{deviceID}}/set
- 状态主题:device/{{deviceID}}/state
- 能耗主题:device/{{deviceID}}/energy
4.2 固件OTA升级
通过HTTPS实现安全升级,流程包括:
- 查询版本信息(GET /api/version)
- 下载固件(GET /api/firmware)
- 校验MD5(确保完整性)
- 跳转到Bootloader
关键的安全措施:
- 每次传输限制512字节数据包
- 启用TLS1.2加密传输
- 双Bank Flash设计(Bank1运行,Bank2更新)
5. 实测性能与优化
5.1 压力测试数据
在以下极端条件下连续运行72小时:
- 85%额定负载(1870W)
- 每5分钟切换状态
- Wi-Fi信号强度-75dBm
测试结果:
- 平均响应延迟:436ms
- 指令丢失率:0.17%
- 最大温升:22.3℃(继电器触点处)
5.2 低功耗优化技巧
通过以下措施将待机功耗从3.2W降至0.8W:
- 关闭未使用的外设时钟(ADC、TIM3等)
- 采用事件唤醒机制(代替轮询)
- 动态调整CPU频率(运行模式72MHz,空闲模式8MHz)
- 优化Wi-Fi心跳包间隔(从60s延长至300s)
具体实现代码:
c复制void Enter_LowPower_Mode(void) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
// 唤醒后恢复时钟
SystemInit();
}
6. 生产注意事项
6.1 安规认证要点
通过CCC认证需要特别注意:
- 爬电距离:L-N之间≥3.0mm
- 抗电强度:2000V AC/1分钟不击穿
- 灼热丝测试:850℃/30秒不起燃
6.2 量产测试方案
我们设计的测试工装包含:
- 负载测试仪(模拟不同功率负载)
- 网络分析仪(检测Wi-Fi性能)
- 自动化测试脚本(Python+PyVISA)
典型测试用例:
python复制def test_relay_switch():
dut.send_at('CTRL:1')
time.sleep(1)
assert power_meter.read() > 1000 # 确认继电器已吸合
dut.send_at('CTRL:0')
assert relay_monitor.get_state() == 'OFF'
这个项目最让我意外的发现是:磁保持继电器在10万次切换后,触点电阻仅增加2.3mΩ,远优于传统继电器的表现。建议在PCB上预留电流检测互感器的位置,后期扩展能耗统计功能会非常方便
