martes, 10 de noviembre de 2015

Calefacción solar de bajo coste. Empezando a programar el Arduino (IV). Modificando externamente el valor de una feed y leyéndola con Arduino.

Muy buenas, disculpad la tardanza entre artículos. Hoy quisiera explicar como he montado una función para poder leer el estado de una feed de emoncms.org. De esta manera podremos controlar el funcionamiento de la calefacción "solar", esto es, la bomba 2 junto al conjunto ventilador-radiador (sustituido este año por un split de aire acondicionado).

La función en cuestión es la siguiente:

int readSSS (void)
{
  sss_read= -1;
  char buffer [200];
  memset (buffer, 0, sizeof(buffer));

  // give a second to initialize:
  delay(1000);
  DEBUG1_PRINTLN("===============================================");
  DEBUG1_PRINTLN("Reading SSS...");
  delay(1000);

  // wait to see if a reply is available
  // if there's incoming data from the net connection.
  // send it out the serial port. This is for debugging
  // purposes only:
  int reintentos = 1;
  
  while (reintentos > 0)
  {
  boolean salir = false; 
  
  // if you get a connection, report back via serial:
  if (client.connect(server, 80))
  {
    DEBUG1_PRINTLN("Connected to server emoncms.org");
    DEBUG1_PRINTLN("Making an HTTP Request");

    client.print("GET /feed/value.json?apikey=");
    client.print(apikey);
    client.print("&id=32427");
    client.println(" HTTP/1.1");

    client.println("Host:emoncms.org");
    client.println("User-Agent: Arduino-ethernet");
    client.println("Connection: close");
    client.println();
    DEBUG1_PRINTLN("End of HTTP Request");
    reintentos--;
  }
  else 
  {
    // if you didn't get a connection to the server:
    DEBUG1_PRINTLN("Connection to server emoncms.org failed");
  }

  // Devuelve algo del tipo: "2"

  // if there are incoming bytes available
  // from the server, read them and print them:
  delay(1000);

  salir = false;
  while (salir == false)
  {
    if (client.available())
    {
      char c = client.read();
      DEBUG1_PRINT(c);

      buffer [strlen(buffer)]= c;
      if (c == '\n' )
      {
        DEBUG1_PRINT("[]");
        DEBUG1_PRINTLN(buffer);
        memset (buffer, 0, 200);
      }    
    }
    else
    {
      DEBUG_PRINTLN ("Client not available");
    }
    delay(1);
    // if the server's disconnected, stop the client:
    if (!client.connected())
    {
      DEBUG1_PRINTLN("* ");
      DEBUG1_PRINTLN(buffer+1);
      /* Mirar si buffer +1 es numérico (0-9)*/
      if ((buffer[1] > 47) && (buffer[1] < 58))
      {
        sss = atoi( buffer + 1 );
        sss_read = sss;
      }

      DEBUG1_PRINTLN("Disconnecting from server emoncms.org.");
      client.stop();
      DEBUG1_PRINTLN("Disconnected from server emoncms.org");
      salir=true;
    }
  }

  DEBUG1_PRINT("Value of sss:");
  DEBUG1_PRINTLN(sss);
  DEBUG1_PRINT("Value of sss_read:");
  DEBUG1_PRINTLN(sss_read);
  DEBUG1_PRINTLN("End of read SSS");
  DEBUG1_PRINTLN("===============================================");
  }
  return 0;
}


Lo que hace básicamente es conectarse al servidor y pedirle el valor de una feed. Cada feed tiene asignado un código que podemos ver en el modo administración de nuestro espacio en emoncms.org. En nuestro caso se le ha asignado el valor 32427.
Este valor lo asigna el sistema. De esta manera,  podemos, conociendo la apikey de escritura, alterar ese valor desde cualquier navegador, en cualquier lugar con conexión a Internet. Nuestro arduino leerá periódicamente ese valor y actuará en consecuencia. 

En el anterior artículo veíamos como crear una entrada de datos simplemente poniendo en un navegador algo como:

http://emoncms.org/input/post.json?json={Sensor0:7}&apikey=a134....

Bien, si en lugar de "Sensor0", ponemos "SetSystemStatus" (Set System Status, o asignar estado del sistema), crearemos otra entrada que deberemos convertir a Feed. Esta feed, será la que arduino deberá leer, con el identificador que nos asignen los chicos de emoncms.

Así que, podemos crear una página html que podremos llevar en nuestro móvil, y que al abrirla nos permita interactuar con nuestro arduino.

Yo he hecho una con tantos botones como modos de funcionamiento tiene mi sistema (5), y en cada botón le he asignado una función en javascript tal que:

Función Javascript del botón 0 (Parar):

function Button0_onclick() {
window.open ("http://emoncms.org/input/post.json?json={SetSystemStatus:0}&apikey=a134...")
}

HTML del botón 0:

"input id="Button0" nbsp="" onclick="return Button0_onclick()" style="background-color: darkred; border-bottom: black thin solid; border-left: black thin solid; border-right: black thin solid; border-top: black thin solid; color: white; font-family: Tahoma; font-weight: bold; height: 70px; width: 248px;" type="button" value="Stop/Parar" >"


Y así con cuatro botones más, uno para cada estado de manera que ha habido que incluir los siguientes valores en el código de arduino:

#define HEATING_STOP         0     // 0: Parar calefacción.
#define HEATING_START_LOW    1     // 1: Arrancar calefacción vel.baja.
#define HEATING_START_HIGH   2     // 2: Arrancar calefacción vel.alta.
#define HEATING_AUTO_LOW     3     // 3: Modo auto calefacción vel.baja
#define HEATING_AUTO         4     // 4: Modo auto calefacción.

junto a un par de variables donde se alamcenará el valor leído:

int sss = HEATING_AUTO_LOW;
int sss_read = -1;

Como hemos dicho, nuestra centralita leerá dicho valor periódicamente y actuará en consecuencia, haciendo esto de la siguiente manera en el bucle principal, en el "loop", tal que así:

void loop() 
{

  if (millis() - lastReadSSSTime > readingSSSinterval)
  {
    lastReadSSSTime = millis();
    readSSS();
  }
  (...) //Resto del programa (bucle) principal...
  
  

Con el artículo de hoy hemos visto como poder comunicarnos con Arduino. Hasta ahora, las funciones presentadas permitían que trabajase autónomamente.
Ahora ya podemos interactuar. ¿ Os atreveis ?
Hasta la próxima.