Control domótico con Arduino

Muy buenas! Hoy vamos a ver cómo podemos realizar un pequeño y sencillo proyecto de control domótico con el Arduino, en primer lugar vamos a ver los componentes necesarios para el tutorial:

  1. Placa Arduino Uno Rev 3.
  2. Shield Ethernet.
  3. Placa de Relé de 250V 10A.
  4. Kit de PLC (Opcional, eso nos permite que no se vean los cables de red en el shield de Ethernet).
  5. Terminación de conector a red eléctrica.
  6. Cables varios.

En primer lugar vamos a usar la terminación de conector a red eléctrica para ponerle los cables y dejarlo ya cerrado de tal forma que lo podamos atornillar a la placa de reles, de tal forma que quedará como en la imagen:

Terminación con Relé

Y ahora conectamos la placa del relé con el arduino para ponerle la masa, los 5v y el cable de control, en mi programa he usado el pin 2 para realizar esta tarea.

Reles con Arduino

Ahora ya tenemos todo el montaje realizado, ahora vamos a ver el programa fuente para realizar la gestión de todo. Yo he usado la librería de Webduino para que fuera más fácil la gestión web.

/*--------------------------------------------------------------
  Program:      IguaHouse

  Description:  Servidor Web protegido mediante contraseña
                para controlar una salida de Luz

  Hardware:     - Arduino Uno y una shield de Ethernet.
                - Una placa de reles conectada al arduino en
                 el pin 2 y GND

  Software:     Desarrollado usando el IDE 1.0.5 y la
                libreria de Webduino

  References:   - Foro de Arduino
                - Documentacion de Webduino

  Date:         26 Diciembre del 2013

  Author:       Arturo Igualada http://wordpress.igua.es
--------------------------------------------------------------*/

/* you can change the authentication realm by defining
 * WEBDUINO_AUTH_REALM before including WebServer.h */
#define WEBDUINO_AUTH_REALM "Igua Private Site"

#define Host_name "Igua"

#include "SPI.h"
#include "Ethernet.h"
#include "WebServer.h"

/* CHANGE THIS TO YOUR OWN UNIQUE VALUE.  The MAC number should be
 * different from any other devices on your network or you'll have
 * problems receiving packets. */
byte mac[] = { 0x16, 0x16, 0x16, 0x16, 0x16, 0x01 };

/* CHANGE THIS TO MATCH YOUR HOST NETWORK.  Most home networks are in
 * the 192.168.0.XXX or 192.168.1.XXX subrange.  Pick an address
 * that's not in use and isn't going to be automatically allocated by
 * DHCP from your router. */
IPAddress ip(172,27,0,15);
IPAddress gateway(172,27,0,1);
IPAddress subnet(255, 255, 255, 0);

/* This creates an instance of the webserver.  By specifying a prefix
 * of "", all pages will be at the root of the server. */
#define PREFIX ""
WebServer webserver(PREFIX, 80);

boolean LED_status = 0;   // state of LED, off by default

// ROM-based messages used by the application
// These are needed to avoid having the strings use up our limited
// amount of RAM.

P(Page_start) = "<html><head><title>ManchiHouse</title></head><body>\n";
P(Page_end) = "</body></html>";
P(Get_head) = "<h1>GET from ";
P(Post_head) = "<h1>POST to ";
P(Unknown_head) = "<h1>UNKNOWN request for ";
P(Default_head) = "unidentified URL requested.</h1><br>\n";
P(Line_break) = "<br>\n";
P(Form_Inicio) = "<form method=\"get\">";
P(Form_Final) = "</form>";

#define NAMELEN 32
#define VALUELEN 32

String GetParam(String ParamName, WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  URLPARAM_RESULT rc;
  char name[NAMELEN];
  char value[VALUELEN];
  String ReturnParam = "";
  if (strlen(url_tail))
    {
    while (strlen(url_tail))
      {
      rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN);
      if (rc != URLPARAM_EOS && String(name) == ParamName)
        {
        ReturnParam = value;
        }
      }
    }
  if (type == WebServer::POST)
  {
    while (server.readPOSTparam(name, NAMELEN, value, VALUELEN))
    {
      if (String(name) == ParamName)
      {
        ReturnParam = value;
      }
    }
  }

  return ReturnParam;
}

