1

背景

前阵子树莓派由于没外壳不小心短路烧掉了。最近得手nodeMCU的板子,不仅便宜还支持串口交互式调试,很是方便。寻思着实现个自动化控制玩玩。自从“穹顶之下”的信息被普及,不仅要出门带口罩,还要家里开空气净化器。于是照着知乎也DIY了一个。但作为一个程序员,不捣鼓一点硬件软件怎么可以,于是花了两三天捣鼓了lua,顺便配了个web端的语音播报,软硬件组合达到了期望的效果。(顺便吐槽一下tinyOS的组件式编程,文档也少得可怜)

实现思路

硬件:

  • MQ烟雾/可燃气体传感器
  • dth温湿度传感器
  • 空气颗粒物(pm1.0,pm2.5,pm10)传感器
  • 继电器*4(用来控制 取暖器,加湿器,净化器,烟雾报警装置)

clipboard.png

软件:

  • 万能的web(html js jq)
  • php(负责爬天气预报和空气质量,以及和nodeMCU通讯)

  • 用socket拼接http去获取天气,结果写完发现它的socket接受发送最大1440字节,本来想直接写进MCU做个lua server。可惜了,于是控制规则干脆写到前端,php做大量的数据获取支持。
  • 用的空气颗粒物传感器接TX口,init.lua加载前会根据D3 D4 TX 来判断是否进入烧写模式,之前接继电器总是上电乱跳,最终把data out 的2口放到D3 D4,解决了这个问题。

效果图

clipboard.png

nodeMCU代码(init.lua)

--家庭空气质量管家
--sensor为传感器data口
--power为继电器控制口
--D0    CH1             0
--D1    CH2             0
--D2    CH4             0
--D3    MQ-DATA  1
--D4    DHT-DATA 0
--D5    CH3             0
--D6    DHT-VCC    1
--RX    PM-TX
Air={
    pm010=0,pm025=0,pm100=0,
    temp=0,humi=0,smoke=1,
    gpio_pm=0,gpio_temp=0,gpio_humi=0,gpio_smoke=0,
    humi_power=0, pm_power=1,
    smoke_power=2,   mq_sensor=3,
    dht_sensor=4,    temp_power=5
}
--引脚初始化
for pi=0,6,1 do
    gpio.mode(pi, gpio.OUTPUT,(pi==6)and gpio.PULLUP or gpio.FLOAT)
    gpio.write(pi,(pi==3 or pi==6)and gpio.HIGH or gpio.LOW)
end
--网络
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","PASSWORD")
--串口监听
uart.setup( 0, 9600, 8, 0, 1, 0 )
uart.on("data",
  function(data)
    if(string.len(data)==32 and string.byte(data)==66) then
        --颗粒
        Air.pm010=tonumber(string.byte(data,11))*256+tonumber(string.byte(data,12))
        Air.pm025=tonumber(string.byte(data,13))*256+tonumber(string.byte(data,14))
        Air.pm100=tonumber(string.byte(data,15))*256+tonumber(string.byte(data,16))
        --温湿度
        _,Air.temp,Air.humi, _, _ =dht.read(Air.dht_sensor)
        --烟雾
        Air.smoke=gpio.read(Air.mq_sensor)
        --继电器
        Air.gpio_pm,Air.gpio_temp,Air.gpio_humi,Air.gpio_smoke=gpio.read(Air.pm_power),gpio.read(Air.temp_power),gpio.read(Air.humi_power),gpio.read(Air.smoke_power)
    end
end, 0)
--http
srv=net.createServer(net.TCP)  
srv:listen(80,function(conn)  
    conn:on("receive", function(client,request)  
        local buf = "{"
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP")
        if(method == nil)then  
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP")
        end  
        local _GET = {}  
        if (vars ~= nil)then  
            for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do  
                _GET[k] = v  
            end  
        end  
        if(_GET.action == "read")then
            for key,value in pairs(Air) do
                buf=buf..key..":"..value..","
            end
        elseif(_GET.action == "write")then
              gpio.write(_GET.pin,_GET.level)
        elseif(_GET.action == "debug")then
              node.input(_GET.data)
        end  
        client:send(buf.."error:0}")
        client:close()
        collectgarbage()
    end)  
end)  

源码

https://github.com/Seasonley/...


seasonley
607 声望693 粉丝

一切皆数据