Control de Relays por Ethernet con Arduino Nano

Este es un proyecto que tenia en la carpeta de pendientes hace mucho tiempo; queria armar algo que me permite apagar y prender el router wifi sin necesidad de ir hasta el lugar; es un equipo viejo que ya no se actualiza el firmware por lo cual me dio la excusa perfecta para trabajar con este proyecto.

La idea es conectarnos a un dispositivo en la red mediante cable (nada de red inalambrica) y poder apagar o encender un dispositivo; en este caso a 12V, aunque es muy facil de adaptarlo para trabajar con 220V.

Para ello utilizamos un Arduino Nano para manejar la lógica; el modulo ethernet ENC28J60, una fuente DC-DC que convierte los 12V a 5V para alimentar la electrónica y por ultimo un modulo relay.

El circuito es el siguiente:

Algunas consideraciones respecto al gráfico anterior
1. El modulo Ethernet si bien soporta 5V, lo recomendable es que opere con 3.3V; utilice un regulador lineal para obtener los 3.3V, puesto que la salida de 3.3V del arduino nano no era suficiente.
2. El modulo de rele que utilice es doble; en el gráfico arme con uno simple; en los módulos simples que tengo la señal es el pin del medio.

El cuadro de conexiones sobre el Arduino Nano seria el siguiente:

ArduinoModulo EthernetRelay
D2Signal
D10SS(CS)
D11MOSI(SI)
D12MISO(SO)
D13SCK

El código del programa es bastante sencillo:


1
2
3
4
5
6
7
8
9
10
11
#include <EtherCard.h>

static byte mymac[] = {0xDD,0xDD,0xDD,0x00,0x01,0x05};
static byte myip[] = {192,168,2,5};
byte Ethernet::buffer[700];

const int ledPin1 = 2;
const int ledPin2 = 3;

char* EstadoLed1="OFF";
char* EstadoLed2="OFF";

Se importa la libreria EtherCard, luego se define la mac del dispositivo y la dirección IP; en este caso no vamos a utilizar DHCP para que tome una IP sino definimos una estatica. Luego se establecen cuales serán los GPIO del Arduino que usaremos para el relay, en este caso el D2.

Por ultimo se definen dos variables que mantendrán el estado de los relay.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void setup () {
 
  Serial.begin(9600);
 
  if (!ether.begin(sizeof Ethernet::buffer, mymac, 10))
    Serial.println( "No se ha podido acceder a la controlador Ethernet");
 else
   Serial.println("Controlador Ethernet inicializado");
 
  if (!ether.staticSetup(myip))
    Serial.println("No se pudo establecer la dirección IP");

  Serial.println();
 
  pinMode(ledPin1, OUTPUT);
  digitalWrite(ledPin1, HIGH);

  pinMode(ledPin2, OUTPUT);
  digitalWrite(ledPin2, HIGH);
 
}

En el método setup() inicializamos la comunicación serie, sirve para el momento de depurar el programa luego no es necesaria; luego inicializamos la conexion Ethernet y por ultimo establecemos la forma de operación de los GPIO, en este caso ambos como salida.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void loop() {
 
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
 
  if(pos) {
    // http://192.168.2.5/?status1=ON
    if(strstr((char *)Ethernet::buffer + pos, "GET /?status1=ON") != 0) {
      Serial.println("Comando ON recivido");
      digitalWrite(ledPin1, LOW);
      EstadoLed1 = "ON";
    }

    if(strstr((char *)Ethernet::buffer + pos, "GET /?status1=OFF") != 0) {
      Serial.println("Comando OFF recivido");
      digitalWrite(ledPin1, HIGH);
       EstadoLed1= "OFF";
    }  

    if(strstr((char *)Ethernet::buffer + pos, "GET /?status2=ON") != 0) {
      Serial.println("Comando ON recivido");
      digitalWrite(ledPin2, LOW);
      EstadoLed2 = "ON";
    }

    if(strstr((char *)Ethernet::buffer + pos, "GET /?status2=OFF") != 0) {
      Serial.println("Comando OFF recivido");
      digitalWrite(ledPin2, HIGH);
       EstadoLed2= "OFF";
    }
         
    ether.httpServerReply(homePage()); // se envia página Web
  }
}