//Se mira la query para ver si se ha de activar o desactivar la linea
String ProcesarCheckbox(String Estado)
{
  LED_status = 0;
  if (Estado == "1")
  {
    LED_status = true;
  }

    if (LED_status) {    // switch LED on
        digitalWrite(2, HIGH);
        // checkbox is checked
        return "<input type=\"checkbox\" name=\"Luz\" value=\"1\" onclick=\"submit();\" checked>Apagar Luz";
    }
    else {              // switch LED off
        digitalWrite(2, LOW);
        // checkbox is unchecked
        return "<input type=\"checkbox\" name=\"Luz\" value=\"1\" onclick=\"submit();\">Encender Luz";
    }
}

void indexCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  server.httpSuccess();
  if (type != WebServer::HEAD)
  {
    P(Saludo) = "<h1>Bienvenido a IGUA!</h1><a href=\"control.html\">Acceder</a>";
    server.printP(Saludo);
  }
}

void controlCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  /* if the user has requested this page using the following credentials
   * username = user
   * password = user
   * display a page saying "Hello User"
   *
   * the credentials have to be concatenated with a colon like
   * username:password
   * and encoded using Base64 - this should be done outside of your Arduino
   * to be easy on your resources
   *
   * in other words: "YWRtaW46YWRtaW4=" is the Base64 representation of "admin:admin"
   *
   * if you need to change the username/password dynamically please search
   * the web for a Base64 library */
  if (server.checkCredentials("YWRtaW46YWRtaW4="))
  {
    server.httpSuccess();
    String Estado = GetParam("Luz", server, type, url_tail, tail_complete);

    if (type != WebServer::HEAD)
    {
      P(Control_Head) = "<h1>Bienvenido al control de IGUA</h1><p>Indica si deseas encender o apagar la luz</p>";

      server.printP(Control_Head);
      server.printP(Form_Inicio);
      server.println(ProcesarCheckbox(Estado));
      server.printP(Form_Final);
    }
  }
  else
  {
    Serial.println("No valido");
    /* send a 401 error back causing the web browser to prompt the user for credentials */
    server.httpUnauthorized();
  }
}

void failCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  //this line sends the "HTTP 400 - Bad Request" headers back to the browser
  server.httpFail();

   /* if we're handling a GET or POST, we can output our data here.
    For a HEAD request, we just stop after outputting headers. */
    if (type== WebServer::HEAD)
    {
      return;
    }

    server.printP(Page_start);

    switch(type)
    {
      case WebServer::GET:
      {
        server.printP(Get_head);
        break;
      }
      case WebServer::POST:
      {
        server.printP(Post_head);
        break;
      }
      default:
      {
        server.printP(Unknown_head);
      }
    }
    server.printP(Default_head);
    server.print(url_tail);
    server.printP(Page_end);

}

