极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 108298|回复: 50

用NodeMCU(ESP8266)打造超级实用的智能插排

[复制链接]
发表于 2015-10-9 15:27:19 | 显示全部楼层 |阅读模式
本帖最后由 快乐起航2012 于 2016-6-4 11:51 编辑

NodeMCUESP8266)打造超级实用的智能插排
      很少写东东,因为确实很繁琐,总是无偿使用别人的成果,今天也贡献一些,希望能给人提供一些帮助。
      买了很多智能插座,但是总和期望相差不少,由于智能家居技术发展很快,现成的产品功能有限,开发不完善,利用率很低,各个公司间壁垒严重,开发进度缓慢,在苦苦煎熬中等待的升级往往也是失望,作为极客一族,看来还是自己动手做一个吧!
1、方案 NodeMCUESP8266+智能插排
     NodeMCU的理由是它足够便宜,另一个就是开源,这样就不会有人为的障碍阻挡你的脚步了,站在巨人的肩膀上,让花费的时间更有意义。


       选择这款插排改造,是因为它本身外形美观,也很实用,加上了wifi可谓锦上添花,价值堪比市场上的几百元的产品,不用单个插座的理由是都上了这么多电路了,只控制一路岂不可惜,选择它还有一个重要原因是它内部有足够的空间去安装wifi控制电路,我们不能总停留在一堆零件上吧,改装完我们会获得这样一个美观实用、功能超强的智能插排!


插排内部图,绿色方框空出的位置正好可以安装NodeMcu和继电器板。





2 、电路原理

      是不是很简单,是因为前人已经做了很多工作了。准备好部件,先在插排内摆放好位置,接好线,其中5V电源连接到插排的USB供电电源上(原单片机供电电源功率可能偏小),12V电源连接到插排原12V电源上,切断原5V到USB连接器的供电,NodeMCU的USB口直接连接到原USB连接器插座上,这样为的是方便安装后再通过计算机给NodeMCU编程,确定需要控制的插座,剪断原铜排连线,将增加的继电器串联到插座中。这里尤其要注意的是板子上不是单纯的低压,220V、5V、12V都在同一块板上,所以在打开插座进行测量时要格外小心,改装后做好绝缘确保安全。全部安装好后要用LuaLoader软件测试一下继电器动作是否正常,一切就绪后再安装好插排盖板,这个一个精致的智能wifi插排就装好了。
3、开发软件及平台
      这个插排是不是很好用重头戏在软件上,开发系统是完全开放的,只要你有想法就能给它赋予更多的智慧,实现各种需求,让它也能与时俱进,不用苦苦等待厂家升级了。
      NodeMCU模块是在ESP8266模块基础上增加了USB接口电路、5V电源等,软件系统实现了简单的脚本语言Lua,方便用户编程。系统的源代码已经开源。本文只讨论到Lua,如果特殊的应用可以再修改底层代码。
      Lua是什么,是一种简单的解释性脚本语言,我也学了几句,程序就算是个示意,起个抛砖引玉的作用吧。
      我们选乐为物联作为插排的管理平台,当然也可以选择其他各种平台,感觉目前都不甚成熟。首先我们需要接通平台,凡事要先从简单的来,太复杂的往往走的弯路更多,
      1)上传数据
           a)我们先在乐为物联上设置两个继电器量;
           b)输入上传代码
test.lua[pre lang="lua" line="1"]local server = "tcp.lewei50.com"--"192.168.1.129"--
local port = 9960
local bConnected = false
gateWay = "xx"  --设备代码
userKey = "xxxxxxxxxxxxxxxxxxxx"  --你自己的key
local uSwitchNode = nil
local strOnline = ""
local str1=""

wifi.setmode(wifi.STATION)
wifi.sta.config("xxxxxxxxxxxxxx","xxxxxxx")   --路由器登陆名称和密码
wifi.sta.connect()
local cnt = 0
tmr.alarm(0, 1000, 1, function()
        if (wifi.sta.getip() == nil) and (cnt < 200000000) then
                print("Trying Connect to Router, Waiting...")
                cnt = cnt + 1
                         if cnt%2==1 then gpio.write(0,gpio.LOW);
                         else gpio.write(0,gpio.HIGH); end
        else
        
                tmr.stop(0);
                gpio.write(1,gpio.LOW)
                tmr.delay(500000)
                gpio.write(2,gpio.LOW)
                tmr.delay(500000)
                gpio.write(5,gpio.LOW)
               
                if (cnt < 20) then print("Conected to Router\r\nMAC:"..wifi.sta.getmac().."\r\nIP:"..wifi.sta.getip())
                        else print("Conected to Router Timeout")
                end
                gpio.write(0,gpio.LOW);
                cnt = nil;cfg=nil;str=nil;ssidTemp=nil;
                collectgarbage()
        end
end)

