?>/script>'; } ?> Arduino + OpenWrt Widgets Magazine

Autor Tema: Arduino + OpenWrt  (Leído 5234 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado raphik

  • *****
  • Mensajes: 102
Arduino + OpenWrt
« en: 21-06-2019, 10:58 (Viernes) »
INTRODUCCIÓN

No se puede hablar de Arduino + OpenWrt sin mencionar el Arduino Yún. Se trata de una placa en la que coexiste un microcontrolador Atmel ATmega32U4 y un microprocesador Atheros AR9331 interconectados por un puerto serie.

El entorno μC-Arduino se encarga de la lectura de sensores y del accionamiento de dispositivos.
El entorno μP-Linux, mediante scripts en Bash y Python y se encarga del tratamiento de datos, la interfaz de usuario e Internet.
La Web de Arduino muestra el Yún como producto retirado.

Un producto más cercano al concepto actual de IoT es el Dragino. Aquí, un conjunto μC-sensor-actuador —nodo— está unido inalámbricamente a un μP Linux —pasarela IoT— que le proporciona acceso a Internet.



PROPÓSITO

Conectar un router OpenWrt a un Arduino. Manejar las GPIOs del Arduino desde el router mediante scripts Lua. Para las pruebas utilizaré un HG553 con OpenWrt 18.06.2 y un Arduino Pro Mini.


LA CONEXIÓN SERIE

El Arduino Pro Mini tiene la ventaja de tener muy bajo consumo. Tal vez por ese motivo no tiene convertidor USB-Serie. Se le puede conectar un convertidor PL2303 externo de esta manera:

O, también se podría enchufar directamente al conector serie interno del HG553.

Para que OpenWrt reconozca el PL2303 hay que instalarle el driver correspondiente.
Código: [Seleccionar]
opkg update && opkg install kmod-usb-serial-pl2303
También hay que instalar la utilidad de configuración de puertos serie.
Código: [Seleccionar]
opkg install coreutils-stty
Ya se puede configurar el puerto serie.
Código: [Seleccionar]
stty -F /dev/ttyUSB0 raw speed 115200 -echo -hupcl
Para enviar mensajes del router al Arduino (desde una sesión ssh):
Código: [Seleccionar]
echo "mensaje" > /dev/ttyUSB0
Y para recibirlos :
Código: [Seleccionar]
cat /dev/ttyUSB0
(Continuará...)
« Última modificación: 30-06-2019, 12:10 (Domingo) por raphik »

Desconectado raphik

  • *****
  • Mensajes: 102
Encender / Apagar el LED de Arduino desde el router
« Respuesta #1 en: 22-06-2019, 17:33 (Sábado) »
Controlar salidas analógicas y digitales desde el router

La Interfaz Web tiene este aspecto.


Éste es el código HTML/Javascript de la Interfaz. Copiar en el router: /www/arduino.html
Código: [Seleccionar]
<html>
<head>
  <title>Arduino</title>
  <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  <META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
</head>
<body>
  <h2>Salidas digitales y analógicas (PWM)</h2>
    PWM03<input type="range" id="PWM03" min="0" max="255"value="0" onchange="analogic(id)"><br><br>
    DIG04<input type="checkbox" id="DIG04" onchange="digital(id)"><br>
    DIG05<input type="checkbox" id="DIG05" onchange="digital(id)"><br>
    DIG13<input type="checkbox" id="DIG13" onchange="digital(id)"><br>
    <form action="./cgi-bin/arduino/comando.lua" id="ejecutar" method="post" target="invisible">
      <input type="hidden" id="mensaje">
    </form>
<script>
function digital(pin) {
  var x = document.getElementById(pin).checked;
  document.getElementById("mensaje").name = pin;
  document.getElementById("mensaje").value = x;
  document.getElementById("ejecutar").submit();
}
function analogic(pin) {
  var x = document.getElementById(pin).value;
  document.getElementById("mensaje").name = pin;
  document.getElementById("mensaje").value = x;
  document.getElementById("ejecutar").submit();
}
</script>
  2019 :P raphik
  <p><iframe name="invisible" style="visibility:hidden;display:none"></iframe>
</body>
</html>

Éste script Lua envía las peticiones a través del puerto serie. Copiar en el router y dar permisos de ejecución (chmod -R 0777 /www/cgi-bin/arduino/comando.lua)
Código: [Seleccionar]
#!/usr/bin/lua
io.write("Content-type: Text/html\n\n")

local infoGET = io.read('*all')

print [[
<!DOCTYPE html><html lang="es">
<head>
  <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  <META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
</head>
<body>
  <h3>Visualizar POST</h3>
]]

io.write(infoGET.."<br>")
os.execute("stty -F /dev/ttyUSB0 raw speed 115200 -echo -hupcl > /dev/null")
serialPort = io.open("/dev/ttyUSB0","w")
serialPort:write(infoGET.."\n")
serialPort:close()

print [[
</body>
</html>
]]

Finalmente, las peticiones que llegan al Arduino son interpretadas por este sketch.
Código: [Seleccionar]
// Control de salidas analógicas (PWM) y digitales
// 2019 :P raphik

void setup() {
  Serial.begin(115200); // Inicializa la UART
  while (!Serial); // Esperr hasta que se conecte la consola
  Serial.println("¡Consola conectada!");
}

void loop() {
  if (Serial.available()) { // Se verifica si hay información entrante
    String data = Serial.readStringUntil('\n'); // Se lee la información entrante
    String modo = data.substring(0,3);
    int pin = data.substring(3,5).toInt();
    if(modo=="DIG") {
      boolean val = data.substring(6) == "true";
      pinMode(pin, OUTPUT);
      digitalWrite(pin, val);
    }
    if(modo=="PWM") {
      byte val = data.substring(6).toInt();
      pinMode(pin, OUTPUT);
      analogWrite(pin, val);
    }
  }
  delay(100);
}

También es posible manejar los pines de salida de Arduino desde la línea de comandos del router.
Código: [Seleccionar]
# Activar la salida digital 13
echo 'DIG13=true' > /dev/ttyUSB0
# Activar al 75% la salida analógica 3
echo 'PWM03=191' > /dev/ttyUSB0
« Última modificación: 25-06-2019, 22:08 (Martes) por raphik »

Desconectado Tki2000

  • Moderador
  • *
  • Mensajes: 2247
Re:Arduino + OpenWrt
« Respuesta #2 en: 22-06-2019, 18:20 (Sábado) »
¿Sabes que si le pones el firmware firmata al arduino y los paquetes de firmata a openwrt puedes manejar todos los pines digitales y analógicos y tener multitud de sensores?

Desconectado raphik

  • *****
  • Mensajes: 102
Re:Arduino + OpenWrt
« Respuesta #3 en: 22-06-2019, 19:16 (Sábado) »
No, no tenía ni idea. ¡Gracias!
¿Funciona en routers que no sean AR9331?


Desconectado Tki2000

  • Moderador
  • *
  • Mensajes: 2247
Re:Arduino + OpenWrt
« Respuesta #4 en: 23-06-2019, 13:33 (Domingo) »
No, no tenía ni idea. ¡Gracias!
¿Funciona en routers que no sean AR9331?

Sí, claro. Es genérico.
Tienes multitud de clientes para el firmata. En python, php, node, c#, ...
https://github.com/firmata/protocol
El cliente de openwrt está basado en node, si mal no recuerdo, así que tienes que instalar los paquetes de node y el del firmata.

Desconectado raphik

  • *****
  • Mensajes: 102
Re:Arduino + OpenWrt
« Respuesta #5 en: 23-06-2019, 18:26 (Domingo) »
Me daba el pálpito de que no iba a caber todo en el HG553.


Node ocupa unos cuantos megas y no deja espacio para Firmata.


Algo parecido le pasa a OpenWrt para Yún (Linino). Además de estar diseñado para el AR9331, corre sobre Python que se come el sistema de archivos.
En fin, probará node antes de meterle más memoria al router.

Desconectado Tki2000

  • Moderador
  • *
  • Mensajes: 2247
Re:Arduino + OpenWrt
« Respuesta #6 en: 23-06-2019, 21:17 (Domingo) »
Sí. Todo lo que sean lenguajes de programación o compiladores se comen todo el espacio del router.
Móntate un extroot y lo pruebas.  ;)

