viernes, 22 de mayo de 2015

Calefacción solar de bajo coste. Empezando a programar el Arduino (III). Enviando datos a Emoncms

Hoy empezamos este artículo con el tema de enviar los datos leídos por los sensores a la web de Emoncms.org, donde quedarán almacenados para poder verlos en tiempo-real o mediante gráficas digamos... "históricas".

Primero veamos qué es Emoncms. Como en su propia página web indican (www.emoncms.org), es una aplicación basada en web para el procesado, apunte y visualización de datos relativos a energía. Está principalmente enfocado a la energía de tipo fotovoltaico, pero incluye algunas características de monitorización para tipo de energía térmica.

Podemos instalar la aplicación en una rapsberry Pi y tener nuestro servidor propio en nuestra casa, o bien probar a  almacenar los datos en los servidores de emoncms. Empezaremos con esto último...


Lo primero que tenemos que hacer es solicitar el alta, escogiendo un usuario y una contraseña de acceso. Y en principio es así de sencillo. Apenas hace falta más. Ya podemos empezar a enviar datos que serán almacenados y que podremos visualizar. En cuanto se nos haya dado de alta se nos asignarán unas claves denominadas "APIs key". En la siguiente foto aparecen difuminadas (ahora veremos por qué) , las he enfatizado en color amarillo.


Las API key son dos claves de un porrón de números y letras. Una API key es de lectura y otra de escritura, y van a permitir leer o actualizar, respectivamente, un valor determinado de una variable de un determinado usuario. La forma de enviar un valor determinado para una variable es de la siguiente forma:

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

Siiiiiiii, se puede hacer desde un explorador, por ejemplo... 

Esto nos va a crear una entrada (en la web lo llama "input", ver recuadro señalado en amarillo en la siguiente foto), con el último valor asignado a esa variable. Si lo repetimos con distintos valores para la variable (Sensor1, Sensor2, Sensor3, etc...) obtenemos una fila nueva por cada una.

Si la variable no existía, la crea automáticamente, y si existía, la actualiza, indicando cuando fué la última vez que se actualizó. En la siguiente foto se pueden apreciar las distintas "inputs" o entradas que tengo definidas, iremos viendo que es cada una.


Como vemos, con un sencillo explorador como el Chrome, Firefox, etc, podemos crear una entrada en nuestro espacio personal de monitorización de Emoncms. Aquí radica la importancia de tener cuidado con la API key de escritura, ya que malintencionadamente, cualquier otra persona que la sepa puede alterarnos el valor de una variable, crearnos nuevas variables innecesarias, etc. Deberemos tener cuidado con ello.

Bien... ya tenemos una entrada, podemos ver el estado de la misma y actualizarla, pero... ¿ cómo almacenamos los cambios de la misma a lo largo del tiempo ? La respuesta está en lo que en emoncms llaman "feeds". El verbo "To feed" en inglés puede traducirse como "alimentar", y eso es lo que es una feed en emoncms ( y en otros ámbitos de la informática) : un grifo, canal o fuente de datos. Si nos fijamos en la anterior foto, algunas de las "inputs" tienen una indicación en la columna "Process list", denominada "log". Otras no tienen nada. Y que significa esto ? Las que tienen el indicador "log", es porque se convierten en "feed's", es decir, se almacenan los datos a medida que van llegando. 

¿Como se hace esto ? Fijaros en la pequeña llave inglesa que hay al final de cada línea... al pinchar con el puntero del ratón sobre la misma se nos abre otra ventana que nos pregunta que acción realizar sobre esa entrada. 


Al añadir proceso ( Add process), seleccionaremos "Log to feed" (se puede traducir como "salvar en feed" ). Crearemos una nueva feed a la que daremos un nombre y seleccionaremos uno de los 3 valores posibles de almacenamiento (feed engine). Al principio de usar emoncms yo usaba el "Variable Interval no Averaging" y me va bien, con un intervalo de 10 segundos. Esto significa que cada 10 segundos lee la entrada (input) para ver si hay datos nuevos.

Por último le damos a "Add" (Añadir) y ya tenemos nuestra feed, lista para ser visualizada gráficamente.

A continuación, añado la función que uso con mi arduino para envíar los datos cada cierto tiempo a emoncms.org. Como ya he comentado, oculto aquí la clave pública de escritura, que tendréis que sustituir por la vuestra. Se puede intuir que es como si el arduino escribiese la dirección que más arriba os enseñé para poner en un explorador, pero a más bajo nivel, y enviando más datos, uno por cada sensor, así como valores de control que se usarán para encender/apagar el ventilador.
Hasta otra semana.

int pumpWorking = OFF;                         // Flag to indicate pump 1 status
int pumpWorking2 = OFF;                        // Flag to indicate pump 2 status
int highSpeedFan = OFF;                        // Flag to indicate heating fan speed
float selectedTemp = 0;                        // To indicate home selected temperature

