Pentru serverul meu IoT prezint primul sistem de inregistrare periodica a unor marimi masurate: o temperatura si un detector de vibratii (cutremur).
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.
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.