void setup()
{
  Serial.begin(9600);
  Serial.println("Iniciado");

  /* initialize the Ethernet adapter */
  //Ethernet.begin(mac, ip, gateway, subnet);

  Serial.println("Trying to get an IP address using DHCP");
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // initialize the ethernet device not using DHCP:
    Ethernet.begin(mac, ip, gateway, subnet);
  }
  // print your local IP address:
  Serial.print("My IP address: ");
  ip = Ethernet.localIP();
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(ip[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println();

  /* setup our default command that will be run when the user accesses
  * the root page on the server */
  webserver.setDefaultCommand(&indexCmd);

  /* setup our default command that will be run when the user accesses
  * a page NOT on the server */
  //webserver.setFailureCommand(&failCmd);

  /* run the same command if you try to load /index.html, a common
  * default page name */
  webserver.addCommand("index.html", &indexCmd);

  webserver.addCommand("control.html", &controlCmd);

  /* start the webserver */
  webserver.begin();

  /*Indicamos que el PIN 2 será de salida
  * para nosotros es donde estará el cable de Luz */
  pinMode(2, OUTPUT);
}

void loop()
{
  char buff[64];
  int len = 64;

  /* process incoming connections one at a time forever */
  webserver.processConnection(buff, &len);
}

Una vez realizado todo ya podemos ponerle algo al enchufe y controlarlo mediante nuestro sencillo servidor web. Para que quedara todo más recogido, personalmente lo he metido en una caja cerrada donde solo saco los cables necesarios.

Circuito Cerrado
Video en funcionamiento: Video.

Espero que les haya gustado.

12 pensamientos en “Control domótico con Arduino

  1. Hola
    estoy usando este codigo y me funciona muy bien me podrias decir como hago para controlar mas luces osea añadirle para manejar 8 luces
    Gracias

    • Buenas Seitony, en el código solo utilizo el pin 2, para controlar más luces simplemente tendrías que tener dos placas de relés y conectarlos a 8 pines distintos de arduino. Tras esto modifica el código para añadir más checkboxes y más variables como el LED_Status_01 hasta el LED_Status_08 para poder controlar todos los pines.

      • Hola Admin
        gracias por tu respuesta,estoy intentando modificarlo haber si le puedo poner mas luces soy muy novato en esto te pongo un trozo de codigo haber si es asi porque al compilar me da muchos errores

        //Se mira la query para ver si se ha de activar o desactivar la linea
        String ProcesarCheckbox(String Estado)
        {
        LED_status = 0;
        if (Estado == «1»)
        {
        LED_status = true;
        }

        if (LED_status_01) { // switch LED on
        digitalWrite(3, HIGH);
        // checkbox is checked
        return «Apagar Luz»;
        }
        else { // switch LED off
        if (LED_status_02) { // switch LED on
        digitalWrite(5, HIGH);
        // checkbox is checked
        return «Apagar Luz»;
        }
        else { // switch LED off
        if (LED_status_03) { // switch LED on
        digitalWrite(6, HIGH);
        // checkbox is checked
        return «Apagar Luz»;
        }
        else { // switch LED off
        if (LED_status_04) { // switch LED on
        digitalWrite(7, HIGH);
        // checkbox is checked
        return «Apagar Luz»;
        }
        else { // switch LED off
        }
        }
        digitalWrite(3, LOW);
        // checkbox is unchecked
        return «Encender Luz»;
        }
        digitalWrite(5, LOW);
        // checkbox is unchecked
        return «Encender Luz»;
        }
        digitalWrite(6, LOW);
        // checkbox is unchecked
        return «Encender Luz»;
        }
        digitalWrite(7, LOW);
        // checkbox is unchecked
        return «Encender Luz»;
        }
        }

        • Buenas Seitony, en este proyecto no se guarda estado de la luz, por ese motivo si tú la enciendes y luego vuelves a la página principal se apaga ya que por defecto su estado es apagada por lo que para que puedas hacer lo que quieres necesitas que tu url sea la que guarde el estado por lo que quitaríamos el parámetro «Luz» y añadiremos «l1,l2,l3…l8».
          Entonces tendremos 8 líneas como:
          String l1= GetParam(«l1», server, type, url_tail, tail_complete)
          Y la funciona de los checkboxes será:

          String ProcesarCheckbox(String l1, String l2, .... ,String l8)
          {
          LED_status_01 = 0;
          if (l1 == “1”)
          {
          LED_status_01 = true;
          }

          if (LED_status_01) { // switch LED_01 on
          digitalWrite(2, HIGH);
          // checkbox is checked
          return "input type=\"checkbox\" name=\"l1\" value=\"1\" onclick=\"submit();\" checked>Apagar Interruptor 01";
          }
          else { // switch LED_01 off
          digitalWrite(2, LOW);
          // checkbox is unchecked
          return "input type=\"checkbox\" name=\"l1\" value=\"1\" onclick=\"submit();\">Encender Interruptor 01";
          }

          //Y así con las otras 7 luces
          .
          .
          .
          //
          }

          De esta forma tu Url será la que gestione cuales estarán encendidas y cuáles no, por ejemplo la URL para encender la 1 y la 4 tendría los siguientes parámetros:
          ?l1=1&l2=0&l3=0&l4=1&l5=0&l6=0&l7=0&l8=0

          • Hola de nuevo,perdona por las molestias.lo he puesto asi he añadido para 2 luces pero al compilar me sale este error
            exit status 1
            stray ‘\342’ in program

            lo he hecho de esta manera
            }
            //Se mira la query para ver si se ha de activar o desactivar la linea
            String l1= GetParam(“l1”, server, type, url_tail, tail_complete)
            String l2= GetParam(“l2”, server, type, url_tail, tail_complete)
            String l3= GetParam(“l3”, server, type, url_tail, tail_complete)
            String l4= GetParam(“l4”, server, type, url_tail, tail_complete)
            String l5= GetParam(“l5”, server, type, url_tail, tail_complete)
            String l6= GetParam(“l6”, server, type, url_tail, tail_complete)
            String l7= GetParam(“l7”, server, type, url_tail, tail_complete)
            String l8= GetParam(“l8”, server, type, url_tail, tail_complete)

            String ProcesarCheckbox(String l1)
            {
            LED_status_01 = 0;
            if (l1 == “1”)
            {
            LED_status_01 = true;
            {

            if (LED_status_01) { // switch LED_01 on
            digitalWrite(2, HIGH);
            // checkbox is checked
            return «input type=\»checkbox\» name=\»l1\» value=\»1\» onclick=\»submit();\» checked>Apagar Interruptor 01″;
            }
            else { // switch LED_01 off
            digitalWrite(2, LOW);
            // checkbox is unchecked
            return «input type=\»checkbox\» name=\»l1\» value=\»1\» onclick=\»submit();\»>Encender Interruptor 01″;
            }
            String ProcesarCheckbox(String l2)
            {
            LED_status_02 = 0;
            if (l2 == “1”
            {
            LED_status_02 = true;
            {

            if (LED_status_02) { // switch LED_02 on
            digitalWrite(3, HIGH);
            // checkbox is checked
            return «input type=\»checkbox\» name=\»l2\» value=\»1\» onclick=\»submit();\» checked>Apagar Interruptor 02″;
            }
            else { // switch LED_02 off
            digitalWrite(3, LOW);
            // checkbox is unchecked
            return «input type=\»checkbox\» name=\»l2\» value=\»1\» onclick=\»submit();\»>Encender Interruptor 02″;
            }

            }

            muchas gracias

          • Buenas, no puedes tener dos funciones con el mismo nombre y los mismos parámetros, por ese motivo te comentaba que la función de los checkbox debía ser:
            String ProcesarCheckbox(String l1, String l2)
            {
            LED_status_01 = 0;
            if (l1 == “1”)
            {
            LED_status_01 = true;
            {

            if (LED_status_01) { // switch LED_01 on
            digitalWrite(2, HIGH);
            // checkbox is checked
            return “input type=\”checkbox\” name=\”l1\” value=\”1\” onclick=\”submit();\” checked>Apagar Interruptor 01″;
            }
            else { // switch LED_01 off
            digitalWrite(2, LOW);
            // checkbox is unchecked
            return “input type=\”checkbox\” name=\”l1\” value=\”1\” onclick=\”submit();\”>Encender Interruptor 01″;

            LED_status_02 = 0;
            if (l2 == “1”
            {
            LED_status_02 = true;
            {

            if (LED_status_02) { // switch LED_02 on
            digitalWrite(3, HIGH);
            // checkbox is checked
            return “input type=\”checkbox\” name=\”l2\” value=\”1\” onclick=\”submit();\” checked>Apagar Interruptor 02″;
            }
            else { // switch LED_02 off
            digitalWrite(3, LOW);
            // checkbox is unchecked
            return “input type=\”checkbox\” name=\”l2\” value=\”1\” onclick=\”submit();\”>Encender Interruptor 02″;
            }

            }

            Además cuando lo pongas en tu código date cuenta que a los return le falta al símbolo < de apertura ya que por motivo de html se lo he tenido que quitar.

      • Bueno ya estoy otra vez por aqui,muchas gracias admin por la ayuda pero no hay manera,no me entero tendre que estudiar mas no he tenido mucho tiempo.
        yo creo que lo hago como me dices pero me sigue dando error al compilar:
        exit status 1
        stray ‘\342’ in program
        se me queda esta linea marcada
        return “Encender Interruptor 02″;

        ya no molesto mas te pego el trozo como lo he hecho y cuando puedas me dices donde tengo el fallo

        }
        String l1= GetParam(“l1”, server, type, url_tail, tail_complete)
        String l2= GetParam(“l2”, server, type, url_tail, tail_complete)

        //Se mira la query para ver si se ha de activar o desactivar la linea
        String ProcesarCheckbox(String l1, String l2)
        {
        LED_status_01 = 0;
        if (l1 == “1”)
        {
        LED_status_01 = true;
        {

        if (LED_status_01) { // switch LED_01 on
        digitalWrite(2, HIGH);
        // checkbox is checked
        return “Apagar Interruptor 01″;
        }
        else { // switch LED_01 off
        digitalWrite(2, LOW);
        // checkbox is unchecked
        return “Encender Interruptor 01″;

        LED_status_02 = 0;
        if (l2 == “1”
        {
        LED_status_02 = true;
        {

        if (LED_status_02) { // switch LED_02 on
        digitalWrite(3, HIGH);
        // checkbox is checked
        return “Apagar Interruptor 02″;
        }
        else { // switch LED_02 off
        digitalWrite(3, LOW);
        // checkbox is unchecked
        return “Encender Interruptor 02″;
        }
        }

        • perdon no se habia copiado bien el codigo

          }
          String l1= GetParam(“l1”, server, type, url_tail, tail_complete)
          String l2= GetParam(“l2”, server, type, url_tail, tail_complete)

          //Se mira la query para ver si se ha de activar o desactivar la linea
          String ProcesarCheckbox(String l1, String l2)
          {
          LED_status_01 = 0;
          if (l1 == “1”)
          {
          LED_status_01 = true;
          {

          if (LED_status_01) { // switch LED_01 on
          digitalWrite(2, HIGH);
          // checkbox is checked
          return “input type=\”checkbox\” name=\”l1\” value=\”1\” onclick=\”submit();\” checked>Apagar Interruptor 01″;
          }
          else { // switch LED_01 off
          digitalWrite(2, LOW);
          // checkbox is unchecked
          return “input type=\”checkbox\” name=\”l1\” value=\”1\” onclick=\”submit();\”>Encender Interruptor 01″;

          LED_status_02 = 0;
          if (l2 == “1”
          {
          LED_status_02 = true;
          {

          if (LED_status_02) { // switch LED_02 on
          digitalWrite(3, HIGH);
          // checkbox is checked
          return “input type=\”checkbox\” name=\”l2\” value=\”1\” onclick=\”submit();\” checked>Apagar Interruptor 02″;
          }
          else { // switch LED_02 off
          digitalWrite(3, LOW);
          // checkbox is unchecked
          return “input type=\”checkbox\” name=\”l2\” value=\”1\” onclick=\”submit();\”>Encender Interruptor 02″;
          }

          • Buenas, te he visto varios problemas en tú código. El primero es que no cierras los bloques de «if» por lo tanto no se puede compilar y por otro lado no cierras tampoco las condiciones, además de que te tienes que acordar de poner punto y coma siempre que acabes una instrucción «;», te adjunto tu sección de código corregida:
            String l1= GetParam(“l1”, server, type, url_tail, tail_complete);
            String l2= GetParam(“l2”, server, type, url_tail, tail_complete);

            String ProcesarCheckbox(String l1, String l2)
            {
            LED_status_01 = 0;
            if (l1 == «1»)
            {
            LED_status_01 = true;
            }

            if (LED_status_01) { // switch LED_01 on
            digitalWrite(2, HIGH);
            return «<input type=\»checkbox\» name=\»l1\» value=\»1\» onclick=\»submit();\» checked>Apagar Interruptor 01″;
            }
            else { // switch LED_01 off
            digitalWrite(2, LOW);
            return «<input type=\»checkbox\» name=\»l1\» value=\»1\» onclick=\»submit();\»>Encender Interruptor 01″;
            }

            LED_status_02 = 0;
            if (l2 == «1»)
            {
            LED_status_02 = true;
            }

            if (LED_status_02) { // switch LED_02 on
            digitalWrite(3, HIGH);
            return «<input type=\»checkbox\» name=\»l2\» value=\»1\» onclick=\»submit();\» checked>Apagar Interruptor 02″;
            }
            else { // switch LED_02 off
            digitalWrite(3, LOW);
            return «<input type=\»checkbox\» name=\»l2\» value=\»1\» onclick=\»submit();\»>Encender Interruptor 02″;
            }
            }

      • Gracias por la ayuda Admin
        me das tu mail y te envio el codigo entero haber donde esta el fallo?
        GRACIAS

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.