Node Mcu es un firmware opensource basado en lua para el ESP8266 y ESP32. utiliza un sistema de archivos SPIFFS basado en flash en el módulo. NodeMCU se implementa en C y se superpone en el SDK NON-OS de Espressif.
El modelo de programación de NodeMCU es similar al de Node.js, solo que en Lua. Es asíncrono y está orientado a eventos. Las funciones, por lo tanto, tienen parámetros para funciones de devolución de llamada.
Mas informacion sobre NodeMcu aquí
Construyendo el Firmware
Existen 3 caminos para construir el firmware:
Si quieres iniciar un poco más rápido, hemos preparado una imagen lista para instalar la cual puedes descargar aquí.
Instalar el Firmware (Flashear)
Instalar imagen en la placa es bastante sencillo. Para esto usaremos una herramienta llamada esptool. Esta herramienta está escrita en python por lo que debemos instalar python en nuestro equipo (descarga python3 aquí).
La herramienta esptool puedes descargarla en el siguiente enlace: https://github.com/espressif/esptool y está soportada por windows, linux, OS X y cualquier sistema operativo que pueda correr python.
Para instalar el firmware es muy importante poner la placa en modo flash, para esto usaremos los pines [flash] en la placa designados para dicho proposito. Usaremos el jumper para poner la placa en modo flash.
PASO 1:
Ejecutaremos el siguiente comando para borrar la memoria del microcontrolador:
esptool.py --port <serial-port-of-ESP8266> erase_flash
Descripción de los parámetros:
<serial-port-of-ESP8266> El puerto serial (COMx Windows, ttyxxx Linux).
PASO 2:
Instalaremos la imagen con un simple comando en nuestra placa. Para lo que conectaremos nuestra placa a nuestro PC y abrimos una consola de de comandos (terminal) y digitamos el siguiente comando:
esptool.py --port <serial-port-of-ESP8266> write_flash -fm <flash-mode> -fs 4MB 0x00000 <nodemcu-firmware.bin>
Descripción de los parámetros:
<serial-port-of-ESP8266> : El puerto serial (COMx Windows, ttyxxx Linux)
<flash-mode>
qio (ESP-01/07 modulos de 512kByte) |
dio (ESP-12 módulos de 4 MByte o más) |
dio (ESP8285)
<nodemcu-firmware>.bin (Ruta y nombre del archivo que contiene la imagen).
Ejemplo:
esptool.py --port COM3 write_flash -fm dio 0x00000 -fs 4MB C:\lua.bin
Una vez terminado el proceso podemos verificar que el firmware ha sido instalado correctamente
abriendo un terminal serial ( configurar baudios en 115200) y presionando el botón reset de la
placa. En el terminal veremos lo siguiente:
Ahora estámos listos para iniciar a programar nuestra placa Motika usando NodeMcu, iniciemos
con los siguientes tutoriales:
Escribiendo código
Podemos escribir nuestro código en cualquier editor, lo importante es tener en cuenta que el archivo donde escribimos nuestro código sea de extensión .lua
Es importante resaltar que nuestro archivo contenedor del script puede tener cualquier nombre, pero si queremos que nuestro script se ejecute en el inicio una vez la placa sea conectada nuestro archivo debe tener el nombre init.lua
Cargando código a la placa.
Existen diferentes alternativas para cargar el código a la placa como nodemacu-uploader.py(escrita en python) y NodeMCU-Tool pero la más usada por su facilidad y flexibilidad es ESPlorer (Java) este es un pequeño IDE que nos permite escribir código y subirlo directamente a la placa sin necesidad de aplicaciones externas.
Descargar ESPlorer: https://github.com/4refr0nt/ESPlorer.
Más documentación sobre como subir código a la placa: https://nodemcu.readthedocs.io/en/release/upload/
Escribiendo código
Motika está basada en el ESP8266, este microcontrolador cuenta con un chip wifi configurable el cual permite conectarse a una red wifi existente (MODO AP) o crear una red wifi desde el propio módulo (MODO STATION) permitiendo así comunicarnos con dispositivos externos mediante protocolos de comunicaciones IP . Toda la informacion sobre wifi en: https://nodemcu.readthedocs.io/en/release/modules/wifi/
Conceptos generales de wifi (esto puede ser un modal)
Conectar a red wifi.
(ver antes conceptos generales de wifi)
Conectar con una red wifi es muy fácil, para esto usaremos el siguiente código:
wifi.setmode(wifi.STATION)
SSID = "ceenford-latinoamerica"
PASS = "44442832"
station_cfg={}
station_cfg.ssid = SSID
station_cfg.pwd = PASS
station_cfg.save = true
wifi.sta.config(station_cfg)
wifi.sta.connect()
Primero creamos una variable de tipo objeto que almacena los parámetros de configuración.
ssid = Nombre de la red wifi a la que se conectará
pwd = Clave de la red
save = ¿se almacenará la configuración en la flash?
Se configura el módulo como STATION para conectar a una red wifi existente y luego se pasa la variable que contiene la configuración a la función wifi.sta.config(station_cfg) encargada de establecer la configuración en el módulo.
Una vez establecida la configuración procedemos a llamar la función wifi.sta.connect() la cual inicia la conexión. Esta función puede recibir como parámetro un callback [connected_cb] el cual se ejecutará cuando la conexión sea establecida. Ejemplo: wifi.sta.connect([connected_cb]).
A continuacion se muestra el codigo completo para conectar a una red wifi y verificar el estado de la conexión.
wifi.setmode(wifi.STATION)
SSID = "nombre de la red"
PASS = "clave de la red"
station_cfg = {}
station_cfg.ssid = SSID
station_cfg.pwd = PASS
station_cfg.save = true
wifi.sta.config(station_cfg)
wifi.sta.connect()
awaitTime = 0
print("Conectando a la red wifi, espere...")
tmr.alarm(1, 1000, 1, function()
if wifi.sta.getip() == nil then
awaitTime = awaitTime + 1
if awaitTime > 20 then
print("falló la conexion a la red wifi")
tmr.stop(1)
end
else
print("IP del modulo Motika "..wifi.sta.getip())
print("conectado a la red "..SSID)
tmr.stop(1)
end
end )
Crear red wifi.
(ver antes conceptos generales de wifi)
wifi.setmode(wifi.SOFTAP)
cfg={}
cfg.ssid="myssid"
cfg.pwd="mypassword"
wifi.ap.config(cfg)
Primero creamos una variable de tipo objeto que almacena los parámetros de configuración.
ssid = Nombre de la red wifi a la que se conectará
pwd = Clave de la red
Se configura el módulo como AP para crear redes wifi y luego se pasa la variable que contiene la configuración a la función wifi.ap.config(cfg) encargada de establecer la configuración en el módulo. Con esto ya podríamos verificar la existencia de una nueva red wifi con nombre y clave establecidos en cualquier dispositivo con conexión wifi.
Creando Socket TCP/IP
Un socket TCP-IP permite la comunicación de nuestra placa con cualquier software o aplicación. Crear uno es bastante facil.
ss = net.createServer(net.TCP,1000)
ss:listen(8080, function(conn)
conn:on("receive", receiver)
end )
net.createServer Recibe como parámetros el tipo de servidor (TCP/UDP) y el tiempo de espera para estabilizar la conexión. Eta función devuelve un socket el cual es almacenado en la variable ss.
ss:listen Recibe como parámetros el puerto donde se escuchará la conexión y una funcion donde luego procesaremos los datos recibidos desde el cliente.
A continuación se muestra el códico completo para crear un socket TCP/IP en la red wifi. La conexión se escuchará en el puerto 8080 pero puedes modificar el valor del puerto por el que gustes.
wifi.setmode(wifi.STATION)
SSID = "nombre de la red"
PASS = "clave de la red"
station_cfg = {}
station_cfg.ssid = SSID
station_cfg.pwd = PASS
station_cfg.save = true
wifi.sta.config(station_cfg)
wifi.sta.connect()
awaitTime = 0
print("Conectando a la red wifi, espere...")
tmr.alarm(1, 1000, 1, function()
if wifi.sta.getip() == nil then
awaitTime = awaitTime+1
if awaitTime > 20 then
print("falló la conexion a la red wifi")
tmr.stop(1)
end
else
print("IP del modulo Motika "..wifi.sta.getip())
print("conectado a la red "..SSID)
ss=net.createServer(net.TCP,1000)
ss:listen(8080, function(conn)
conn:on("receive", receiver)
end )
tmr.stop(1)
end
end )
function receiver(sck, data)
print(data)
response = "Hola soy tu placa Motika By CVR"
sck:send(response)
end
Controlando Cargas:
Motika, cuenta con 4 relés mecánicos en placa con posibilidad de control de 8 canales de relé (P4-P7) y hasta 16 canales (agregando módulo de expansión de 8 canales extra) completamente aislados del microcontrolador y controlados por el módulo de expansión PCF8574. permitiendo el control de las cargas haciendo uso de solo 2 pines del microcontrolador (I2C).
A continuación el código de muestra para el control de cargas mediante el uso de relés.
Para facilitar el uso de los relés en placa hemos desarrollado un script que se encarga del control de los mismos. Este script debe ser cargado a la placa y ejecutado en la primera linea para cargar sus funciones.
A continuación el escript pcf8574_control.lua
PCF8574_address = 0x20
last_byte = 0
function pcf8574_init(init,SDA,SCL) --inicializa el bus i2c
id = 0
pinSDA = SDA --4
pinSCL = SCL --3
speed = i2c.SLOW
if init then
i2c.setup(id, pinSDA, pinSCL, speed)
end
PCF8574_clear()
end
function PCF8574_clear()
writeToPCF(0)
last_byte = 0
end
function writeToPCF(byte) --escribe los datos al pcf8574 modulo vía i2c
i2c.start(id)
i2c.address(id, PCF8574_address,i2c.TRANSMITTER)
i2c.write(id,byte)
i2c.stop(id)
end
function on_io(pin)
last = string.byte(get_io())
bases = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80}
if pin == "all" then
nb = bit.band(0xFF,255)
writeToPCF(nb)
last_byte = 255
elseif pin > 0 and pin < 9 then
nuevo = bit.bor(bases[pin],last)
writeToPCF(nuevo)
last_byte = nuevo
end
end
function off_io(pin)
last_off = last_byte
bases_off = {0xFE,0xFD,0xFB, 0xF7,0xEF,0xDF,0xBF,0x7F}
if pin =="all" then
writeToPCF(0)
last_byte = 0
elseif pin > 0 and pin < 9 then
nuevo_off = bit.band(bases_off[pin],last_off)
writeToPCF(nuevo_off)
last_byte = nuevo_off
end
end
function get_io()
i2c.start(id)
i2c.address(id, PCF8574_address, i2c.RECEIVER)
c = i2c.read(id, 1)
i2c.stop(id)
return c
end
Una vez cargado el script podemos controlar cargas haciendo uso de los relés integrados en la placa.
El siguiente codigo activa y desactiva cada uno de los relé de forma secuencial.
pcf8574_init(true,4,3)
PCF8574_clear()
on_io(1)
tmr.delay(1000)
on_io(2)
tmr.delay(1000)
on_io(3)
tmr.delay(1000)
on_io(4)
tmr.delay(4000)
off_io(1)
tmr.delay(1000)
off_io(2)
tmr.delay(1000)
off_io(3)
tmr.delay(1000)
off_io(4)
tmr.delay(1000)
Controlando cargas vía TCP-IP
Por ultimo, dejaremos un ejemplo completo en el que se mostrará como controlar cargas desde el modulo Motika desde cualquier cliente TCP/IP por medio de la red wifi.
Recuerda que esta es solo una pequeña aplicación para instruirte sobre como funciona la placa, pero con tu imaginación podrás hacer cualquier cosa.
dofile("pcf8574_control.lua")
pcf8574_init(true,4,3)
PCF8574_clear()
wifi.setmode(wifi.STATION)
SSID = "Nombre de la red"
PASS = "Clave de la red"
station_cfg = {}
station_cfg.ssid = SSID
station_cfg.pwd = PASS
station_cfg.save = true
wifi.sta.config(station_cfg)
wifi.sta.connect()
awaitTime = 0
print("Conectando a la red wifi, espere...")
tmr.alarm(1, 1000, 1, function()
if wifi.sta.getip() == nil then
awaitTime = awaitTime+1
if awaitTime > 20 then
print("falló la conexion a la red wifi")
tmr.stop(1)
end
else
print("IP del modulo Motika "..wifi.sta.getip())
print("conectado a la red "..SSID)
ss=net.createServer(net.TCP,1000)
ss:listen(8080, function(conn)
conn:on("receive", receiver)
end )
tmr.stop(1)
end
end )
function receiver(sck, data)
print("Datos recibidos: "..data)
response = " "
if data == "OnCharge1" then
on_io(1)
response = "Carga #1 encendida"
elseif data == "OnCharge2" then
on_io(2)
response = "Carga #2 encendida"
elseif data == "OnCharge3" then
on_io(3)
response = "Carga #3 encendida"
elseif data == "OnCharge4" then
on_io(4)
response = "Carga #4 encendida"
elseif data == "OffCharge1" then
off_io(1)
response = "Carga #1 encendida"
elseif data == "OffCharge2" then
off_io(2)
response = "Carga #2 encendida"
elseif data == "OffCharge3" then
off_io(3)
response = "Carga #3 encendida"
elseif data == "OffCharge4" then
off_io(4)
response = "Carga #4 encendida"
end
sck:send(response)
end