ESP8266/templogger

Da raspibo.
Jump to navigation Jump to search


ESP8266 ThingSpeak

L'ESP8266 può essere utilizzato come microcontrollore standalone con il firmware Nodemcu. Grazie ai due GPIO pins si possono collegare sensori di temperatura, led, relè o altro. In questo esempio il GPIO2 è collegato ad un sensore DS18B20 per la misurazione della temperatura e ogni 30 secondi la lettura viene inviata a ThingSpeak


Wifi temp logger2.jpg


Schema elettrico

Wifi temp logger2 schem.png

Consiglio di alimentare ESP8266 attraverso un alimentatore dedicato, non utilizzare i collegamenti forniti da altro micro controllore tipo Arduino, nè quelli del convertitore USB-TTL.

Nella millefori è utile predisporre anche le uscite dei pin RX, TX, GND, GPIO2, GPIO0 in modo da avere massima flessibilità e poter facilmente collegare l'unità per la programmazione oppure per sperimentare con le uscite.

Firmware

Collegare TX del convertitore USB-TTL a RX del ESP8266 e RX del convertitore a TX del ESP8266. Nota: il convertitore deve funzionare 3,3V e non a 5V!

Scaricare l'ultima versione di Nodemcu e attraverso ESPlorer caricare i tre sketch lua

ds18b20.lua

 --------------------------------------------------------------------------------
 -- DS18B20 one wire module for NODEMCU
 -- NODEMCU TEAM
 -- LICENCE: http://opensource.org/licenses/MIT
 -- Vowstar <vowstar@nodemcu.com>
 -- 2015/02/14 sza2 <sza2trash@gmail.com> Fix for negative values
 --------------------------------------------------------------------------------
 -- Set module name as parameter of require
 local modname = ...
 local M = {}
 _G[modname] = M
 --------------------------------------------------------------------------------
 -- Local used variables
 --------------------------------------------------------------------------------
 -- DS18B20 dq pin
 local pin = nil
 -- DS18B20 default pin
 local defaultPin = 9
 --------------------------------------------------------------------------------
 -- Local used modules
 --------------------------------------------------------------------------------
 -- Table module
 local table = table
 -- String module
 local string = string
 -- One wire module
 local ow = ow
 -- Timer module
 local tmr = tmr
 -- Limited to local environment
 setfenv(1,M)
 --------------------------------------------------------------------------------
 -- Implementation
 --------------------------------------------------------------------------------
 C = 0
 F = 1
 K = 2
 function setup(dq)
   pin = dq
   if(pin == nil) then
     pin = defaultPin
   end
   ow.setup(pin)
 end
 function addrs()
   setup(pin)
   tbl = {}
   ow.reset_search(pin)
   repeat
     addr = ow.search(pin)
     if(addr ~= nil) then
       table.insert(tbl, addr)
     end
     tmr.wdclr()
   until (addr == nil)
   ow.reset_search(pin)
   return tbl
 end
 function readNumber(addr, unit)
   result = nil
   setup(pin)
   flag = false
   if(addr == nil) then
     ow.reset_search(pin)
     count = 0
     repeat
       count = count + 1
       addr = ow.search(pin)
       tmr.wdclr()
     until((addr ~= nil) or (count > 100))
     ow.reset_search(pin)
   end
   if(addr == nil) then
     return result
   end
   crc = ow.crc8(string.sub(addr,1,7))
   if (crc == addr:byte(8)) then
     if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then
       -- print("Device is a DS18S20 family device.")
       ow.reset(pin)
       ow.select(pin, addr)
       ow.write(pin, 0x44, 1)
       -- tmr.delay(1000000)
       present = ow.reset(pin)
       ow.select(pin, addr)
       ow.write(pin,0xBE,1)
       -- print("P="..present)
       data = nil
       data = string.char(ow.read(pin))
       for i = 1, 8 do
         data = data .. string.char(ow.read(pin))
       end
       -- print(data:byte(1,9))
       crc = ow.crc8(string.sub(data,1,8))
       -- print("CRC="..crc)
       if (crc == data:byte(9)) then
         t = (data:byte(1) + data:byte(2) * 256)
         if (t > 32767) then
           t = t - 65536
         end
         if(unit == nil or unit == C) then
           t = t * 625
         elseif(unit == F) then
           t = t * 1125 + 320000
         elseif(unit == K) then
           t = t * 625 + 2731500
         else
           return nil
         end
         t = t / 10000
         -- print("Temperature="..t1.."."..t2.." Centigrade")
         -- result = t1.."."..t2
         return t
       end
       tmr.wdclr()
     else
     -- print("Device family is not recognized.")
     end
   else
   -- print("CRC is not valid!")
   end
   return result
 end
 function read(addr, unit)
   t = readNumber(addr, unit)
   if (t == nil) then
     return nil
   else
     return t
   end
 end
 -- Return module table
 return M

