发布时间:
目录
一、介绍 #
我是一个软件开发者,心血来潮想 diy 远程控制热水器烧水的控制器,热水器功率较大一直开着费电,所以我就想能不能利用我毕生所学自己实战一下。选择 51 单片机因为简单入门快。这个过程中也遇到了大量问题,在黑电子论坛各位大佬的帮助下和 AI
的加持下完成。
二、功能 #
- 远程控制(通过 ESP-01S WiFi 模块)
- 指示灯反馈控制状态
- 电压降压保护电路
- 简单的短路与反接保护
三、元器件清单 #
序号 | 元件名称 | 型号 / 参数 | 数量 | 作用说明 |
---|---|---|---|---|
1 | 单片机核心板 | STC89C516 | 1 | 控制核心,负责逻辑控制和指令响应 |
2 | WiFi 模块 | ESP-01S | 1 | 实现 WiFi 联网,接收远程控制指令 |
3 | 继电器 | JQC-3FF-S-Z | 1 | 控制交流电通断,用于热水器控制 |
4 | 整流二极管 | 1N4007 | 1 | 防止继电器回流电压损坏元件 |
5 | 降压芯片 | AMS1117-3.3 | 1 | 将5V电压降为3.3V供 ESP-01S 使用 |
6 | 三极管 | S8550 PNP | 1 | 放大驱动电流控制继电器通断 |
7 | 电阻 | 1.2kΩ | 1 | 用于三极管基极限流 |
8 | 指示灯 | LED + 100Ω电阻 | 1 | 显示继电器工作状态(亮=加热) |
9 | 电源 | 5V 电源(USB 或降压) | 1 | 提供系统电压 |
10 | 下载器 | STC UST-TTL | 1 | USB下载器 |
11 | 杜邦线 | - | 若干 | 连接电路 |
四、开发软件 #
序号 | 名称 | 描述 |
---|---|---|
1 | sscomV5131.exe | 串口调试工具/网络调试工具,创建TCP服务和客户端 |
2 | Keil uVision4 | C51代码开发工具,编译 hex 文件 |
3 | CH340 | STC 下载器驱动程序 |
4 | AIapp-ISP-v6.95M | STC-ISP 将 hex文件下载到单片机软件 |
五、原理图 #
画电路图不太行,简单画了下方便大家凑合看吧!
接线图
六、电路连接说明 #
- 单片机:
- P3.0(RX) ←→ ESP-01S TX
- P3.1(TX) ←→ ESP-01S RX
- P1.0 → 控制三极管基极(限流电阻串联)
- 继电器驱动:
- 线圈两端并联二极管(1N4007)防止反电动势,需要反接
- AMS1117 电源模块:
- 输入接 5V,输出接 ESP-01S VCC,GND 公共
- LED 指示灯:
- 与继电器共用控制线,继电器吸合时 LED 同时点亮(通过100Ω限流)
七、软件设计与源代码 #
代码部分很简单,大部分内容AI生成,需要注意的时修改WiFi名称和密码。还有就是要修改 TCP 服务器地址和端口,可以现在自己电脑测试,有云服务器可以填写云服务地址+端口就可以实现远程操作。
#include <reg51.h>
#include <intrins.h>
#include <string.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
// 引脚定义
sbit relay = P1^0; // 继电器控制引脚
// 将大数组放到XDATA区(外部数据存储器)
uchar xdata RecBuf[50]; // 接收缓冲区,使用xdata关键字
uchar RxCounter = 0; // 接收计数器
bit receiveFinish = 0; // 接收完成标志
// 函数声明
void UartInit(void); // 串口初始化
void ESP8266_Init(void); // ESP8266初始化
void SendCmd(uchar *cmd); // 发送AT命令
void DelayMs(uint ms); // 毫秒延时
void ConnectWiFi(void); // 连接WiFi
void ConnectTCP(void); // 连接TCP服务器
void SendHeartbeat(void);
void CheckResponse(uchar *response); // 检查响应
void main() {
UartInit(); // 初始化串口
ESP8266_Init(); // 初始化ESP8266
ConnectWiFi(); // 连接WiFi
ConnectTCP(); // 连接TCP服务器
while(1) {
if(receiveFinish) { // 如果接收到数据
receiveFinish = 0;
// 检查是否接收到"1"或"0"
if(strstr(RecBuf, "1") != NULL) {
relay = 0; // 低电平,打开继电器
SendCmd("AT+CIPSEND=4\r\n"); // 准备发送数据
DelayMs(500);
SendCmd("0104\r\n"); // 发送确认信息
}
else if(strstr(RecBuf, "0") != NULL) {
relay = 1; // 高电平,关闭继电器
SendCmd("AT+CIPSEND=4\r\n");
DelayMs(500);
SendCmd("0104\r\n");
}
memset(RecBuf, 0, sizeof(RecBuf)); // 清空缓冲区
RxCounter = 0;
}
SendHeartbeat();
}
}
// 发送心跳包
void SendHeartbeat(void) {
DelayMs(2000);
SendCmd("AT+CIPSEND=4\r\n"); // 发送10字节数据
DelayMs(500);
SendCmd("0102\r\n"); // 心跳包内容
}
// 串口初始化函数
void UartInit(void) {
SCON = 0x50; // 8位数据,可变波特率
TMOD |= 0x20; // 设置定时器1为8位自动重装方式
TH1 = 0xFD; // 波特率9600
TL1 = 0xFD;
TR1 = 1; // 启动定时器1
ES = 1; // 使能串口中断
EA = 1; // 开总中断
}
// ESP8266初始化
void ESP8266_Init(void) {
DelayMs(2000); // 等待ESP8266启动
SendCmd("AT\r\n"); // 测试AT命令
DelayMs(1000);
SendCmd("AT+RST\r\n"); // 重启ESP8266
DelayMs(2000);
SendCmd("AT+CWMODE=1\r\n"); // 设置为STA模式
DelayMs(1000);
SendCmd("AT+CIPMUX=0\r\n"); // 设置单连接模式
DelayMs(1000);
}
// 连接 WiFi
void ConnectWiFi(void) {
uchar cmd[50];
sprintf(cmd, "AT+CWJAP=\"FAST\",\"12345678\"\r\n");
SendCmd(cmd);
DelayMs(5000); // 等待连接WiFi
}
// 连接TCP服务器
void ConnectTCP(void) {
uchar cmd[50];
sprintf(cmd, "AT+CIPSTART=\"TCP\",\"192.168.1.100\",8888\r\n");
SendCmd(cmd);
DelayMs(3000); // 等待连接TCP
SendCmd("AT+CIPMODE=1\r\n"); // 设置为透传模式
DelayMs(1000);
SendCmd("AT+CIPSEND\r\n"); // 开始透传
DelayMs(1000);
SendCmd("AT+CIPSEND=4\r\n");
DelayMs(500);
SendCmd("0102\r\n");
}
// 发送AT命令
void SendCmd(uchar *cmd) {
uchar i = 0;
while(cmd[i] != '\0') {
SBUF = cmd[i];
while(!TI);
TI = 0;
i++;
}
}
// 毫秒延时函数
void DelayMs(uint ms) {
uint i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 123; j++);
}
// 串口中断服务函数
void Uart() interrupt 4 {
if(RI) {
RI = 0;
RecBuf[RxCounter++] = SBUF;
if(RxCounter >= 49) { // 防止缓冲区溢出
RxCounter = 0;
}
// 判断是否接收完成
if(SBUF == '\n') {
receiveFinish = 1;
}
}
}
八、ESP-01S 通讯控制方式 #
ESP 先连接 WiFi,然后建立 TCP 连接(可使用 sscom 创建 TCP server),TCP 服务端负责下发数据控制继电器。
九、遇到的问题与解决 #
S8050 NPN 型三极管,高电平导通 #
- 使用 S8050(NPN) P1.0 无法驱动继电器,串联电阻无法驱动,据说是IO口驱动能力较弱。
GPIO P1.0--->1.2kΩ--->S8050(B)
- 在电源和P1.0口串联电阻(上拉电阻)就可以驱动了(大佬给原理图)
5v+-----|
|
[电阻 R1 1.2kΩ]
|
P1.0----·--->S8050(B)
- 又出现新的问题,第一次上电或复位时瞬间吸合一次,这个问题即使改代码也解决不了,因为51单片机IO口默认高电平。看了很多大佬的电路也是没能解决,电路是在
P1.0
加下拉电阻,P1.0
串联 1kΩ电阻到B
基,手头也没 10kΩ 电阻没有测试成功。
GPIO P1.0--->1kΩ--->S8050(B)
|
|
|
[10kΩ 下拉]
|
GND
S8550 PNP 型三极管,低电平导通 #
最终采用了 S8550 来驱动继电器,正如标题它是低电平导通,所以单片机默认高电平,复位或上电就不会出现吸合一次的情况。
问题描述 | 解决办法 |
---|---|
ESP-01S 工作不稳定 / 无响应 | 使用 AMS1117 提供独立3.3V供电,加入电容滤波 |
串口通信乱码 / 无反应 | 确认波特率一致(9600),ESP-01S 接 RX需分压至3.3V |
继电器吸合但没有动作 | 检查三极管是否导通、电阻设置是否合理 |
LED 长亮/不亮 | 检查LED极性、限流电阻是否连接、继电器是否正确驱动 |
十、三极管扩展 #
概念 #
三极管广泛用于电子电路中的开关和放大功能。其特点是价格低廉、体积小、性能稳定,常见于音频放大器、电源控制、信号处理等低功率场合。
实物 TO-92 封装 #
类型 | 实物图 | 电路符号 | 电流方向 |
---|---|---|---|
NPN | ![]() |
![]() |
发射极流出,集电极流入 |
PNP | ![]() |
![]() |
发射极流入,集电极流出 |
引脚 #
正面朝你(扁平面朝前,脚朝下):
序号 | 引脚 | 引脚名称 |
---|---|---|
1 | E | 发射器 |
2 | B | 基极 |
3 | C | 集电极 |
奇技淫巧(个人理解) #
第一次接触三极管感觉不太好理解,可能脑容量不够用哈哈!
-
NPN
箭头方向→
接负极(GND
),另外一端→
接负载(例如:继电器线圈一端)。 -
PNP
箭头方向→
接正极(VCC
),另外一端→
接负载(例如:继电器线圈一端)。 -
中间基极接
IO
口,要串电阻。
十一、注意事项 #
- 注意用电安全,尤其外接负载设备时。
- 在继电器
COM
(公共端) 和NC
(常开)接线时用质量好一点的线,否则有可能直接烧掉。热水器功率是 2000 W,第一次测试时用塑料接线端子没想到一会就直接烧掉了,后来焊接 1.5 ㎡铜线。 JQC-3FF-S-Z
大功率继电器理论上不超过 2000 W 就可以用,超过了建议别用小心炸了。继电器吸合通电时会产生热量,所以不要把继电器包裹起来要让它可以通风。- 串口调试 WiFi 模块发送指令时需要加
\r\n
,有些工具自带加回车换行
选项 - ESP-01s 默认波特率 是
128000
需要修改为9600
- 要远程操作需要有云服务器或者使用提供TCP物联网协议的云平台,就可以实现远程控制了。我的是使用 go 写了一个 TCP server ,部署在云服务器实现远程控制。
十二、总结 #
本项目利用常见的 51 单片机 + ESP-01S
模块,完成了一个低成本的智能热水器控制器。
在完成该实践后我又发现实际上可以用 ESP-01S
作为 MCU
直接控制继电器(刷固件)而不用单独单片机也是可以的。
对于老手来说这是一个很简单的电路,于我而言涉及的内容多且复杂的,你需要懂代码,电路图,元器件作用特性等等。不过完成该案例也是受益匪浅学到了不少知识点。