一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 130|回复: 2

[其他DIY] 智能家居第二步DIY:MQTT协议远程控制电器

[复制链接]
发表于 2025-9-28 08:10 | 显示全部楼层 |阅读模式
第一步传送门:https://www.yleee.com.cn/forum.php?mod=viewthread&tid=92416
继使用STM32模拟EV1527后,智能家居的DIY进入第二步,使用MQTT协议进行远程遥控继电器通断来控制一个220V设备的开启和关闭。

### 电路:
64581644598DA956EAADA87D6859358C.jpg
使用串口屏的E1扩展端口进行继电器的控制

### 成品效果
外壳成品.jpg


### 代码实现:

这是一个mqtt连接的测试程序,在此界面之前,已经在开机的界面用下面的语句完成了wifi的连接,SNTP互联网时间获取,以及mqtt服务器的连接:

  1. void init()
  2. {   str ssid;
  3.     str pwd;
  4.     ssid=bind_get("wifissid");  //获取存储的wifi AP的SSID
  5.     pwd=bind_get("wifipass");   //获取存储的wifi密码
  6.     wifi_connect(ssid,pwd);     //wifi连接
  7.     gpio_mode(0,1);        //E1端口 设置成输出模式
  8.     app.setio(0); //E1低电平,继电器关闭
  9. }
复制代码

wifi连接时异步事件,在异步回调之后再依次处理,以下是部分核心代码:
  1. void app.onASYNC(int m){
  2.     if (m==1){
  3.         //已经WIFI连接成功,需要进入下一步:获取互联网时间
  4.         wifi_sntp("ntp.aliyun.com","CST-8");
  5.     }
  6.     if (m==2){
  7.         //获取网络时间OK,在此书写连接服务器的代码
  8.         mqtt_init();    //配置文件初始化
  9.             //mqtt_setv(0,"mqtt://user:pwd@host.com"); //使用自有的mqtt服务器
  10.             mqtt_setv(2,"");//使用SHMICTRL官网提供的免费服务器
  11.             mqtt_connect(); //连接mqtt服务器
  12.     }
  13.     if (m==3){
  14.             //mqtt服务器连接完成
  15.             gopage(2); //直接调整到第2个页面
  16.     }
  17.     super.onASYNC(m);        //调用appbase父类继续处理其他消息
  18. }
复制代码


可以看到连接mqtt服务器后,会跳转的第二个页面,实际效果如下:
运行界面.jpg

在此界面中,点按钮“开关”可以实现继电器的开关,然后界面处于mqtt协议的连接状态,当收到mqtt消息的时候,会将消息显示在左侧的调试消息显示框中,并且对消息命令进行处理:

- RS:读取状态
- S1: 打开继电器
- S0:关闭继电器
- 返回: 0- 继电器当前是关闭状态 1-开启状态

同时,界面中生成一个二维码,对应服务器上的一个URL程序,该程序是PHP编制,使用PHP连接mqtt服务器发送相应的消息,用于控制继电器的开关

