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.

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.

martes, 28 de abril de 2015

Calefacción solar de bajo coste. Empezando a programar el Arduino (I)


Muy buenas.

Ha llegado el día de desvelar el secreto mejor guardado de este proyecto... 

¡ el código del programa que se ejecuta en Arduino !

Como ya deberéis saber si habéis llegado hasta aquí, el lenguaje de programación que se utiliza para realizar programas en Arduino es el C.

Vamos a ir empezando desgranando las rutinas o funciones más importantes del mismo.

Cuando arranca el Arduino, cuando lo encendemos y se carga el programa en su memoria, lo primero que hace es ejecutar una función que forzosamente se ha de llamar "setup". En dicha función realizamos tareas de inicialización de variables que luego utilizaremos durante la ejecución del programa.

void setup() {
  delay(500);  
// allow some time (50 -250 ms) after powerup and sketch start, for the Wiznet W5100 Reset IC to release and come out of reset.
  // start serial port:
  Serial.begin(9600);

  pinMode(relayPin, OUTPUT);  
  pinMode(relayPinPump2, OUTPUT); 
  pinMode(relayPinFan, OUTPUT); 

  digitalWrite(relayPin, HIGH);  
  digitalWrite(relayPinPump2, HIGH);  
  digitalWrite(relayPinFan, HIGH);  

  pinMode(SS_SD_CARD, OUTPUT);
  pinMode(SS_ETHERNET, OUTPUT);
  digitalWrite(SS_SD_CARD, HIGH);   // SD Card not active
  digitalWrite(SS_ETHERNET, LOW);   // Ethernet active

  analogReference(DEFAULT);
  DEBUG_PRINT("Version 5.2 2014-12-04 21:00.\n");
  DEBUG_PRINTLN("Emoncms client starting...");
  // wait 1 second for initialization:
  delay(1000);
  if (!Ethernet.begin(mac)) 
  {
    // if DHCP fails, start with a hard-coded address:
    DEBUG_PRINTLN("Failed to get an IP address using DHCP, forcing manually");
    Ethernet.begin(mac, ip, dns, gw, subnet);
  }
  printStatus();
  delay(1000);

  int trys=0;
  while(!getNtpTime() && trys < 10) 
  {
    trys++;
  }
  if(trys<10)
  {
    ntpUpdated = true;
    DEBUG_PRINTLN("NTP server update success");  
    digitalClockDisplay();
  }
  else
  {
    ntpUpdated = false;
    DEBUG_PRINTLN("NTP server update failed");
  }

  readSSS();

  DEBUG_PRINT("Sensor0\t" );
  DEBUG_PRINT("Sensor1\t" );
  DEBUG_PRINT("Sensor2\t" );
  DEBUG_PRINT("Sensor3\t" );
  DEBUG_PRINT("Sensor4\t" );
  DEBUG_PRINT("Sensor5\t" );
  DEBUG_PRINT("Relay1\t" );
  DEBUG_PRINTLN("Relay2" );
  DEBUG_PRINTLN("End of setup");

}


Dichas tareas son, principalmente, las siguientes:
  1. Se inicializa el puerto serie de comunicaciones (para poder ver en el PC determinados mensajes a modo de traza).
  2. Se establecen determinados pines del Arduino en modo "salida", ya que van a actuar sobre elementos externos, fundamentalmente relés, aunque también sobre aquellos pines que interactúan comunicándose con la placa Ethernet que montamos sobre el Arduino.
  3. Tras poner la tensión de referencia analógica por defecto e imprimir un mensaje (esto es a lo que me refería antes con el puerto serie) que veríamos en el "monitor serial" si tuviésemos conectado el Arduino al PC, se espera un segundo para dar tiempo a que la placa ethernet se inicialice y después se arranca con la función "begin".
  4. Dejamos otro segundo para que todo vaya correctamente y llamamos a la función "getNtpTime" (que veremos más adelante), que lo que hace es intentar conectarse por internet a un servidor proveedor de hora y fecha. Establecemos 10 reintentos, y en una variable denominada "ntpUpdated", indicamos si lo hemos logrado (verdadero o falso).
  5. Se llama a la función ReadSSS, que lo que hace es leer (ya veremos como) un valor de una "feed" (ya vermos tambien que es) de emoncms.org, que nos dira el estado del sistema (Set System Status-> SSS).
  6. Tras esto, mandamos a consola una especie de cabecera, para ir anotando debajo las lecturas de los diferentes sensores posteriormente.

La función "getNtpTime" es la siguiente (hay muchos ejemplos en Internet). No voy a entrar en detalle sobre esta función, que se apoya en otra más llamada "sendNTPpacket". Simplemente funciona y ya está...
También pongo el código de la función "digitalClockDisplay" que manda al monitor Serial el valor de hora y fecha leído.