postThingSpeak.lua

 function postThingSpeak(level)
   conn=net.createConnection(net.TCP, 0)
   conn:on("receive", function(conn, payload)
     if (string.find(payload, "Status: 200 OK") ~= nil) then
       print("Posted OK");
     end
   end)
   conn:on("connection", function(connout, payloadout)
     print ("Posting...");
     conn:send("GET /update?api_key=CHIAVE&field1=" .. level
       .. " HTTP/1.1\r\n"
       .. "Host: api.thingspeak.com\r\n"
       .. "Connection: close\r\n"
       .. "Accept: */*\r\n"
       .. "User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n"
       .. "\r\n")
   end)
   conn:on("disconnection", function(connout, payloadout)
     connout:close();
     collectgarbage();
   end)
   conn:connect(80,'184.106.153.149') -- api.thingspeak.com 184.106.153.149
 end

Sostituire CHIAVE con la chiave ottenuta dalla registrazione su Thingspeak.com

init.lua

 --init.lua
 require("postThingSpeak")
 ledPin = 3 --> GPIO0
 value = gpio.LOW
 -- Initialise the pin
 gpio.mode(ledPin, gpio.OUTPUT)
 gpio.write(ledPin, value)
 print("Setting up WIFI...")
 wifi.setmode(wifi.STATION)
 wifi.sta.config("ssid","pw")
 wifi.sta.connect()
 tmr.alarm(1, 30*1000, 1, function()
   t = require("ds18b20")
   tempPin = 4 --> GPIO2
   t.setup(tempPin)
   temp = t.read()
   print("Temperature: "..temp.."C")
   print("Sending data to thingspeak.com")
   postThingSpeak(temp)
   -- Don't forget to release it after use
   t = nil
   ds18b20 = nil
   package.loaded["ds18b20"]=nil
 end)

Sostiture ssid e pw con il nome del access point e la password


ThingSpeak

https://thingspeak.com/channels/32934

Riferimenti



ESP8266 Redis

Una variante rispetto al primo progetto presentato in questa pagina: un sensore che pubblica i dati su un server redis, è una versione base che pubblica semplicemente i dati su server, il file DS18B20.lua è lo stesso usato nella prima parte di questa pagina.

Non avendo trovato un'esempio soddisfacente nelle librerie nodemcu, ho scritto quattro righe di codice per fare dei test con un sensore portatile.

wifi.lua

Il file di connessione Wifi l'ho mantenuto separato perchè a me piace così.

wifi.setmode(wifi.STATION)
wifi.sta.config("SSID_rete_WiFI", "password")
wifi.sta.connect()
ip = wifi.sta.getip()
print(ip)

redis.lua

La connessione a redis è molto semplice, è una semplice connessione telnet alla porta 6379. Attenzione bisogna che il server redis(magari su un raspberry) accetti connessioni dall'esterno perchè normalmente accetta solo connessioni dalla macchina su cui è in esecuzione quindi va modificato il file /etc/redis/redis.conf :

bind 127.0.0.1 indirizzo_ip_server_redis

e poi il server va restartato

/etc/init.d/redis-server restart

Attenzione: questo è solo un test, non ho settato password e tutta la parte di configurazione di sicurezza accessi è tralasciata, per un uso continuativo è utile fare un'analisi più approfondita a livello di autenticazione e controllo.

function sendtoredis(temp)
  conn=net.createConnection(net.TCP, 0)
  conn:on("receive", function(conn, payload)
    if (string.find(payload, ":") ~= nil) then
      print("Save: OK");
    end
    end)
   conn:on("connection", function(connout, payloadout)
     print ("Saving");
     conn:send("rpush esp_temp " .. temp  .. "\r\n")
   end)
   conn:on("disconnection", function(connout, payloadout)
     connout:close();
     collectgarbage();
   end)
   conn:connect(6379,'indirizzo_ip_server_redis') -- server redis
end


init.lua

Il file init lancia lo script di connessione wifi legge la temperatura dal sensore e lancia la funzione di pubblicazione su redis.

dofile("wifi.lua")

require("redis")
tmr.alarm(1, 30*1000, 1, function() 
   t = require("ds18b20")
   tempPin = 4 --> GPIO2
   t.setup(tempPin)
   temp = t.read()
   print("Temperature: "..temp.."C")
   print("Sending data to redis server")
   sendtoredis(temp)
   -- Don't forget to release it after use
   t = nil
   ds18b20 = nil
   package.loaded["ds18b20"]=nil
end)

Utilizzo

Questo esperimento mi serve per testare un sensore di temperatura 1 wire/wifi che produce dati per il mio progetto Termostato.

Riferimenti