domingo, 1 de noviembre de 2015

Domos con NodeMCU Lua

Pongámonos en situación: "Domos" es mi proyecto personal de control remoto de cosas, como por ejemplo de una estufa de Pellets. El asunto lo tengo solucionado utilizando como hardware el micro-controlador Arduino, pero éste tiene un defecto importante y es que si se va la luz no se recupera: Hay que pulsar físicamente el botón Reset.

Además, la solución con Arduino viene utilizando una conexión Ethernet lo que me obliga a cablear hasta el punto de acceso.

Así que me he puesto a investigar un nuevo hardware: El Chip ESP2866 y el sistema IoT (Internet of Things) llamado NodeMCU, que se programa con un lenguaje tipo Scripting que es muy parecido a Python. Este sistema tiene una ventaja enorme: Viene con Wifi integrado. Cuesta muy poco: 7€ en China, y tiene un IDE de desarrollo muy productivo.




Ahora estoy escribiendo el código fuente equivalente al de Arduino, para el control de la estufa. De momento, con este código puedo enviar la temperatura y encender un Led en función del estado deseado de la estufa, Solamente me falta incluir el envío de la señal de Infrarrojos para encender o apagar la estufa de verdad.

El código fuente es el siguiente:


-- ------------------- CONFIGURACION ----------------------
ID_SENSOR=1235
ID_ACTUADOR=2234
PIN_ESTADO=1
PIN_BLINK=2
N_TEMP=4    -- Cada cuantas lecturas de temperatura guardar
-- --------------------------------------------------------

-- Contador de envíos de temperatura para insertar solo de  vez en cuando.
contTemperatura=0
swBlink=true

function procesar()
    wifi.setmode(wifi.STATION)
    wifi.sta.config("MACETERO","xxxxx")
    print("Conectando a la WIFI...")
    
    tmr.alarm(1, 1000, 1, function() 
        if wifi.sta.getip()== nil then 
            print("IP unavaiable, Waiting...") 
        else 
            tmr.stop(1)
            print("Config done, IP is "..wifi.sta.getip())
            doPeticion(enviarTemperatura, recibidaTemperatura)
            
            --wifi.sta.disconnect()
        end 
    end)
end

function recibidaTemperatura(sck, c)
    print("Ok recibida respuesta temperatura")
    --print(c)
    doPeticion(consultarEstado, procesarEstado)
end

function procesarEstado(sck, c)
    buffer=buffer..c   
    print("Ok recibida respuesta consulta estado")
    --print( "Recibido " .. buffer)
    
    if string.find(c,"ON") then
        print ("ON!!!!")
        gpio.write(PIN_ESTADO, gpio.HIGH)
    end
    if string.find(c,"OFF")  then
        print ("OFF!!!!")
        gpio.write(PIN_ESTADO, gpio.LOW)
    end
end

function doPeticion(onConnection, onReceive)
    sk=net.createConnection(net.TCP, 0)
    print("Conectando...")
    sk:connect(80,"php-domos.rhcloud.com")
    sk:on("connection", onConnection)
    sk:on("disconnection", function(sck) print "Desconectado" end)
    sk:on("sent", function(sck) print "Sent" end)
    sk:on("receive", onReceive)
end


function enviarTemperatura(sk)
    --tmr.delay(1000000)
    print ("Enviando...")
    v=node.readvdd33() / 10
    r=adc.read(0)
    c=r*v/1024
    insertar=0
    if contTemperatura == N_TEMP then
        insertar=1
        contTemperatura=0
    end
    contTemperatura=contTemperatura+1
    sk:send("GET /insert.php?sensor=" .. ID_SENSOR .. "&valor=" .. c .. "&insertar=" ..insertar.. " HTTP/1.1\r\n"
        .."Host: php-domos.rhcloud.com\r\n"
        .."Connection: keep-alive\r\n"
        .."Accept: */*\r\n\r\n")
    -- tmr.delay(10000000)
    print ("Fin")
end

function consultarEstado(sk)
    --tmr.delay(1000000)
    print ("Consultando estado...")
    buffer=""
    sk:send("GET /actuador.php?id=" .. ID_ACTUADOR .. " HTTP/1.1\r\n"
        .."Host: php-domos.rhcloud.com\r\n"
        .."Connection: keep-alive\r\n"
        .."Accept: */*\r\n\r\n")
    -- tmr.delay(10000000)
    print ("Fin")
end

function blink()
    if swBlink then
        gpio.write(PIN_BLINK, gpio.HIGH)        
    else
        gpio.write(PIN_BLINK, gpio.LOW)
    end
    swBlink=not swBlink
end

gpio.mode(PIN_ESTADO,gpio.OUTPUT)
gpio.mode(PIN_BLINK,gpio.OUTPUT)
procesar()
tmr.alarm(2, 5 * 60 * 1000, 1, procesar)
tmr.alarm(3, 1000, 1, blink)