float TempInCelciusf[] = {
  0,0,0,0,0,0};        // Calculated temperature in Celcius

//api key
char apikey[] = "a1340..........................";
int node = 0;                                  //if 0, not used

void sendData() 
{
  DEBUG_PRINTLN("Connecting...");
  // if there's a successful connection:
  if (client.connect(server, 80)) 
  {
    // send the HTTP GET request:
    int newFree = client.free();

    node =0;
    client.print("GET /api/post?apikey=");
    client.print(apikey);
    if (node > 0) {
      client.print("&node=");
      client.print(node);
    }
    client.print("&json={Sensor0");
    client.print(":");
    client.print(TempInCelciusf[COLECTOR1]);
    client.print(",Sensor1:");
    client.print(TempInCelciusf[COLECTOR4]);
    client.print(",Sensor2:");
    client.print(TempInCelciusf[EXTERIOR]);
    client.print(",Sensor3:");
    client.print(TempInCelciusf[TANQUESUP]);
    client.print(",Sensor4:");
    client.print(TempInCelciusf[TANQUEINF]);
    client.print(",Sensor5:");
    client.print(TempInCelciusf[CASA]);
    client.print(",Bomba:");
    client.print(pumpWorking);
    client.print(",Bomba2:");
    client.print(pumpWorking2 + highSpeedFan);
    client.print(",Temperatura:");
    client.print(selectedTemp);
    client.print(",SSS_actual:"); // Valor con el que está trabajando actualmente.
    client.print(sss);   
    client.print(",SSS_leido:"); // Último valor leido para sss. (-1: error, no ha podido leerlo)
    client.print(sss_read);

    client.println("} HTTP/1.1");

    client.println("Host:emoncms.org");
    DEBUG_PRINTLN("Host:emoncms.org");
    client.println("User-Agent: Arduino-ethernet");
    DEBUG_PRINTLN("User-Agent: Arduino-ethernet");
    client.println("Connection: close");
    DEBUG_PRINTLN("Connection: close");
    client.println();
    DEBUG_PRINTLN("*********************************");

    // note the time that the connection was made:
    lastConnectionTime = millis();      
    //}
  }
  else 
  {
    // if you couldn't make a connection:
    DEBUG_PRINTLN("Connection failed");
    DEBUG_PRINTLN("Disconnecting...");
    client.stop();
  }
}



viernes, 15 de mayo de 2015

Calefacción solar de bajo coste. Empezando a programar el Arduino (II). Leyendo los sensores.

Hoy vamos a ver cómo realizar las lecturas de los sensores de temperatura.

La lectura de los sensores la realiza la función denominada "read_sensors()" que os muestro a continuación. Como parámetro de entrada admite el número de veces que se va a realizar la lectura. Yo suelo leer cada sensor 2000 veces y hago la media.

Como hay 6 sensores, tiene un bucle con ese valor que a su vez ejecutará otros dos bucles: uno que realiza 10 lecturas que se desechan para estabilizar la adaptación de impedancias entre los sensores y el conversor AD (Analógico-Digital) del procesador del Arduino, y otro bucle que realiza la lectura de cada sensor tantas veces como le hayamos indicado en el parámetro de entrada.

Estas lecturas se van sumando para después realizar una media. Se podría además desechar el mayor y el menor valor de las lecturas, para eliminar picos, pero en mi caso parece que los datos salen muy pero que muy aceptables.

La fórmula que se aplica para convertir el valor en voltios del sensor a un valor digital es la proporcionada por el fabricante de los sensores MCP9700.



void read_sensors (int n) {   // n= number of readings.   // It takes about 100 microseconds (0.0001 s) to read an analog input,   // so the maximum reading rate is about 10,000 times a second.   float lectura;   DEBUG_PRINT("Reading sensors...");   // Calculate Temperature in Celcius   // Ltemp1=((analogRead(Ptemp1)*5000.0)/1024.0-500.0)/10.0;   // Previous analogRead and delay to stabilize reading (not sure)   for (int j = 0; j < 6; j++)   {      for (int k = 0; k < 10; k++)      {       //dummy reads for stabilization       analogRead(j);       delay(10);      }     lectura=0;     for (int i = 0; i < n; i++)     {       lectura = (((analogRead(j)*5000.0)/1024.0)-500.0)/10.0;       TempInCelciusf[j] += lectura;       delay(1);     }     TempInCelciusf[j] = TempInCelciusf[j]/n;   }   DEBUG_PRINTLN("Ok");   //Total delay (n=6): 6*(1000 +10+1) = 6066 msec = 6,06 sec }
Venga, os animo a hacer alguna prueba y que me comenteis...
Hasta la próxima.