strOnline = "{\"method\":\"update\",\"gatewayNo\":\""..gateWay.."\",\"userkey\":\""..userKey.."\"}&^!"

socket=net.createConnection(net.TCP, 0)
     socketn("connection", function(sck, response)
          socket:send(strOnline)
                        print (strOnline)
                        tmr.delay(500000)
                        str1= "{\"method\":\"upload\",\"data\":[" .. "{\"Name\":\"SW1\",\"Value\":\"99.7\"}"  .. "]}&^!\r\n"
                        socket:send(str1)
                        print (str1)
          bConnected = true
     end)

     socketn("disconnection", function(sck, response)

          bConnected = false
     end)

     socketn("receive", function(sck, response)
          --dealResponse(response)
     end)

     socketn("sent", function(sck, response)
          print(tmr.now().."sent")
     end)
        
socket:connect(port, server)[/code]
            

          如上图所示,如果乐联平台上的状态显示由灰变蓝,说明数据已经上传到乐联网了。
      2)增加控制功能
         a)乐联上设置控制开关功能
         b)lua代码修改
            测试一下,如果反馈回ok说明控制功能连接成功,到此一个能连wifi的物联插诞生了,可以把玩一下了!
init.lua
  1. local luaFile = {"sta.lua"}
  2. for i, f in ipairs(luaFile) do
  3.         if file.open(f) then
  4.       file.close()
  5.       print("Compile File:"..f)
  6.       node.compile(f)
  7.           print("Remove File:"..f)
  8.       file.remove(f)
  9.         end
  10. end

  11. local luaFile = {"mysocket.lua"}
  12. for i, f in ipairs(luaFile) do
  13.         if file.open(f) then
  14.       file.close()
  15.       print("Compile File:"..f)
  16.       node.compile(f)
  17.           print("Remove File:"..f)
  18.       file.remove(f)
  19.         end
  20. end

  21. dofile("sta.lc");
  22. dofile("mysocket.lc");
  23. luaFile = nil
  24. collectgarbage();
复制代码
sta.lua
  1. gpio.mode(1,gpio.OUTPUT)
  2. gpio.mode(2,gpio.OUTPUT)
  3. gpio.mode(5,gpio.OUTPUT)
  4. gpio.write(1,gpio.HIGH)
  5. gpio.write(2,gpio.HIGH)
  6. gpio.write(5,gpio.HIGH)

  7. wifi.setmode(wifi.STATION)
  8. wifi.sta.config("xxxxxx","xxxxxx") --wifi路由器名称及密码
  9. wifi.sta.connect()
  10. local cnt = 0
  11. tmr.alarm(0, 1000, 1, function()
  12.         if (wifi.sta.getip() == nil) and (cnt < 200000000) then
  13.                 print("Trying Connect to Router, Waiting...")
  14.                 cnt = cnt + 1
  15.                          if cnt%2==1 then gpio.write(0,gpio.LOW);
  16.                          else gpio.write(0,gpio.HIGH); end
  17.         else
  18.         
  19.                 tmr.stop(0);
  20.                 gpio.write(1,gpio.LOW)
  21.                 tmr.delay(500000)
  22.                 gpio.write(2,gpio.LOW)
  23.                 tmr.delay(500000)
  24.                 gpio.write(5,gpio.LOW)
  25.                
  26.                 if (cnt < 20) then print("Conected to Router\r\nMAC:"..wifi.sta.getmac().."\r\nIP:"..wifi.sta.getip())
  27.                         else print("Conected to Router Timeout")
  28.                 end
  29.                 gpio.write(0,gpio.LOW);
  30.                 cnt = nil;cfg=nil;str=nil;ssidTemp=nil;
  31.                 collectgarbage()
  32.         end
  33. end)
