Program NodeMCU in Lua pentru serverul IoT

Categorii: Internet, Programare, Stiinta si Tehnologie

18-May-2017 22:04 - 2834 vizionari

Pentru serverul meu IoT prezint primul sistem de inregistrare periodica a unor marimi masurate: o temperatura si un detector de vibratii (cutremur).

NodeMCU, DS18B20 si senzor vibratii

Senzorul de vibratii (un cilindru albastru) are placa dedicata cu 3 pini, alimentare si semnal de iesire, un amplificator operational si un potentiometru de reglaj sensibilitate.

In spatele senzorului de vibratii este traductorul de temperatura, DS18B20, si are forma unui tranzistor de plastic de tip BC.

Editorul LUA de conectare la NodeMCU

In prima versiune, programul trimitea date pana la actualizarea #207, dupa care se oprea pentru ca modulul NodeMCU nu mai are suficient RAM (Heap) liber.

O solutie este sa resetez modulul (node.restart()) cand memoria (heap) scade sub 15000. Alta solutie este sa gasesc un firmware LUA care nu are greseli de implementare.

Programul Lua actualizat si cu restart automat este suficient de scurt si de simplu:


--
-- iot1.lua
--
-- program de trimitere valori masurate
-- in serverul IoT la fiecare 60 de secunde
--
-- serverul IoT al meu merge numai cu SSL
--

cnt = 1
updcnt = 1
cntcutremur = 0


mySet = function(HOST, URL, WKEY, flag)
     collectgarbage()
     local conn=net.createConnection(net.TCP, flag)
     if flag then
         conn:connect(443,HOST)
     else
         conn:connect(80,HOST)
     end
     conn:on("connection", function(connexion)
           print("Updating IoT server, use ssl="..flag)
           collectgarbage()
           connexion:send("GET "..URL.." HTTP/1.1\r\n".. 
                  "Host: "..HOST.."\r\n"..
                  "WKEY: "..WKEY.."\r\n"..
                  "Accept: */*\r\n"..
                  "User-Agent: Mozilla/4.0 (compatible; esp8266 Lua;)"..
                  "\r\n\r\n") 
     end ) 
     conn:on("receive", function(connexion, data)
          connexion:close()
          collectgarbage()
          --print(data)
          print("Done update. Heap="..node.heap())
          collectgarbage()
          end )
     --conn:on("disconnection", function(connexion)  print("disconnected") end )
     collectgarbage()
 end 


getTemp = function()
    -- temperatura
    local t = require("ds18b20")
    local temp_pin = 1
    local temperatura=0
    t.setup(temp_pin)
    local addrs = t.addrs()
    if (addrs ~= nil) then
        temperatura = t.read()
    end            
    t = nil
    ds18b20 = nil
    package.loaded["ds18b20"]=nil
    return temperatura
end

myUpdate = function()

    local UPDINTERVAL = 20 -- 3 sec x 20 = 60 secunde
    --senzor cutremur
    local pin = 2
    gpio.mode(pin, gpio.INPUT)
    for i=1,2048 do
        if 1 == gpio.read(pin) then
            cntcutremur = cntcutremur + 1
        end
    end

    if updcnt >= UPDINTERVAL then
        print("Upd#"..updcnt.."/"..UPDINTERVAL.." Heap="..node.heap())
        updcnt = 1
        collectgarbage()
        print('\r\nStart update #'..cnt)
        local url = "/set/zona1?t1="..getTemp()..
            "&tmr="..tmr.now().."&cnt="..cnt..
            "&datetime=&heap="..node.heap()..
            "&cutremur="..cntcutremur
        cntcutremur = 0
        mySet("iot.rainbowheart.ro", url, "1234", 1)
        -- mySet("-- sau my local ip fara ssl --", url, "1234", 0)
        url = nil
        collectgarbage()
        cnt = cnt + 1
    else
        if node.heap() < 15000 then
            print("RESTART NODEMCU")
            node.restart()
        end
        print("Run#"..updcnt.."/"..UPDINTERVAL.." Heap="..node.heap())
        updcnt = updcnt + 1
    end
    --collectgarbage("collect")
    collectgarbage()
end


getTemp() -- pregateste senzorul de temperatura
if not tmr.create():alarm(3000, tmr.ALARM_AUTO, myUpdate)
then
  print("whoopsie")
  node.restart()
end


Programul init.lua de pornire automata a achizitiei dupa reboot:


--
-- init.lua
--
-- daca e definita variabila 'stop'
-- atunci executia 'mystart' este oprita
-- daca nu: dofile("iot1.lc")
-- in editorul ESPlorer am definit un macro 'stop=1'
-- pentru oprirea fortata imediat dupa reboot
--

local mystart = function()
    print("My start. Heap="..node.heap())
    if stop ~= nil then
        print("Gasit stop.")
    else
        print("Run my start script.")
        dofile("iot1.lc")
    end
end

if not tmr.create():alarm(5000, tmr.ALARM_SINGLE, mystart)
then
  print("whoopsie")
  --node.restart() -- atentie aici sa nu intre in restart infinit
end


Rezultatele achizitiei periodice de date se pot vizualiza in Serverul IoT.

Se pare ca singura problema cu modulele NodeMCU bazate pe Lua este ca au memorie de lucru (RAM sau Heap) putina (48k cred), iar limitarea este data de Lua. Daca modulul este programat in C din mediul de dezvoltare Arduino IDE, limitarea dispare.

Mai pot programa NodeMCU in MicroPython sau in Basic.


Ultimele pagini: RSS

Alte adrese de Internet

Categorii

Istoric


Atentie: Continutul acestui server reprezinta ideile mele si acestea pot fi gresite.