Desconectado raphik

  • *****
  • Mensajes: 102
Re:Arduino + OpenWrt
« Respuesta #7 en: 24-06-2019, 20:27 (Lunes) »
Al final no me ha hecho falta instalar firmata para controlar las salidas analógicas y digitales de Arduino. Ha bastado con una interfaz Web escrita en HTML/Javascript y un script en Lua. Y, como es logico, Arduino también ha necesitado su propio sketch.

El código está aquí: https://foro.seguridadwireless.net/openwrt/arduino-openwrt/msg366859/#msg366859

Ya veremos cómo me las arreglo para leer las entradas.
« Última modificación: 24-06-2019, 20:28 (Lunes) por raphik »

antares

  • Visitante
Re:Arduino + OpenWrt
« Respuesta #8 en: 26-06-2019, 10:28 (Miércoles) »
Me picó el gusanillo con el firmata y lo he probado en un arduíno conectado a un HG556 (openwrt 17.01.4).
Sólo he necesitado instalar los paquetes "lua-rs232" y "luasocket", que ocupan menos de 100KB.

En el arduíno he grabado el StandardFirmata.ino y en openwrt he utilizado los ejemplos que vienen en
"github.com/sivieri/lua-firmata/tree/master/src",  con algunas modificaciones en example.lua:

