这玩意儿折腾了俩礼拜才跑通,原理其实简单到爆:ESP8266当服务器,手机APP发指令过去,开关继电器。但坑全在代码细节里,老司机都懂
局域网继电器控制 esp8266 8路继电器控制 不是实物,不是实物,不是实物。 源码包括8266程序和app程序。 自己花时间弄出来的,有详细的图文说明文件,不提供,不提供。 源码采用arduino 开发环境。 APP采用E4A开发。

先看8266这头,Arduino环境直接上AsyncTCP库,异步处理就是爽。核心代码结构跟俄罗斯套娃似的:
// 别问我为什么不用WebServer库,问就是内存不够用
AsyncServer server(2333); // 端口号得骚
void setup(){
pinMode(relay1, OUTPUT);
// 其他7个继电器同理...别偷懒复制粘贴啊
server.onClient([](void *arg, AsyncClient *client){
if(client->remoteIP() != WiFi.localIP()) return; // 局域网限定
client->onData([](void *arg, AsyncClient *c, void *data, size_t len){
String cmd = String((char*)data).substring(0,8); // 截取前8字节足够
handleRelay(cmd); // 关键在这
}, nullptr);
}, nullptr);
server.begin();
}
void handleRelay(String cmd){
// 协议示例: RELAY1_ON 或者 RELAY5_OFF
int relayNum = cmd.substring(5,6).toInt(); // 取第5位字符
if(relayNum <1 || relayNum >8) return;
digitalWrite(relayPins[relayNum-1], cmd.indexOf("ON")>0 ? LOW : HIGH);
// 注意继电器模块高低电平触发问题!
}
这代码有个魔鬼细节:继电器模块大多是低电平触发,但不同厂家可能反过来。实测时烧了三个三极管才反应过来,血泪教训记得加注释!

APP这边E4A开发,界面丑但能用。核心就一个按钮点击事件:
// E4A这语法真让人头大
事件 按钮1.被单击()
dim 请求头 as string = "RELAY1_TOG" // 切换状态比单独开关靠谱
网络操作1.发送数据("192.168.1.666",2333,请求头,utf8编码)
结束 事件
重点在异常处理——8266突然掉线的话APP直接卡死。后来加了心跳检测:
定时器1.时钟周期=5000
事件 定时器1.周期事件()
if 上次响应时间 < 当前时间戳 - 10000 then
弹窗提示("设备失联!")
按钮组.禁用所有() // 防止乱点
end if
结束 事件
实际测试发现局域网延迟能到200ms,所以协议里必须带时间戳校验。后来改成UDP广播发现,结果被路由器防火墙教做人,老老实实换回TCP长连接。

局域网继电器控制 esp8266 8路继电器控制 不是实物,不是实物,不是实物。 源码包括8266程序和app程序。 自己花时间弄出来的,有详细的图文说明文件,不提供,不提供。 源码采用arduino 开发环境。 APP采用E4A开发。

最坑的是8266的AP模式不稳定,最后妥协用STA模式连路由器。家里路由器要是挂了整套系统直接凉凉,但总比三天两头断线强。

代码里藏着个骚操作:继电器状态用二进制位存储,一个字节就能表示8路状态。省流量又方便校验:
byte relayStates = 0b00000000;
// 更新状态
if(cmd.indexOf("ON")){
relayStates |= (1 << (relayNum-1));
}else{
relayStates &= ~(1 << (relayNum-1));
}
APP同步显示状态这事折腾最久,最后用了个土办法:8266每秒广播当前状态字节,APP收到就解析更新图标。虽然简单粗暴,但实测没丢过包。
这套系统现在挂着控制鱼缸灯光,半年没掉链子。下次准备加上MQTT对接HomeAssistant,不过那就是另一个坑的故事了...
更多推荐
所有评论(0)