1. 项目概述
作为一名嵌入式开发工程师,我最近完成了一个基于STM32F103的智能Wi-Fi插座项目。这个项目完美融合了嵌入式控制、无线通信和电力电子技术,实现了家电的远程智能化控制。下面我将详细分享这个项目的设计思路、硬件选型、软件实现以及调试经验。
智能插座作为物联网时代的典型应用,其核心价值在于:
- 通过手机APP远程控制家电开关
- 实时监测用电情况
- 提供过载保护等安全功能
- 支持本地按键应急控制
这个项目特别适合作为嵌入式开发的入门实践,涵盖了GPIO控制、ADC采集、UART通信、I2C显示等基础外设的使用,同时也涉及Wi-Fi联网、TCP通信等物联网关键技术。
2. 硬件设计与选型
2.1 核心硬件架构
整个系统采用模块化设计,主要分为以下几个部分:
- 主控模块:STM32F103C8T6最小系统板
- 通信模块:ESP8266-01S Wi-Fi模块
- 功率控制模块:5V单路继电器
- 电流检测模块:ACS712-5A霍尔传感器
- 显示模块:0.96寸OLED屏幕
- 用户输入模块:两个轻触按键
- 报警模块:有源蜂鸣器
- 电源模块:隔离型5V电源+AMS1117-3.3V稳压
2.2 关键器件选型要点
在选择硬件器件时,我特别考虑了以下几个因素:
-
安全性:强电部分必须与弱电控制端完全隔离。继电器选用带光耦隔离的型号,电源采用隔离型模块。
-
可靠性:主控选择STM32F103系列,工业级芯片,性能稳定。ESP8266选用带金属屏蔽罩的01S版本,抗干扰能力更强。
-
易用性:所有模块都选择市面上常见的开发板形态,无需自己设计PCB,方便初学者快速搭建。
-
成本控制:整套硬件成本控制在80元以内,性价比极高。
特别提醒:ACS712电流传感器输出最大5V,而STM32的ADC输入不能超过3.3V,必须添加分压电路(1kΩ+2kΩ电阻分压),否则会损坏单片机!
2.3 硬件接线详解
2.3.1 控制端接线
控制端采用3.3V供电,主要连接关系如下:
-
STM32与ESP8266:
- PA2(TX) → ESP8266 RX
- PA3(RX) ← ESP8266 TX
- 3.3V → ESP8266 VCC和CH_PD
- 共地连接
-
STM32与继电器/蜂鸣器:
- PB0 → 继电器IN
- PB1 → 蜂鸣器I/O
- 5V供电,共地连接
-
STM32与OLED:
- PB6 → OLED SCL
- PB7 → OLED SDA
- 3.3V供电,共地连接
2.3.2 强电端接线
强电部分需要特别注意安全:
- 市电火线 → 5A保险丝 → 继电器COM端
- 继电器NO端 → 插座火线端
- 市电零线直接接插座零线端
- ACS712串联在火线回路中
重要安全提示:所有强电接线必须断电操作!接线完成后用热缩管和绝缘胶带做好绝缘处理,避免裸露铜线。
3. 软件开发环境搭建
3.1 工具链准备
开发环境采用Keil MDK + STM32CubeMX组合:
- Keil MDK-ARM:代码编写和调试
- STM32CubeMX:图形化配置外设和生成初始化代码
- ST-Link Utility:程序烧录工具
- 串口调试助手:用于调试ESP8266 AT指令
3.2 STM32CubeMX配置
在CubeMX中需要配置以下外设:
- 时钟树:配置为72MHz主频(STM32F103最大频率)
- USART2:115200波特率,用于ESP8266通信
- ADC1:12位分辨率,采样ACS712输出
- I2C1:100kHz,驱动OLED屏幕
- GPIO:
- PB0:推挽输出,控制继电器
- PB1:推挽输出,控制蜂鸣器
- PC0/PC1:上拉输入,连接按键
配置完成后生成MDK-ARM工程,会自动生成所有外设的初始化代码。
4. 软件架构设计
4.1 程序流程图
整个系统采用裸机编程,主循环中按优先级处理各项任务:
- 按键扫描(最高优先级)
- TCP指令解析
- 系统状态更新(电流检测、Wi-Fi状态等)
- OLED刷新显示
4.2 关键功能实现
4.2.1 Wi-Fi通信实现
ESP8266通过AT指令配置,主要流程:
- 发送AT测试指令,确认模块正常
- 设置STA模式:AT+CWMODE=1
- 连接路由器:AT+CWJAP="SSID","PWD"
- 建立TCP服务器:AT+CIPSTART="TCP","0.0.0.0",8080
- 进入透传模式:AT+CIPMODE=1 → AT+CIPSEND
经验分享:ESP8266上电后需要约1秒初始化时间,发送AT指令前最好加个延时,否则可能无响应。
4.2.2 电流检测算法
ACS712输出与电流的关系:
code复制Vout = 2.5V + (0.185V/A × I)
STM32通过ADC采集后,计算实际电流的公式:
code复制I = (ADC_value × 3.3V/4096 × 3 - 2.5V) / 0.185
其中乘以3是因为分压电路将5V分压到3.3V以内。
4.2.3 双控逻辑实现
为了保证手机APP和本地按键控制不冲突,采用以下策略:
- 任何控制源改变状态后,立即同步到另一个控制源
- 过流保护触发后,必须通过按键或APP指令手动复位
- 状态变化时通过OLED和APP同时反馈
5. 核心代码解析
5.1 系统初始化
c复制void System_Init(void)
{
// 初始化系统状态
g_sys.wifi_state = WIFI_DISCONNECT;
g_sys.socket_state = SOCKET_OFF;
g_sys.current = 0.0f;
// 初始化外设状态
RELAY_OFF;
BUZZER_OFF;
// 初始化OLED
OLED_Init();
OLED_Clear();
OLED_ShowString(0,0,"WiFi: Disconnect");
}
5.2 主循环逻辑
c复制while(1)
{
// 1. 按键处理
if(Key_Scan(KEY_ON_OFF_PIN) && !g_sys.over_current_flag)
{
Relay_Control(g_sys.socket_state == ON ? OFF : ON);
System_Send_State();
}
// 2. TCP指令解析
if(g_sys.uart_buf_idx > 0)
{
TCP_Cmd_Parse(g_sys.uart_buf, g_sys.uart_buf_idx);
}
// 3. 系统状态更新
System_Update_State();
HAL_Delay(100);
}
5.3 过流保护实现
c复制void System_Update_State(void)
{
// ADC采集电流
uint32_t adc_val = HAL_ADC_GetValue(&hadc1);
g_sys.current = ADC_Calc_Current(adc_val);
// 过流检测
if(g_sys.current > OVER_CURRENT_THRESH && !g_sys.over_current_flag)
{
Relay_Control(SOCKET_ALARM);
g_sys.over_current_flag = 1;
Buzzer_Alarm(1); // 持续报警
}
// 更新OLED显示
Update_OLED_Display();
}
6. 调试经验与问题解决
6.1 常见问题及解决方法
-
ESP8266无法连接Wi-Fi
- 检查SSID和密码是否正确
- 确保路由器是2.4GHz频段(ESP8266不支持5GHz)
- 尝试在AT+CWJAP指令后增加更长的超时时间(如10秒)
-
继电器状态不稳定
- 检查继电器供电是否充足(5V/1A以上)
- 在继电器线圈两端并联续流二极管(如1N4148)
- 确保STM32 GPIO设置为推挽输出模式
-
电流检测不准确
- 校准ACS712的零点(无电流时输出应为2.5V)
- 检查分压电路是否正常(1kΩ+2kΩ)
- 增加软件滤波(如多次采样取平均)
6.2 性能优化建议
- 增加看门狗定时器,提高系统稳定性
- 实现OTA升级功能,方便远程更新固件
- 添加电量统计功能,记录用电量
- 支持MQTT协议,实现跨局域网控制
7. 项目扩展方向
这个基础框架可以进一步扩展更多实用功能:
- 定时控制:添加RTC模块,实现定时开关
- 语音控制:对接智能音箱平台
- 多路控制:扩展更多继电器通道
- 数据记录:添加SD卡存储用电记录
- 云平台接入:对接阿里云IoT等平台
8. 开发心得
通过这个项目,我总结了以下几点经验:
- 安全第一:强电部分必须严格隔离,做好绝缘防护
- 模块化设计:各功能模块独立开发,最后整合
- 充分测试:先测试弱电部分,再接入强电
- 文档记录:详细记录每个调试步骤和参数
这个项目虽然不算复杂,但涵盖了嵌入式开发的多个关键技术点,非常适合作为学习STM32和物联网开发的实践项目。希望我的分享对大家有所帮助,也欢迎交流讨论更多实现细节。