Dentro de la función loop(), lo primero que realiza es recibir los paquetes. Si los paquetes finalizan en GET /?status1=ON indica que el relay1 debe encenderse, si en cambio finaliza en GET /?status1=OFF debe apagarse, mismo caso para el relay2.

Luego de realizar el cambio de estado, asigna el nuevo estado a la variable EstadoLed1 o EstadoLed2 segun corresponda y por ultimo devuelve el resultado de la funcion homePage().


1
2
3
4
5
6
7
8
9
10
11
static word homePage() {
 
 BufferFiller bfill = ether.tcpOffset();
 
 bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\n"
      "Content-Type: text/htmlrnPragma: no-cachernRefresh: 5\r\n\r\n"
      "{"uptime":"$L","s1":"$S","s2":"$S"}"      
      ),millis()/1000,EstadoLed1,EstadoLed2);
     
  return bfill.position();
}

La funcion homePage() devuelve un word conteniendo un JSON, donde se informa el tiempo de uptime del dispositivo y el estado de cada relay.

Luego de cargado el programa simplemente accediendo a la direccion IP del dispositivo mas /?status1=ON podes activar el rele y con/?status1=OFF lo apagamos.

En thingiverse pueden encontrar los archivos STL para descargar la caja e imprimirla si lo desean.

En la imagen anterior pueden ver como quedo armada la caja con la electrónica interna.

El repositorio donde pueden encontrar el código completo es el siguiente:
https://github.com/gsampallo/ArduinoLanSwitch

A continuación pueden encontrar el video completo de como se armo:

Instalar Mosquitto fácil y rápido

La parte de rápido depende mucho de la conexión de internet de cada uno para poder descargar los archivos, habiendo hecho esta salvedad.

Nos encontramos que para la mayoría de los proyectos IoT en los que trabajamos necesitamos tener disponible un servidor broker para poder enviar mensajes con el dispositivo que estamos armando; en muchas ocasiones con un broker publico de internet solucionamos el problema, pero otras veces necesitamos tener algo local (a raíz que nuestra conectividad no es estable o simplemente no disponemos de acceso a internet donde vamos a instalar el dispositivo).

Mosquitto es uno de los brokers mas utilizado por ser opensource y ser mantenido por la fundación Apache, para instalarlo es entornos linux es sencillo simplemente lo hacemos por medio del gestor de paquetes.

Pero la realidad es que en la mayoría de los laboratorios en escuelas o universidades las pcs tiene Windows; e instalar el servicio del broker resulta un poco engorroso, particularmente si no se va a usar de manera dedicada y no queremos el servicio corriendo.

La forma mas sencilla de instalarlo es utilizando el esquema de contenedores de Docker, tres sencillos pasos:

  1. Será necesario instalar primero Docker en nuestra pc, la instalación es sencilla simplemente damos continuar y al finalizar nos pedirá reiniciar el sistema.
  2. Luego que tengamos Docker corriendo en el sistema (en la traybar veremos el icono de la ballena) ejecutamos desde la consola:

1
docker pull eclipse-mosquitto

Para que descargue el contenedor de mosquitto en nuestra pc.

3. Creamos una instancia del contenedor, especificando el puerto sobre el que va a trabajar, utilizaremos los puertos 9001 y 1883 que son estándar para este servicio:


1
docker run -p 1883:1883 -p 9001:9001 eclipse-mosquitto

Esto crea un contenedor que sirve para entornos de prueba y laboratorio, no se guarda las configuraciones, ni tienen ningún mecanismo de seguridad.

Pero la puesta en marcha es rápida y sin complicaciones; luego de que se haya descargado la primera vez el contenedor las siguientes ejecuciones son aun mas ágiles.