--require "posix"

arduino = Arduino("/dev/ttyACM0")
por
arduino = Arduino("/dev/ttyUSB0")

cur = posix.gettimeofday()["sec"]
por
cur = os.time()

root@HW556:~/lua-firmata-master/src# lua example.lua
OK, port open with values 'device: /dev/ttyUSB0, baud: 57600, data bits: 8, parity: none, stop bits: 1, flow control: off'
LED changed
0
LED changed
0
LED changed
87
LED changed
91
LED changed
114

Y eso es todo. El programilla activa/desactiva una salida digital y lee una entrada analógica.

Desconectado Tki2000

  • Moderador
  • *
  • Mensajes: 2247
Re:Arduino + OpenWrt
« Respuesta #9 en: 26-06-2019, 16:52 (Miércoles) »
Lo siguiente es conectar sensores i2c y leer los valores en openwrt...  >:D
https://github.com/firmata/protocol/blob/master/i2c.md

sourlemon

  • Visitante
Re:Arduino + OpenWrt
« Respuesta #10 en: 26-06-2019, 18:22 (Miércoles) »
Gracias por el tema.
« Última modificación: 26-06-2019, 22:17 (Miércoles) por Tki2000 »

Desconectado raphik

  • *****
  • Mensajes: 102
Re:Arduino + OpenWrt
« Respuesta #11 en: 27-06-2019, 15:03 (Jueves) »
Me picó el gusanillo con el firmata y lo he probado en un arduíno conectado a un HG556 (openwrt 17.01.4).
Gracias por comentar.
Yo también lo he estado probando en un Arduino Pro Mini conectado a un AR-5387un (Chaos Calmer 15.05). Ahora los tengo conectados mediante un cable de medio metro, pero tengo en mente conectarlos inalámbricamente vía LoRa para poder separarlos geográficamente varios Kms. El script ejemplo.lua se puede modificar fácilmente para leer cualquier entrada analógica o escribir cualquier salida digital. Lo que no veo es la manera de manejar las salidas analógicas (las pwm).

Código: [Seleccionar]
#!/usr/bin/lua
local simple_dispatcher = require "simple_dispatcher"
local arduino_module = require "arduino"
local socket = require "socket"

sched = SimpleDispatcher()
arduino = Arduino("/dev/ttyUSB0")
arduino.pinMode(13, ArduinoConstants.OUTPUT)

sched:AddRoutine(function()
  while true do
    arduino.processInput()
    coroutine.yield()
  end
end)

sched:AddRoutine(function()
  local last = 0
  local cur = 0
  local status = false
  while true do
    cur = os.time()
    if cur - last > 1 then
      if status then
        arduino.digitalWrite(13, 0)
        print("LED apagado")
      else
        arduino.digitalWrite(13, 1)
        print("LED encendido")
      end
      status = not(status)
      last = cur
      print("A0 --> "..arduino.analogRead(0))
      print("A1 --> "..arduino.analogRead(1))
      print("A2 --> "..arduino.analogRead(2))
      print("A3 --> "..arduino.analogRead(3))
      print("A4 --> "..arduino.analogRead(4))
      print("A5 --> "..arduino.analogRead(5))
    end
    coroutine.yield()
  end
end)
sched:Run()