复制代码
mysocket.lua
  1. local server = "tcp.lewei50.com"--"192.168.1.129"--
  2. local port = 9960
  3. local bConnected = false
  4. local gateWay = "xx"  --你的设备号,类似01等
  5. local userKey = "xxxxxxxxx"  --你自己的Key
  6. local uSwitchNode = nil
  7. local strOnline = ""
  8. local str1=""
  9. local sw1="0"
  10. local sw2="0"
  11. local sw3="0"

  12. --get value from string like "p1":"1","f":"getAllSensors"
  13. local function getStrValue(str,strName)
  14.      i,j = string.find(str,"""..strName.."":"")
  15.      k,l = string.find(string.sub(str, j+1, -1),""")
  16.      return string.sub(str, j+1,j-1+l)
  17. end

  18. function sw_refresh()
  19.         print(sw1,sw2,sw3)
  20.         if sw1=="1" then
  21.                 gpio.write(5,gpio.HIGH)
  22.         else
  23.                 gpio.write(5,gpio.LOW)
  24.         end
  25.         if sw2=="1" then
  26.                 gpio.write(1,gpio.HIGH)
  27.         else
  28.                 gpio.write(1,gpio.LOW)
  29.         end
  30.         if sw3=="1" then
  31.                 gpio.write(2,gpio.HIGH)
  32.         else
  33.                 gpio.write(2,gpio.LOW)
  34.         end
  35. end

  36. local function dealResponse(str)
  37.      ufunctionName = getStrValue(str,"f")
  38.      if(ufunctionName == "writeSerial") then
  39.                 uswitchName = getStrValue(str,"p1")
  40.         uswitchValue = getStrValue(str,"p2")
  41.                 if uswitchName=="1" then sw1=uswitchValue end
  42.                 if uswitchName=="2" then sw2=uswitchValue end
  43.                 if uswitchName=="3" then sw3=uswitchValue end
  44.                 sw_refresh()
  45.                 nodeStr= "{"method":"response","result":{"successful":true,"message":"TD Write serial OK."}}&^!"
  46.                 socket:send(nodeStr)
  47.         nodeStr = nil
  48.         str = nil
  49.      end
  50.      str = nil
  51. end

  52. socket=net.createConnection(net.TCP, 0)
  53.      socket:on("connection", function(sck, response)
  54.           socket:send(strOnline)
  55.                         print (strOnline)
  56.                         tmr.delay(500000)
  57.                         str1= "{"method":"upload","data":[" .. "{"Name":"SW1","Value":"" .. sw1 .. ""},{"Name":"SW2","Value":"" .. sw2 .. ""},{"Name":"SW3","Value":"" .. sw3 .. ""}"  .. "]}&^!\r\n"
  58.                         socket:send(str1)
  59.                         print (str1)
  60.           bConnected = true
  61.      end)

  62.      socket:on("disconnection", function(sck, response)
  63.           bConnected = false
  64.      end)

  65.      socket:on("receive", function(sck, response)
  66.           dealResponse(response)
  67.                 print("return ok!")
  68.      end)

  69.      socket:on("sent", function(sck, response)
  70.           print(tmr.now().."sent")
  71.      end)


  72. strOnline = "{"method":"update","gatewayNo":""..gateWay.."","userkey":""..userKey..""}&^!"        
  73. socket:connect(port, server)

  74. tmr.alarm(4, 5000, 1, function()
  75.         str1= "{"method":"upload","data":[" .. "{"Name":"SW1","Value":"" .. sw1 .. ""},{"Name":"SW2","Value":"" .. sw2 .. ""},{"Name":"SW3","Value":"" .. sw3 .. ""}"  .. "]}&^!\r\n"
  76.         print(str1)                        
  77.         socket:send(str1)
  78. end)
复制代码

         微信控制:通过手机微信开关插座,可以做到远程控制;
         定时烧茶水:每天可以定时开始烧水,烧完水好自动关闭电源;

           编辑2个计划任务,一个用于打开烧茶说电源,一个任务是一小时以后关闭电源。


        启动计划后,系统就在每天晚上7点给烧水插座供电,如果需要烧水可预先灌好水,按下烧水按钮,待插座通电后自动开始烧水,水烧开后自动断电,此后每天7点以后,就可以泡一杯香茶或咖啡,岂不美哉!{:soso_e113:}




          自动加湿:就是在湿度过低时自动接通加湿器电源加湿,隔一定时间或湿度到达后自动断开加湿器电源,停止加湿。有人问,那湿度信号从哪里来啊,那就请到论坛找找,有很多方法的,这个才体现了万物物联的真谛!




          还有很多很多新奇的功能…,欢迎交流,可以让生活更舒适简单。


          我还想实现一个功能,记得住宾馆,离开房间时拿走房卡,房间里可以自动断电,方便又安全,如何在家也这样方便呢,期待你的高招...{:soso_e129:}


          感谢“瘦网虫”提供的lua代码参考,乐联提供的免费平台还有很多很多人在网上提供的资料和软件。