unsigned long getNtpTime()
{

  Udp.begin(localPort);
  sendNTPpacket(timeServer); // send an NTP packet to a time server

    // wait to see if a reply is available
  delay(1000);
  if ( Udp.parsePacket() ) {
    // We've received a packet, read the data from it
    Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);

    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord &lt;&lt; 16 | lowWord;
    DEBUG_PRINT("Seconds since Jan 1 1900 = " );
    DEBUG_PRINTLN(secsSince1900);              

    // now convert NTP time into everyday time:
    DEBUG_PRINT("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;    
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;
    // print Unix time:
    DEBUG_PRINTLN(epoch);                              

    // print the hour, minute and second:
    DEBUG_PRINT("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    DEBUG_PRINT((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)

    epoch += timeZoneOffset; // Adding seconds for local time

    DEBUG_PRINT(':');
    if ( ((epoch % 3600) / 60) &lt; 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      DEBUG_PRINT('0');
    }
    DEBUG_PRINT((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    DEBUG_PRINT(':');
    if ( (epoch % 60) &lt; 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      DEBUG_PRINT('0');
    }
    DEBUG_PRINTLN(epoch %60); // print the second

    //setTime((epoch  % 86400L) / 3600,(epoch % 3600) / 60,epoch % 60,28,1,2014);
    ///////////////////////////////////////////////////////////
    // Quitar anterior setTime y dejar este:
    // (de: http://www.openreefs.com/ntpServer )
    unsigned long epoch2;
    epoch2 = highWord &lt;&lt; 16 | lowWord;
    epoch2 = epoch2 - 2208988800 + timeZoneOffset;
    setTime(epoch2);
    ///////////////////////////////////////////////////////////


    Udp.stop();
    return OK;
  }
  else
  {
    DEBUG_PRINTLN("ERROR: No NTP packet received");
    return KO;
  }
}

unsigned long sendNTPpacket(IPAddress&amp; address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay &amp; Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:     
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket();
}

void digitalClockDisplay(){
  // digital clock display of the time
  DEBUG_PRINT(hour());
  printDigits(minute());
  printDigits(second());
  DEBUG_PRINT(" ");
  DEBUG_PRINT(day());
  DEBUG_PRINT(" ");
  DEBUG_PRINT(month());
  DEBUG_PRINT(" ");
  DEBUG_PRINT(year());
  DEBUG_PRINTLN();
}


¡¡¡ Ala, a practicar !!!

Con esto ya se puede hacer un programita sencillo que se conecte a Internet para leer la hora, pero no os lo voy a dar todo hecho...

martes, 24 de marzo de 2015

Calefacción solar de bajo coste. La electrónica.

¡ Muy buenas !

Hoy quisiera presentaros por fin el tema relacionado con el Arduino y la electrónica de mi sistema de calefacción solar: la centralita.



En primer lugar os presento el esquema, donde se puede ver principalmente el conjunto de la placa de Arduino unida a la Ethernet, junto los sensores de temperatura y los relés.

La placa de Arduino monta sobre ella otra placa, denominada Ethernet Shield, que sirve para poder conectarse a una red, bien sea local o a Internet mismo. Desde el momento en que esto es así, el conjunto pasa a formar parte del concepto IOT (Internet of Things, o traducido al español, Internet de las Cosas)
Resultado de imagen de arduino uno ethernet
De esta parte nos vamos a olvidar de momento, ya que volveremos a ella más tarde.

Como digo, la placa es una Arduino Uno, la más popular de todas. Va provista de 6 entradas analógicas (A0-A5). Idóneas para leer los datos proporcionados por 6 sensores de temperatura tipo MCP9700A. En la siguiente foto, el esquema del conjunto tal y como está a la fecha de publicación de este artículo.



Estos sensores están distribuidos de la siguiente manera:

Sensor 0: Colocado en uno de los colectores.
Sensor 1: En teoría iba a ser colocado en otro de los colectores, pero se utiliza de pruebas, como por ejemplo ver a que temperatura sale el agua del intercambiador y comprobar su eficacia, o la de retorno. La mayor parte del tiempo me indica la temperatura del sótano donde se encuentra el depósito.
Sensor 2: Situado en el exterior, en una caja de conexiones, protegido del sol y aislado mediante porexpán en una especie de garita meteorológica.


Como se ve, tiene los capuchones de los orificios recortados a la mitad, lo que permite que pase el aire, y cuando lo coloquemos en su emplazamiento definitivo, protegerá al sensor de la entrada de agua por lluvia.


Es un sistema sencillo y barato. La idea no es mía, creo que había algo parecido en el foro de aficionados a la meteorología "meteoclimatic".



Sensor 3: Nos indica la temperatura de la parte superior del depósito. El sensor va en el interior de un tubo de cobre de 22 mm de diámetro para que no se moje. Se vió en el anterior artículo publicado.
Sensor 4: Igual que el sensor 4, pero nos indica la temperatura de la parte inferior del depósito.
Sensor 5: Está ubicado en el salón de la casa.



Por otro lado, utilizamos tres salidas digitales de dicha placa Arduino, con la que activamos o desactivamos otros tantos relés, que controlan el funcionamiento de bombas y ventiladores.

La salida digital D3 es la que activa el relé de la bomba de colectores. Esta es la bomba que impulsa el agua desde el depósito hacia los colectores para que se caliente. Cuando el relé es activado, puentea el camino que deja pasar la corriente hacia la bomba, que trabaja a 220V AC y ésta impulsa el agua hacia los colectores.

La salida digital D5 activa el relé de la bomba de calefacción, esto es, la del circuito presurizado que llega al radiador que hay en el falso techo del baño. Cuando se activa este relé, ocurre lo mismo que hemos explicado anteriormente y el agua llega desde el sótano hasta la primera planta. Esta bomba también funciona a 220V AC.

Pero si sobre el radiador, que es un intercambiador de calor agua-aire, no actuamos con un ventilador, su rendimiento es prácticamente nulo. Por eso utilizamos la salida digital D7 para arrancar un ventilador de conducto de aire que hará pasar éste por el radiador y lo calentará. Como dicho ventilador tiene dos velocidades,utilizamos las dos posiciones del relé para seleccionar la velocidad baja o la alta. En la siguientes fotos se adjunta la información que el fabricante del ventilador aporta en el propio aparato.




Por último, hay que señalar que la placa arduino va alimentada con un transformador de 2 A. Los relés, por otra parte, llevan otro transformador para alimentarlos. El negativo de ambos transformadores va en común, y todo ello en una caja de plástico de las usadas en electrónica.

Respecto a los sensores de temperatura, como llevan tres cables (Vcc, Gnd y Salida), he empleado conectores miniDIN de 3 contactos. Desde el sótano hasta el exterior y a la casa llego a ellos con cable de portero automático de 7 hilos. En la siguiente foto se ven las bases soldadas a una placa de circuito impreso, la cual a su vez está pegada con cola termofusible a la base de la caja.


Los sensores no llevan resistencias, ni condensadores de filtrado. Van directamente a las entradas del Arduino. Al principio usaba dichos condensadores y resistencias de filtrado soldados en las patillas de los mismos, pero ocurría que se me estropeaban muy a menudo, falseando medidas y haciendo malfuncionar el sistema. Achaco esto a que los sensores de temperatura están preparados para aguantar temperaturas superiores a 100ºC, pero los condensadores y resistencias no... Esto provocaba que se deteriorasen y produjesen cortos o variaciones sustanciales en su comportamiento.

Como digo, sencillamente se sueldan los cables y luego se protegen con tubo termorretráctil y si acaso, un poco de cinta aislante. No he vuelto a tener problemas.

Los conectores de las bombas y ventiladores, como van a 220V, son de los utilizados en aparatos como ordenadores, etc.,de tipo hembra para evitar que al manipular la caja nos podamos electrocutar.



En esta foto se puede apreciar el inicio de la colocación de los diversos componentes comentados: placa Arduino con Shield Ethernet, Placa de un solo relé y fuente de alimentación. Con esto se iniciaron las pruebas para mover la bomba de colectores.Luego se instalaron los otros dos placas de relés, sujetándolas con cinta de doble cara.


Tras realizar todas las perforaciones necesarias para las entradas y salidas de la placa Arduino, colocar todos los conectores, etc podemos ver la caja montada con todos los componentes comentados en su interior, sobre el armazón que envuelve el depósito de agua.


Por último, comentar que está previsto todavía monitorizar otro sensor más, en este caso a través de una entrada digital sencilla, que nos informará de cuando hay que rellenar el depósito (a través de un interruptor de flotador) por pérdidas de evaporación, fugas o similares.

También utilizaremos unas cuantas entradas/salidas digitales de las numerosas que quedan libres, para controlar el estado de la calefacción, saber si la caldera está en marcha o activarla/apagarla incluso saltándonos el cronotermotasto de la casa, todo remotamente por Internet, desde el móvil o un PC y con el mismo Arduino y un par de relés más. Pero eso lo añadiremos más adelante.

Las posibilidades de este pequeño invento son infinitas, como se ve.
Nos vemos. Saludos.