Firmata se pasa todo el rato enviando datos del Arduino al Router. Se puede visualizar haciendo un cat /dev/ttyUSB0. Ese uso súper intensivo del puerto serie es justo lo contrario de lo que se busca en una conexión LoRa.

Otro inconveniente es que no hay seguridad de que los comandos que se envían desde el router llegen a ejecutarse en el Arduino. He cortado la conexión RS232 y el router no se entera. No me refiero a dejar al router sin UART, sino a desconectar cables.
« Última modificación: 30-06-2019, 12:14 (Domingo) por raphik »

antares

  • Visitante
Re:Arduino + OpenWrt
« Respuesta #12 en: 27-06-2019, 20:28 (Jueves) »
Toda la gestión del protocolo se hace en "arduino.lua" y viendo el código no parece que el autor haya incluído el procesamiento de los comandos extendidos SysEx, que son los que se ocupan del PWM o el I2C.

antares

  • Visitante
Re:Arduino + OpenWrt
« Respuesta #13 en: 28-06-2019, 21:45 (Viernes) »
Después de enredar otro rato he visto que sí se puede configurar una salida como PWM.
Hay que declarar una salida que lo soporte (ej. pin 3)
arduino.pinMode(3, ArduinoConstants.PWM)
y escribir  con
arduino.analogWrite(3, variablePWM)

El uso intensivo del puerto serie se debe a que el programa inicializa el firmata para que envíe datos siempre que haya un cambio en algún pin, ya sea analógico o digital, en vez de cuando se le soliciten. Y los valores analógicos siempre están fluctuando.
Estas órdenes están en las líneas 122 y 126 de arduino.lua
si ponemos p:write(write_format(true, "1", 0)) en la línea 122 el envío de datos analógicos cesa y el uso de la CPU baja a un 5% pero habría que rehacer la función "analogRead(pin)" para que reciba las lecturas de una entrada analógica a petición. Lo miraré.

Desconectado raphik

  • *****
  • Mensajes: 102
Re:Arduino + OpenWrt
« Respuesta #14 en: 30-06-2019, 11:53 (Domingo) »
Pues la verdad, no le veo mucho sentido a Firmdata. Me parece un desperdicio utilizar el Arduino como simple repetidor, con el único propósito de manejar sus entradas y salidas desde el router con un script Lua.

Me parece más interesante dejar que Arduino se encargue de la lectura de los sensores, del accionamiento de dispositivos y de los cálculos a bajo nivel y utilizar el router para el registro de datos, la interfaz de usuario e Internet.
« Última modificación: 30-06-2019, 12:08 (Domingo) por raphik »

Desconectado eduperez

  • **
  • Mensajes: 42
Re:Arduino + OpenWrt
« Respuesta #15 en: 01-07-2019, 13:21 (Lunes) »
Pues la verdad, no le veo mucho sentido a Firmdata. Me parece un desperdicio utilizar el Arduino como simple repetidor, con el único propósito de manejar sus entradas y salidas desde el router con un script Lua.

Me parece más interesante dejar que Arduino se encargue de la lectura de los sensores, del accionamiento de dispositivos y de los cálculos a bajo nivel y utilizar el router para el registro de datos, la interfaz de usuario e Internet.

Supongo que depende del uso que se le quiera dar: en algunos casos puede interesar que el Arduino tenga cierta inteligencia, como tu propones; en otros casos, es más sencillo tener que programar sólo un dispositivo. A mí me parece una opción muy interesante para añadir varias entradas y salidas al router de forma rápida y barata: con un cable USB, un Arduino Nano, y un par de componentes discretos ya tendría suficiente.
« Última modificación: 01-07-2019, 13:23 (Lunes) por eduperez »

antares

  • Visitante
Re:Arduino + OpenWrt
« Respuesta #16 en: 01-07-2019, 20:49 (Lunes) »
Para el que no quiera liarse con el protocolo firmata hay otra opción similar mediante una interfaz de línea de comandos (CLI) que corre en un arduíno con atmega328.
Hay que buscar en github por piconomix-fwlib, descargarse el zip y grabar en el arduíno el fichero cli_explorer.hex utilizando el programa XLoader.
Al conectarte en modo terminal te saca un menú con opciones para configurar pines, I2C, SPI, RTC y entradas analógicas.
Yo lo tuve instalado en un arduino Ethernet y corría sin problemas.