很多人咨询插排,少量提供,极客工坊的用户另有特价

欢迎联系交流我的qq:250051104

源代码、资料、工具软件可以去qq群 475079657下载

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2015-10-9 16:25:38 | 显示全部楼层
期待                                         
回复 支持 反对

使用道具 举报

发表于 2015-10-9 19:12:13 | 显示全部楼层
很棒的教程,收藏……
回复 支持 反对

使用道具 举报

发表于 2015-10-9 22:28:36 | 显示全部楼层
真不错  发教程的都是好人
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-10 09:37:10 | 显示全部楼层
老胖熊 发表于 2015-10-9 16:25
期待

一起完善啊,有什么好主意欢迎交流
回复 支持 反对

使用道具 举报

发表于 2015-10-10 20:25:27 | 显示全部楼层
Lua,百花齐放啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-12 16:24:27 | 显示全部楼层
嗯,不过想实现的功能还是有些局限
回复 支持 反对

使用道具 举报

发表于 2015-10-19 19:08:54 | 显示全部楼层
mysocket 代码最后差个end
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-19 20:05:59 | 显示全部楼层
〆﹏MARK 发表于 2015-10-19 19:08
mysocket 代码最后差个end

高手啊,谢谢提醒,
修改过来了,代码粘过来漏掉了{:soso_e181:}
回复 支持 反对

使用道具 举报

发表于 2015-10-20 14:25:30 | 显示全部楼层
快乐起航2012 发表于 2015-10-19 20:05
高手啊,谢谢提醒,
修改过来了,代码粘过来漏掉了

照着教程做的,但是硬件不上线不知何因?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-20 15:12:45 | 显示全部楼层
本帖最后由 快乐起航2012 于 2015-10-20 15:48 编辑
〆﹏MARK 发表于 2015-10-20 14:25
照着教程做的,但是硬件不上线不知何因?

先用1)b)的mysocket.lva 测试,主意:1、先让ESP8266能够上互联网,代码没有专门附 2、上传代码主意3点如图:1设备代码要正确 2 userkey要正确 3 测试用的是一个T的变量,所以要在乐为上建一个T的变量,或者把T修改成SW1,我把上面的示例代码修改成SW1了,避免大家走弯路。


以上程序比较简单,就是专门为测试是否能够上传成功的。

我把联网的代码也加进去了形成上面的test.lua,把用户名等修改后就可以了,执行效果如下图:



我是把硬件连通以后就安装起来了,这样整齐,而且安全,正好这个插排有个usb口,之后编程直接插到电脑上就可以了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2015-10-20 22:57:25 | 显示全部楼层
快乐起航2012 发表于 2015-10-20 15:12
先用1)b)的mysocket.lva 测试,主意:1、先让ESP8266能够上互联网,代码没有专门附 2、上传代码主意3点 ...

这次确实好用了谢谢楼主指导,有个问题,为什么不用控制器而用传感器来控制开关量呢?
回复 支持 反对

使用道具 举报

发表于 2015-10-20 23:07:18 | 显示全部楼层
快乐起航2012 发表于 2015-10-20 15:12
先用1)b)的mysocket.lva 测试,主意:1、先让ESP8266能够上互联网,代码没有专门附 2、上传代码主意3点 ...

还有个问题就是开始启动的时候设备能上线,但是过一段时间就无法控制了,测试显示设备offline
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-21 18:30:57 | 显示全部楼层
本帖最后由 快乐起航2012 于 2015-10-21 18:45 编辑
〆﹏MARK 发表于 2015-10-20 23:07
还有个问题就是开始启动的时候设备能上线,但是过一段时间就无法控制了,测试显示设备offline

lua我也是这两天才看的,上面的程序只能说是个参考,为的是做到能通,容错性还需要进一步考虑的,如果你lua过关了可以参考“瘦网虫”的帖子,他编了一个乐为物联的接口程序库,有点复杂,我暂时没搞懂,
物联网包含的内容太多了,需要大量的硬件和软件支撑的,需要大家一起来,开放或许是必须的
我们的另外一个stm32控制器连续运行了一个月,目前还一直稳定运行,那个联网方案是gprs,不是目前的这个wifi模块。
回复 支持 反对

使用道具 举报

发表于 2015-11-9 16:04:26 | 显示全部楼层
好东西,正好看看。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-26 07:49 , Processed in 0.048536 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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