本页面完整代码如下:
  1. class app=loadcom(appbase);  //加载全局控制控件
  2. class page=loadcom(page);    //加载页面控制控件
  3. class s1=loadcom(skinwindows);  //加载窗体控件
  4. class m1=loadcom(memo); //左侧的大文本显示控件
  5. class s2=loadcom(skinbutton); //按钮"开"
  6. class s3=loadcom(skinbutton); //按钮"测试发布"
  7. class s4=loadcom(skinbutton); //按钮"返回"
  8. class s5=loadcom(skinbutton); //按钮"清空"
  9. class q1=loadcom(QRcode);     //二维码控件

  10. str retstr= "";  //反馈字符串
  11. str maintopic=""; //主topic
  12. io=0;   //端口状态
  13. void app.onASYNC(int m){
  14.         if (m==200){
  15.                 //收到消息后,如果有反馈字符串,则发布消息,返回反馈字符串
  16.                 if (retstr!=""){
  17.                         mqtt_pub(maintopic,0,retstr); //发布一条消息
  18.                         retstr="";
  19.                 }
  20.         }

  21. }

  22. //mqtt传来的消息命令执行函数
  23. void mqtt_work(str topic,str data){
  24.         if (data=="S1"){
  25.                 gpio_out(0,1); //E1端口高电平
  26.                 retstr="1";    //返回1
  27.                 io=1;
  28.         }
  29.         if (data=="S0"){
  30.                 gpio_out(0,0);  //E1端口低电平
  31.                 retstr="0";     //返回0
  32.                 io=0;
  33.         }
  34.         if (data=="RS"){    //读取继电器状态,也就是E1的端口电平
  35.                 retstr=""+io;
  36.         }
  37.         if (retstr!=""){
  38.                 async_run(200);  //如果有返回信息,则执行异步反馈发送消息
  39.         }
  40. }


  41. void app.onWIFI32(int m){
  42.     //在此书写有关m对应的wifi异步执行结果的处理代码
  43.     str s;
  44.     int msgnum;
  45.         msgnum=wifi_getinfo(2);
  46.     if (m==7){//m==7 表示收到的是mqtt消息事件
  47.                    if (msgnum==6){  //msgnum==6 表示事件是收到mqtt消息
  48.                            //收到消息
  49.                            str topic;
  50.                            str data;
  51.                            int qos;
  52.                            topic=wifi_getinfo(23); //获取消息的topic
  53.                            data=wifi_getinfo(24);  //获取消息的实际内容
  54.                            qos=wifi_getinfo(4);    //获取qos,可以不处理
  55.                            //---在此书写收到的mqtt消息处理
  56.                            s="RECV:"+data+"\r\n";
  57.                            m1.text=m1.text+s; //将收到的消息字符串累加到屏幕左侧的大文本控件,用于显示
  58.                            mqtt_work(topic,data); //处理传来的消息命令
  59.                    }
  60.     }
  61.     super.onWIFI32(m); //调用appbase的父类,继续处理其他的wifi事件
  62. }

  63. void s2.onclick()
  64. {   //返回按钮的点击事件
  65.     gopage(1); //跳到页面1(菜单界面)
  66. }
  67. void s3.onclick()
  68. {   //发布按钮
  69.         mqtt_pub(app.maintopic,0,"testmessage");//发布一条测试消息
  70. }
  71. void s4.onclick()
  72. {   //卡关按钮
  73.         if (s4.text=="开"){
  74.                 s4.text="关";  //点击后改变按钮上显示内容
  75.                 gpio_out(0,1); //E1输出高电平
  76.                 io=1;
  77.         }
  78.         else{
  79.                 s4.text="开";
  80.                 gpio_out(0,0); //E1输出低电平
  81.         io=0;
  82.         }
  83. }
  84. void s5.onclick()
  85. {   //清空按钮
  86.         m1.text="";  //清空大文本控件的显示内容
  87. }
  88. void init(){
  89.         //刚进入页面时的初始化函数
  90.         q1.text="http://shmictrl.com/wifi/shmi-R1.php?id="+getsn(6); //生成二维码的url
  91.         maintopic="shmi-R1/"+getsn(6); //生成mqtt消息的topic
  92. }
  93. init(); //调用init()函数,初始化一些参数
  94. start(); //进入页面的消息循环,处理页面的显示与触摸事件
复制代码



### 内部结构
内部结构.jpg
### 主要BOM:


器件 |说明
---|---
串口屏|SHMICTRL 神秘魔控 ESP32-40ATP
AC电源模块|薄款 25X15mm  220-5V1A
继电器|SRD-05V  5V控制
光耦|PC817C SMD-4P
AC输入座|RT-C14-C0B-AA
AC输出座|DB-F-C3-C
外壳|铝型材外壳,厂家打孔

DIY下来总成本元器件不超过120元,不含PCB和外壳;

下一步:需要书写正式程序,并把多段定时程序加上,这样就可以控制热水器等设备了;
再远一点,将本控制器和前面做的自学习遥控器合并,用于控制各个灯具。


发表于 2025-9-28 10:08 | 显示全部楼层
做的太好了,绑定。
回复

使用道具 举报

发表于 2025-9-29 13:49 | 显示全部楼层
为什么不直接用HA+ESPHOME
回复

使用道具 举报

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2025-10-1 03:13 , Processed in 0.052257 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表