domingo, 24 de julio de 2016

Tercera fase. Sistema SCADA para instalación de calefacción y ACS con RaspberryPi y Arduino MEGA



En el presente proyecto se trata el diseño de un sistema integrado de gestión y control, sistema SCADA (Supervisión, Control y Adquisición de Datos) de una instalación típica para Agua Caliente Sanitaria (ACS) y calefacción de una vivienda unifamiliar.

Tercera fase:

Implementación de un servidor web que permitirá supervisar, parametrizar y analizar toda la instalación desde cualquier punto con acceso a Internet, convirtiendo todo el proyecto en un modesto pero eficiente sistema SCADA (Supervisión, Control y Adquisición de Datos).
Para ello se utilizará una RaspberryPi, en la que se instalará un servidor LAMP (Linux, Apache2, MySql, PhP) conectada a la placa Arduino MEGA 2560 a través del puerto serie.
Video demostrativo del funcionamiento.

TERCERA FASE

Configuración de la RaspberryPi.

El servidor LAMP incluye los siguientes paquetes:
Servidor WEB Apache2.
Base de Datos MySQL.
Intérprete del lenguaje PHP.

Instalación de LAMP ( Linux, Apache2, MySQL, PHP):

La configuración e instalación de nuevos paquetes en Linux es un tarea que escapa a este proyecto. Existen cientos de blogs y páginas que tratan el asunto con mucho rigor y acierto.
No obstante a continuación se detallan los pasos para poner en funcionamiento el servidor LAMP en nuestra raspberryPi.



Base de Datos MySQL:

A continuación se detallan la forma de crear una base de datos y como importarla.

Vista de la tabla "yun_arduino_yun"




Archivos de Control de la aplicación:

Para la gestión y control de la aplicación se han creado una serie de programas y scripts que nos permiten la comunicación raspberryPi  <=> Arduino, la parametrización del Arduino, la gestión de la BBDD y la captura de datos del Arduino entre otras cosas.
A continuación se detallan los distintos archivos de control.

Programador de tareas periódicas,  "Crontab"

El programador de tareas de Linux Crontab nos facilita la manera de llamar a los distintos programas de control del servidor y es en síntesis el motor del flujo de los archivos de Control de la aplicación.
Las tareas  solicitadas en el mismo son las siguientes:
Cada minuto, cada día de la semana se busca si está en ejecución el programa "raspduinoRecibir.py" y se elimina el proceso en curso.
Cada minuto, cada día de la semana se busca si está en ejecución el script "iniciaLecturaDeArduino" y se elimina el proceso en curso.
Cada minuto, cada día de la semana se ejecuta el script "guardaHoraSistema.sh".
Cada minuto, cada día de la semana se ejecuta el script "iniciaLecturaDeArduino".



guardaHoraSistema.sh


El siguiente script tiene varias instrucciones de importancia.
En primer lugar guarda la hora del servidor ( la raspberryPi ) en la BBDD de la caldera "DatosDeCaldera".

En segundo lugar llama al programa python "raspduinoModificar.py" y le envía como parámetros la hora y minuto del servidor. El programa "raspduinoModificar.py" permite a través del puerto serie,  el envío en un formato predeterminado de los nuevos valores para los parámetros de funcionamiento del Arduino.

En tercer lugar llama al programa "raspduinoParametrizar.py", el cual gestiona la actualización de los parámetros de funcionamiento del Arduino, comparándolos con los introducidos en la BBDD por el usuario de la instalación.

En cuarto lugar, llama al programa "raspduinoVerificaComunicacion.py", encargado de comprobar el correcto funcionamiento de la comunicaciones de nuestro servidor con el Arduino y el acceso a Internet.








raspduinoModificar.py

El programa python "raspduinoModificar.py" confecciona un mensaje de escritura incluyendo los argumentos recibidos.
Estos argumentos corresponden al nombre del parámetro el primero, y el valor del mismo el segundo.
Una vez confeccionado el mensaje lo envía al Arduino  a través del puerto serie.




raspduinoParametrizar.py

El programa python "raspduinoParametrizar.py"  modifica los parámetros de funcionamiento de la instalación.
Para ello comprueba las columnas "valor" y "eepromSimulada" de la tabla "yun_arduino_yun"  en las filas donde los parámetros de la columna "nombre" coincide con los incluidos en el array -params-.
Si el resultado de la comparación es falso, se confecciona un mensaje preformateado y se envía al Arduino el  nuevo valor del parámetro  a través del puerto serie para la modificación del mismo.
De esta manera conseguimos hacer de nuestra BBDD en la raspberryPi una emulación del funcionamiento de una memoria EEPROM, ( de ahí el nombre de la columna "eepromSimulada" en la BBDD).
Además,  en caso de corte de alimentación o reinicio de la instalación,  nos permite recuperar la completa configuración de los parámetros de funcionamiento modificados por el usuario, en lugar de usar los de defecto sin necesidad de volverlos a introducir.
Se ha optado por esta solución debido a que las necesidades de nuestra aplicación requería una cantidad considerable de escrituras-lecturas de la EEPROM del propio Arduino lo cual, sin duda habría puesto a prueba la duración de la vida útil del Arduino.
 


raspduinoVerificaComunicacion.py

El programa python "raspduinoVerificaComunicacion.py" comprueba la correcta comunicación del servidor con el Arduino y con la red (Internet).
En caso de fallos continuados de comunicación reinicia los equipos cortándoles la alimentación mediante la activación de sendos relés.

Listado del programa :


iniciaLecturaDeArduino

Prepara al Arduino para lectura a través del programa "raspduinoRecibir.py" si es que no existe ya una instancia en proceso, en cuyo caso deja que termine el mimo.


raspduinoRecibir.py

El programa python "raspduinoRecibir.py" lee los parámetros de estado de los equipos y los valores de las  variables enviados por el Arduino a través del puerto USB de la raspberryPi.
Si el mensaje recibido tiene un formato coherente, lo valida y lo guarda  en  la BBDD "DatosDeCaldera".

Listado programa :

Archivos del servidor  HTML y PHP.

Pantallas de presentación de los archivos principales de la aplicación:


index.html:





calderaTelegestionCaldera.php:




calderaLeerCurva.php










calderaParametrizacion.php











calderaFalloEnvio.php






Conjunto de la aplicación al completo:



Solicitar aquí  información del proyecto :


softmpr@gmail.com


Descarga Parcial del proyecto


Ver video demo en Youtube








Segunda Fase. Sistema SCADA para instalación de calefacción y ACS con RaspberryPi y Arduino MEGA

En el presente proyecto se trata el diseño de un sistema integrado de gestión y control, sistema SCADA (Supervisión, Control y Adquisición de Datos) de una instalación típica para Agua Caliente Sanitaria (ACS) y calefacción de una vivienda unifamiliar.

Segunda fase:

Diseño e implementación de un sistema completo de control y gestión de la instalación basado en un microcontrolador de la plataforma Arduino, en concreto el Arduino Mega.
El sistema dispondrá de entradas y salidas digitales para la gestión de los equipos tales como bombas, quemador, termostatos, pulsadores, etc.
Incorporación de tres sondas para la captura de temperatura de impulsión del agua de la caldera, temperatura de ACS y temperatura exterior.
Incorporación de una pantalla LCD que servirá para informar de los estados de los equipos, valores de sondas de temperatura y otros valores relevantes de la instalación.
Implementación de un control de la temperatura de impulsión del agua de caldera para los radiadores, en función de la temperatura exterior, (curva de compensación).

Hardware.
Listado de componentes utilizados.
Descripción de los componentes.
Esquema eléctrico.

Software.
Descripción del programa.
Descripción de las funciones principales.
Test de la aplicación.

SEGUNDA FASE 

HARDWARE.

Listados de componentes principales.

La aplicación cuenta con  los siguientes componentes  principales:
1 Microcontrolador Arduino MEGA 2560 R3.
1 Placa de prototipos.
1 Pantalla LCD de 16 columnas  x  2  filas.
1 modulo de salida relés de 4 canales.
3 Sensores de temperatura DS18B20.
1 Fuente de alimentación de  1 A 5 V.c.c.
 


Otros componentes y accesorios:

Cables de conexionado.
Potenciómetro. 1K5
Resistencia. 15 K


DESCRIPCIÓN DE LOS COMPONENTES:

 Arduino MEGA 2560 R3:



La elección de este placa obedece al hecho de que supera a la mayoría de las placas en lo que se refiere a entradas/salidas, puertos de comunicación y memoria disponibles.




Comparativa de placas Arduino.

En la siguiente captura se pueden comprobar las características más importantes del Arduino MEGA.
 

  

 Asignación de pins de la placa Arduino MEGA 2560 (pinOUT)




Placa de prototipos :

 

 
La placa de prototipos ElecFreaks permita una rápida implementación de los proyectos, gracias a su interfaz física coincidente con el pinout de la mayoría de placas Arduino, incluyendo la MEGA 2560.






Pantalla de cristal líquido de 16  x 2 caracteres:

 




Pantalla de cristal líquido  alfanumérica .







 
 Asignación de pins del LCD:


 
 






















Conexionado típico del LCD 16x2:



 



Módulo de cuatro salidas a relé:

 





Módulo de salida para cuatro relés alimentados a 5Vcc, con indicador de estado de cada canal.









 Sensor de temperatura DS18B20:




Sensor de temperatura envainado estanco basado en el microcontrolador DALLAS DS 1820. Su principal característica es que se comunica por un único pin, haciéndolo ideal para proyectos basados en microcontroladores.






 Asignación de pins del sensor DS18B20:

 
El sensor DS1820 tiene un patillaje realmente sencillo, no obstante para su conexión con el Arduino precisa de una resistencia de 4,7 K conectada entre el pin de datos  DQ y el pin de alimentación VDD.

ESQUEMAS ELÉCTRICOS: 

 Interconexionado del Arduino Mega con el resto de componentes de la aplicación:


Circuito completo del Arduino MEGA y el resto de equipos y accesorios:



  Circuito ensamblado en caja estanca:


Esquema eléctrico de caldera modificado:

 

SOFTWARE: 

 

Para la  confección el programa del microcontrolador se ha utilizado el IDE de Arduino.

Para la confección de la librería "TratamientoDeLaEEPROM.h" se ha utiizado el editor de texto Notepad.


El siguiente programa para microcontrolador Arduino MEGA 2560 R3, es parte de un proyecto 
para controlar y gestionar la producción de calor para el suministro de
agua caliente sanitaria ( ACS ) y  calefacción en una instalación doméstica típica.
El proyecto completo ( software y hardware ) incluye un servidor LAMP (Linux, Apache,
MySQL, PHP presentado en la Tercera Fase del proyecto) permite controlar y gestionar el
funcionamiento total de la instalación mediante una conexión a Internet.
El diagrama de flujo implementado en el presente programa, es el mismo que el utilizado en el
funcionamiento mediante accesorios convencionales presentado en la primera entrega  Primera
Fase del proyecto.
En esa fase se explica con detalle el funcionamiento, por lo cual se recomienda su lectura para
facilitar la comprensión del funcionamiento de este programa.
Para la gestión de la temperatura del de agua de la caldera hacia los radiadores,
se ha implementado una curva de compensación, que permite modificar la temperatura
automáticamente con dependencia de la temperatura exterior.
La gestión de las alarmas y protecciones de seguridad típicas de cualquier caldera,
siguen delegándose en los equipos convencionales tales como centralitas de encendido,
termostatos de seguridad, detectores de humos, etc., que siguen perfectamente habilitados.

Aunque el proyecto es absolutamente operativo, NO SE ACONSEJA SU IMPLEMENTACIÓN
EN UNA INSTALACIÓN REAL, pues la implementación requiere profundos conocimientos
para la manipulación de la caldera, en concreto su cableado eléctrico. Un error en la
manipulación del cableado eléctrico de la caldera puede derivar en graves accidentes además de
 un funcionamiento inestable de instalación.
En cualquier el caso, el objeto de la presentación de este proyecto es de carácter lúdico, no constructivo, por ello la responsabilidad que pudiera derivarse de la implementación total o
parcial de este proyecto, recaerá en quien la ejecuta o lleva a la práctica, en ningún caso sobre quien la divulga o presenta.
No obstante, si su intención es continuar implementando el proyecto, puede hacerlo utilizando
como fuente de calor, un simple radiador eléctrico, por ejemplo, sin necesidad de modificar
nada del mismo.


Listado del programa "calderaSL.ino" 

 /* Inclusión de las librerías del programa*/
#include <OneWire.h> // Lectura de varias sondas DS1820 por un único pin
#include <DallasTemperature.h> // Control de sondas DS1820
#include <LiquidCrystal.h> // Conttol del LCD
#include <TratamientoDeLaEEPROM.h> // Control de los parámetros de la aplicación
#include <avr/wdt.h> // Control de la continuidad del programa

int VISUALIZACIONES[] = {
    VER_CONSIGNA, VER_TEMP_IMPULSION, VER_TEMP_EXTERIOR, VER_TEMP_ACS, VER_HORARIO_ACS, VER_HORARIO_CALEFACCION };
// Constantes para la identificación
// de los distintos sensores de Temperatura
#define GUARDA_VALOR (A,B) (B=VISUALIZACIONES[A])
//Se establece el pin 4 como bus para la comunicación OneWire
OneWire pinDeEntrada ( PIN_ENTRADA_SONDAS ) ;
//Instancia la librería DallasTemperature
DallasTemperature SONDAS ( &pinDeEntrada ) ;

// Configuración de la los pins a utilizar por el
// display de cristal liquido
LiquidCrystal lcd ( 7, 8, 9, 10, 11, 12 ) ;

// contadores "retardos"
int contadorRetardoDelQuemador = 0;
int contadorDeBucles = 1;
int punteroDeParams=18;
int contadorEstadoArduino=0;
// variables de uso global

// Variables para almacenamiento de las
// lecturas de las sondas

float TempImpulsion;
float TempExterior;
float TempACS;
DeviceAddress direccionImpulsion, direccionAcs, direccionExterior;

// Valores por defecto de los parámetros de funcionamiento de la instalación
// Importación y exportación a base de datos

int puntoDeOrigenDeImpulsionEnCurvaDeCompensacion = 45;
int puntoLimiteDeImpulsionEnCurvaDeCompensacion = 65;
int puntoOrignDeTemperaturaExteriorEnCurvaDeCompensacion = 20;
int puntoLimiteDeTemperaturaExteriorEnCurvaDeCompensacion = 1;
int consignaDeRadiadores = 60;
int consignaDeConsumoDeAcs = 43;
int consignaDeRadiadoresManual = 60;
int consignaMinimaPrimarioDeAcs = 55;
int consignaMaximaPrimarioDeAcs = 75;
int consignaManualDeRadiadoresHabilitada = 0;
int ciclosDeRetardoDelQuemador = 8;
int horaDeEncendidoDeAcs = 6;
int horaDeApagadoDeAcs = 23;
int horaDeEncendidoDeCalefaccion = 7;
int horaDeApagadoDeCalefaccion = 23;
int horaDelSistema = 9;
int minutoDelSistema = 15;
int horaDelArduino = 10;
int minutoDelArduino = 25;

int valorActual=1;
int ultimoValor =2;
int penultimoValor =3;
int fallos =0;

int raspDisponible = 33+89;
struct parametro{
String nombre="nombre";
String valor="valor";
int destino=70;
};
parametro params[39];        

// Representacion de los estados de los termostatos
boolean cerrado =false;
boolean abierto = true;
struct termostatosAuxs{
boolean termostatoDeAcs = cerrado;
boolean termostatoDeMaximaPrimarioDeAcs = cerrado;
boolean PrecalentamientoDePrimarioParaAcs = cerrado;
boolean termostatoDeAmbiente = cerrado;
boolean termostatoDeMaximaPrimarioDeCalefaccion = cerrado;
boolean PrecalentamientoDePrimarioParaCalefaccion = cerrado;
};

// Representación de los estados de los horarios
boolean off =false;
boolean on = true;
struct  horariosAuxs {
boolean acsEnHorario = on;
boolean calefaccionEnHorario = on;
};

struct  relesAuxs{
int regimen = 0;
boolean releAuxAcs = off;
boolean releAuxCalefacccion = off;
};
boolean estadoDeLaBBDD = off;

// signaturas
void InicializarIO () ;
void VerificarComunicacion( int contador);
void GstionDelLCD ( int impresionDe, relesAuxs rAux, horariosAuxs hAux ) ;
void LecturaDeSondas () ;
float  CalcularConsignaRadiadores ( float consignaActual, relesAuxs rAux ) ;
void RecepcionDeParametros (parametro prM[39]) ;
int LeerValorDeBBDD ( String nombre ) ;
void GuardarEnBBDD ( parametro prM[39], String valor, String param ) ;
int  ControlDelQuemador ( boolean alarmas, int contadorRetardo, int retardo, relesAuxs rAuxs ) ;
struct relesAuxs AccionamientoDeBombas ( relesAuxs rAux, termostatosAuxs tAux, horariosAuxs hAux ) ;
struct termostatosAuxs GestionDeBombasY_ParoMarcha_ACS ( termostatosAuxs tAux ) ;
void EjecutarParoPorAlarma ( char tipoAlarma[16] ) ;
boolean  VigilanciaDeAlarmas (int ciclosDeReset) ;
struct horariosAuxs  AnularHorarios ( horariosAuxs hAux ) ;
struct horariosAuxs Comprobar_Horarios ( horariosAuxs hAux ) ;

void ImprimirEnviarBBDD ( parametro prM[39], String param) ;
int ModificarValoresDeParametros ( parametro prM[39],int parametro, int valor) ;
void(* Resetea) (void) = 0;
/* ...geters &
   ...seters */
// Metodo de inicio
void setup () {

        Serial.begin(9600);
        wdt_disable () ;
        SONDAS.begin () ;
        SONDAS.getDeviceCount();
        SONDAS.isParasitePowerMode();
        SONDAS.getAddress(direccionImpulsion, SONDA_IMPULSION);//1
        SONDAS.getAddress(direccionExterior, SONDA_EXTERIOR); //0
        SONDAS.getAddress(direccionAcs, SONDA_ACS); //2       
        SaludoInicial () ;
        InicializarIO () ;
        LecturaDeSondas () ;
        relesAuxs rAuxs;
        setConsignaDeRadiadores ( CalcularConsignaRadiadores ( getConsignaDeRadiadores (), rAuxs  )  ) ;
}
void SaludoInicial () {
        //Saludo inicial
        lcd.begin ( 16, 2 ) ;
        lcd.setCursor ( 0, 0 ) ;
        lcd.write ( "Fredinsa    1994" ) ;
        lcd.setCursor ( 0, 1 ) ;
        lcd.write ( " Espere el test " ) ;
        delay ( 2000 ) ;
   
  }
 // bucle infinito
void loop () {


            wdt_reset();         
            horariosAuxs hAux = AnularHorarios ( hAux ) ;
            termostatosAuxs tAux = GestionDeBombasY_ParoMarcha_ACS ( tAux ) ;
            relesAuxs rAux = AccionamientoDeBombas ( rAux, tAux, hAux ) ;  
            setConsignaDeRadiadores ( CalcularConsignaRadiadores ( getConsignaDeRadiadores (), rAux  )  ) ;           
            contadorRetardoDelQuemador = ControlDelQuemador ( VigilanciaDeAlarmas (1), contadorRetardoDelQuemador, getCiclosDeRetardoDelQuemador (), rAux ) ;
            setHoraDelArduino ( getHoraDelSistema());
            setMinutoDelArduino  ( getMinutoDelSistema()); 
            VerificarComunicacion( punteroDeParams);      
            params[17].valor=String( getHoraDelArduino());
            params[18].valor=String( getMinutoDelArduino());
            RecepcionDeParametros (params);   
            if ( contadorDeBucles ++ > 5 ) { contadorDeBucles = 0; } 
            wdt_reset();
            GstionDelLCD ( VISUALIZACIONES[contadorDeBucles], rAux, hAux ) ;
}
  void InicializarIO () {
   
        pinMode ( 13, OUTPUT ) ;
        pinMode ( PIN_ENTRADA_TERMOSTATO_AMBIENTE, INPUT ) ;
        pinMode ( PIN_ENTRADA_ANULACION_DE_HORARIOS, INPUT ) ;
        analogWrite ( SALIDA_QUEMADOR, 0 ) ;
        analogWrite ( SALIDA_BOMBA_RADIADOR, 0 ) ;
        analogWrite ( SALIDA_BOMBA_ACS, 0 ) ;
        analogWrite ( SALIDA_RESET_DE_raspi, 0 ) ;
       
        for (int k=0;k<38;k++)params[k]=InicializaParametros(k);      
 }

void VerificarComunicacion(int contador){
    valorActual =  getMinutoDelArduino();
    if (contador == 18){
          penultimoValor = ultimoValor;
          ultimoValor = valorActual;
          if (fallos < 10)
              analogWrite ( SALIDA_RESET_DE_raspi, 0 );
          if ( ( valorActual == ultimoValor) && ( valorActual == penultimoValor ) )
               fallos ++;
          else fallos = 0 ;
     }
    if (fallos >= 10) {
          analogWrite ( SALIDA_RESET_DE_raspi, 255 );
          fallos = 0;
     }
                                    
  }
void GstionDelLCD ( int impresionDe, relesAuxs rAux, horariosAuxs hAux ) {
    float valor = 0;
    const int paro = 0;
    const int calefaccion = 1;
    const int acs = 2;
    String valorDelRegistro = "SIN_DEMADA";
    String nombreDelRegistro = TIPO_DE_DEMANDA;//#define  "57"
    
    switch ( impresionDe ) {

      case VER_CONSIGNA:
        lcd.clear () ;
        lcd.setCursor ( 0, 0 ) ;
        lcd.write ( "DEMANDA DE " ) ;
      
              switch ( rAux.regimen ) {
                case calefaccion:
                  lcd.write ( "CALF." ) ;
                  valorDelRegistro = "CALEFACCION";       
                  valor = getConsignaDeRadiadores () ;
                break;
             
                case acs :
                  lcd.write ( "  ACS" ) ;
                  valorDelRegistro = "ACS";
                  valor = getConsignaMaximaPrimarioDeAcs () ;
                break; 
               
                case paro:
                  lcd.setCursor ( 0, 0 ) ;
                  lcd.write ( "   SIN DEMANDA  " ) ;
         
                  valor = getTempImpulsion () ;
                break;
                }
        lcd.setCursor ( 0, 1 ) ;
        lcd.write ( "Consigna " ) ;
        lcd.print ( valor ) ;
        lcd.print ( " C" ) ;
        digitalWrite ( 13, HIGH ) ; 
          break;
   
      case VER_TEMP_IMPULSION:
        lcd.setCursor ( 0, 0 ) ;
        lcd.write ( "Temp. impulsion:" ) ;
        lcd.setCursor ( 0, 1 ) ;
        lcd.print ( "        " ) ;
        lcd.print ( getTempImpulsion () , 2 ) ;
        valorDelRegistro = String ( getTempImpulsion () , 1 ) ;

        nombreDelRegistro = TEMPERATURA_DE_IMPULSION;//#define  "31"
        lcd.print ( " C   " ) ;
        digitalWrite ( 13, LOW ) ;
        break;
   
      case VER_TEMP_EXTERIOR:
        lcd.setCursor ( 0, 0 ) ;
        lcd.write ( "Temp.  exterior:" ) ;
        lcd.setCursor ( 0, 1 ) ;
        lcd.print ( "        " ) ;
        lcd.print ( getTempExterior () , 2 ) ;
        valorDelRegistro = String ( getTempExterior () , 1 ) ;
        nombreDelRegistro = TEMPERATURA_EXTERIOR;//#define   "32"
        lcd.print ( " C   " ) ;
        digitalWrite ( 13, HIGH ) ;    
        break;
   
       case VER_TEMP_ACS:
         lcd.setCursor ( 0, 0 ) ;
         lcd.write ( "Temp.       ACS:" ) ;
         lcd.setCursor ( 0, 1 ) ;
         lcd.print ( "        " ) ;
         lcd.print ( getTempACS () , 2 ) ; 
         valorDelRegistro = String ( getTempACS () , 1 ) ;
         nombreDelRegistro = TEMPERATURA_DE_ACS;//#define   "33"    
         digitalWrite ( 13, LOW ) ;
         break;
       
       case VER_HORARIO_ACS: 
         lcd.setCursor ( 0, 0 ) ;
         lcd.write ( "      ACS       " ) ;
         lcd.setCursor ( 0, 1 ) ;  
         if (contadorEstadoArduino++ == 1000)contadorEstadoArduino=0;
         GuardarEnBBDD ( params, String(contadorEstadoArduino), ESTADO_DEL_ARDUINO ) ; 
        
         if ( hAux.acsEnHorario ) {
             lcd.write ( "   En horario   " ) ;
             valorDelRegistro = "EnHorario";    
           }
         else {
             lcd.write ( "Fuera de horario" ) ;
             valorDelRegistro = "Fuera_Horario";
             }
         digitalWrite ( 13, HIGH ) ;    
         lcd.setCursor ( 0, 0 ) ; 
         nombreDelRegistro = ACS_EN_HORARIO;//#define   "55"
         break;
        
       case VER_HORARIO_CALEFACCION: 
         lcd.write ( "  Calefaccion   " ) ;
         lcd.setCursor ( 0, 1 ) ;
        
         if ( hAux.calefaccionEnHorario ) {
             lcd.write ( "   En horario   " ) ;
             valorDelRegistro = "EnHorario";
           }   
         else {
             lcd.write ( "Fuera de horario" ) ;
             valorDelRegistro = "Fuera_Horario";
            }
         digitalWrite ( 13, LOW ) ;
         nombreDelRegistro = CALEFCCION_EN_HORARIO;//#define  "56"
         break;    
  }
    GuardarEnBBDD ( params, valorDelRegistro, nombreDelRegistro ) ; 
    valorDelRegistro = String ( getHoraDelSistema()  ) ;
}

void LecturaDeSondas () {

    SONDAS.requestTemperatures () ; //Prepara los sensores para la lectura
    setTempImpulsion ( SONDAS.getTempC ( direccionImpulsion )  ) ;
    setTempExterior ( SONDAS.getTempC ( direccionExterior )  ) ;
    setTempACS ( SONDAS.getTempC ( direccionAcs )  ) ;
}
/*
Calcula la consigna para el agua de caldera.
Para ello se sirve de cuatro parámetros que corresponden al rango de
temperatura exterior por un lado, al rango de temperatura de impulsión por otro. Utiliza además una variable que es la lectura de la  temperatura exterior.
El valor obtenido será la consigna de referencia para el  funcionamiento de la caldera.
Con ello obtenemos una modificación constante de la  consigna de impulsión de agua a los radiadores, según vaya variando la temperatura exterior, obteniendo así un ahorro energético.
Si la demanda de la caldera es de ACS, se corrige la consigna a la seleccionada para el
primario de impulsión de ACS.
Si no existe demanda de ACS ni de calefacción, la consigna se establece en 5ºC como protección contra bajas temperaturas ( anti hielo ).
Existe también la posibilidad de programar una temperatura manualmente que prevalecerá sobre la calculada para curva de compensación, no así para la establecida para la máxima de ACS que continuará siendo la misma.
*/

float  CalcularConsignaRadiadores ( float consignaActual, relesAuxs rAux ) {

      float ejeX = ( getPuntoOrignDeTemperaturaExteriorEnCurvaDeCompensacion () - getPuntoLimiteDeTemperaturaExteriorEnCurvaDeCompensacion ()  ) ;
      float ejeY = ( getPuntoLimiteDeImpulsionEnCurvaDeCompensacion () - getPuntoDeOrigenDeImpulsionEnCurvaDeCompensacion ()  ) ;
      float relacionXY = ejeY / ejeX;
      int manual = 1;
      const int calefaccion = 1;
      const int acs = 2;
      float consigna=5;
          switch ( rAux.regimen ){
         
            case calefaccion:
           
                consigna = getPuntoDeOrigenDeImpulsionEnCurvaDeCompensacion () + ( relacionXY * ( getPuntoOrignDeTemperaturaExteriorEnCurvaDeCompensacion () - getTempExterior ()  )  ) ;
 
                if ( consigna < getPuntoDeOrigenDeImpulsionEnCurvaDeCompensacion ()  )
                     consigna = getPuntoDeOrigenDeImpulsionEnCurvaDeCompensacion () ;
                    
                if ( consigna > getPuntoLimiteDeImpulsionEnCurvaDeCompensacion ()  )
                     consigna = getPuntoLimiteDeImpulsionEnCurvaDeCompensacion () ;
                    
                   /* Uso de una consigna manual */    
                if ( getConsignaManualDeRadiadoresHabilitada () == manual ) consigna = getConsignaDeRadiadoresManual () ;
            break;
           
            case acs:
                consigna = getConsignaMaximaPrimarioDeAcs ();           
            break;
           
         }

        if ( consigna!=consignaActual ) {
           String textoDelMensajeParaConsigna = String ( consigna, 1 ) ; 
           GuardarEnBBDD ( params, textoDelMensajeParaConsigna, CONSIGNA_DE_RADIADORES_CALCULADA ) ;
        }//#define  "41"
          
           return consigna;                   
}
/*
El método recibe un string en un formato predeterminado y obtiene de el varias etiquetas:
  $-Carácter de inicio de tipo de mensaje->Tipo de mensaje->
  %-Carácter de inicio de->NOMBRE_DE_PARAMETRO a quien a dirigido en mayusculas->
  &-Carácter de inicio de->Nuevo Valor del parámetro
  Los tres bloques deben ir juntos y sin espacios.
  Ejemplo de lectura de un parámetro:
  $lectura%HORA_DE_ENCENDIDO_DE_CALEFACCION&
  escritura:
  $escritura%HORA_DE_ENCENDIDO_DE_CALEFACCION&12+ un valor numérico culquiera;9
  $escritura%HORA_DE_ENCENDIDO_DE_CALEFACCION&129
*/
void RecepcionDeParametros (parametro prM[39] ) {   

              char c =' ' ; char n=' '; char a = ' '; char v = ' ' ;
             
              int buffer_entrada[64];  
              int int_entrada[64];  
              char entrada[64]="entrada";  
              int r = 0 ;
              int s = 0;
              int t = 0 ;      
   
              char accion[14]= "nula";
              char parametro[40]="nada";
              char valor[7]="0";
               
               

              const char int_Accion = '$'; //$
              const char int_Parametro = '%'; // %
              const char int_Valor = '&'; // &
              const char int_Final = '/'; // &             
              char caso = c ; //0;
              int w=0;
              int l =0;

              int A = 0 ;
              int P = 0 ;
              int V = 0 ;     
              boolean nuevaEntrada = false;
              int q=0;
  
              // confección de la entrada  
              Serial.flush();          
              if (Serial.available() > 0) {//Comprobamos si hay algo esperando
                              while(  s < 64 ) {//Si lo hay, lo leemos hasta el carácter intro
                                    r = Serial.read(); //Leer 1 carácter
                                    delay(10);
                                    if ( r > 33 && r < 126 && r != -1 && r != 47 ){
                                        int_entrada[t] = ( buffer_entrada[s] = r );                                    
                                       
                                        t++;
                                        l=t;
                                     }
                                    s++;
                                    }
                                    nuevaEntrada = true;
                        }// fin de entrada en buffer
                       if (  nuevaEntrada ){
                             for (int k=0;k<l;k++){
                                                            

                              if ( int_entrada[k] == int_Final ) break;
                              entrada[k] = char ( int_entrada[k] );

                            }
                      // Inicio de análisis
                   
                    for (int i=0; i<l-1;i++){
                      c = entrada[i];
                            if ( c == int_Final)  caso = int_Final;
                            if ( c == int_Accion ) caso = int_Accion ;
                            if ( c == int_Parametro ) caso = int_Parametro ;
                            if ( c == int_Valor ) caso = int_Valor ;
                                 
                                        if ( caso == int_Accion && A<=13) {
                                        accion[A-1] = char ( c );//entrada[w];//d ;                                    
                                        A++;}
                                       
                                        if ( caso == int_Parametro && P<=39) {//int_Parametro:
                                        parametro[P-1] = char ( c );//d ;
                                        P++;}
                                       
                                        if ( caso == int_Valor && V<=5) {//int_Valor:
                                        valor[V-1] = char ( c );//entrada[w];//d ;                                          
                                        V++;}
                    }
                        
                } // Nueva entrada
                  String aux_Accion = accion;
                  String aux_Parametro = parametro;
                  String aux_Valor = valor;
                  //Envió para su impresión de los valores de variables y estado de los algoritmos.
                  // No se imprimen los parámetros introducidos a no ser que se pidan explícitamente.
                  // a través de la etiqueta -lectura-
                                    if (punteroDeParams++>38)punteroDeParams=16;
                  // Si se solicita una lectura, se imprime el parámetro solicitado y se envía.
                                    if ( aux_Accion == "lectura" ) ImprimirEnviarBBDD ( prM, parametro) ;  
                  // Sino se imprime cada vez uno por orden de array, siempre que sea menor que -p-
                                    else if (punteroDeParams>=16)ImprimirEnviarBBDD ( prM, prM[punteroDeParams].nombre);                          

}
 /*
 El  método consiste en envía en un formato predeterminado un mensaje
 con el -nombre- y el -valor- de un parámetro, separados por un espacio.
 La RaspberryPi reconocerá la estructura del dato  y tratará.
 Si el valor de -param- es -TODO-, se imprimirá todo el array de parámetros y variables
 */
void ImprimirEnviarBBDD ( parametro prM[39], String param) {

        
          String todo="TODO";
          int n,v,r;
                   /*  if ( param == todo ){                           
                            Serial.print("                 Nombre                 ");
                            Serial.print ("       Valor        ");
                            Serial.println (" Registro ");
                            Serial.println ("   ----------------------------------      --------------     --------  ");                           
                            Serial.println();
                            for (int k=0;k<38;k++){
                             
                              n = prM[k].nombre.length();
                              n = (40-n)/2;
                             for (int i=0;i<n;i++){
                            Serial.print(" ");}                           
                            Serial.print ( prM[k].nombre);

                              v = prM[k].valor.length();                            
                              v = (20-v)/2;                       
                             for (int i=0;i<v+n;i++){
                            Serial.print(" ");}                           
                            Serial.print ( prM[k].valor);*/    //Abrir para TODO
                           
                         /*     r = prM[k].registro.length();
                              r = (14-r)/2;                        
                             for (int i=0;i<r+v;i++){
                            Serial.print(" ");}                           
                            Serial.print ( prM[k].registro); */
                           
                      /*      Serial.println();
                         }
                          return;                        
                       }*/     //Abrir para TODO
                                  
          for (int k=0;k<38;k++){
                      if ( prM[k].nombre == param ){   
                         Serial.print(prM[k].nombre);
                         Serial.print(" "+prM[k].valor );
                         Serial.println();
                         break;
                       }     
        }
}
/* Actualiza el Array con los nuevos estados de los equipos y valores de sondas de temperatura.
   Para ello primero comprueba que el  "valor " está dentro de rango establecido par cada uno de los parámetros.De no ser así lo corrige
   Una vez verificada se guarda en el array.         
*/
void GuardarEnBBDD ( parametro prM[39], String valor, String nombre  ) {

        for (int k=0;k<38;k++){
        if (prM[k].nombre==nombre){prM[k].valor=valor;
            if (k<=16){
               int valorVerificado= ModificarValoresDeParametros (prM, prM[k].destino, valor.toInt() );  
                      prM[k].valor=String(valorVerificado);
                 }
        break;}
        }
}
 

struct termostatosAuxs GestionDeBombasY_ParoMarcha_ACS ( termostatosAuxs tAux ) {
 
      tAux.PrecalentamientoDePrimarioParaAcs =
      tAux.termostatoDeMaximaPrimarioDeAcs =
      tAux.termostatoDeAcs =
      tAux.PrecalentamientoDePrimarioParaCalefaccion =
      tAux.termostatoDeMaximaPrimarioDeCalefaccion =
      tAux.termostatoDeAmbiente = cerrado;
     
      if ( getTempImpulsion () > getConsignaMinimaPrimarioDeAcs ()  )
            tAux.PrecalentamientoDePrimarioParaAcs = abierto;

      if ( getTempImpulsion () > getConsignaMaximaPrimarioDeAcs ()  )
            tAux.termostatoDeMaximaPrimarioDeAcs = abierto;

      if ( getTempACS () < getConsignaDeConsumoDeAcs ()  )
            tAux.termostatoDeAcs = abierto;           
           
      if ( getTempImpulsion () >  getPuntoDeOrigenDeImpulsionEnCurvaDeCompensacion ()  )
            tAux.PrecalentamientoDePrimarioParaCalefaccion = abierto;

      if ( getTempImpulsion () > getConsignaDeRadiadores ()  )
            tAux.termostatoDeMaximaPrimarioDeCalefaccion = abierto;
           
      String mensajeDelTermostatoAmbiente = "21,3";
      if ( digitalRead ( PIN_ENTRADA_TERMOSTATO_AMBIENTE )  ) {
                 mensajeDelTermostatoAmbiente = "20,7";       
                 tAux.termostatoDeAmbiente = abierto;
               }
              
       GuardarEnBBDD ( params, mensajeDelTermostatoAmbiente, TEMPERATURA_AMBIENTE ) ;//#define "38"       
      
 return tAux;          
}
struct relesAuxs AccionamientoDeBombas ( relesAuxs rAux, termostatosAuxs tAux, horariosAuxs hAux ) {
     
      int paro = 0;
      int regimen = paro;
      int calefaccion = 1;
      int acs = 2;
      String mensajeDeBombaAcs = "PARO";
      String mensajeDeBombaCalefaccion = "PARO";

      rAux.releAuxCalefacccion = off;
      rAux.releAuxAcs = off;
        analogWrite ( SALIDA_BOMBA_ACS, 0 ) ; // paro por consigna
        analogWrite ( SALIDA_BOMBA_RADIADOR, 0 ) ; // paro por consigna
              
             if ( tAux.termostatoDeAcs && hAux.acsEnHorario ) {
                        rAux.regimen = acs;
                     if ( !tAux.termostatoDeMaximaPrimarioDeAcs ) rAux.releAuxAcs = on;  

                     if ( !tAux.PrecalentamientoDePrimarioParaAcs ) { mensajeDeBombaAcs = "PRE_CALENTAMIENTO"; }
                         else { analogWrite ( SALIDA_BOMBA_ACS, 255 ) ;   mensajeDeBombaAcs = "MARCHA"; }    
                     if ( tAux.termostatoDeAmbiente && hAux.calefaccionEnHorario ) mensajeDeBombaCalefaccion = "SIN_PRIORIDAD";                     
              
             }             
               else if ( tAux.termostatoDeAmbiente && hAux.calefaccionEnHorario ) {
                
                         rAux.regimen = calefaccion;                 

                       if ( !tAux.termostatoDeMaximaPrimarioDeCalefaccion ) rAux.releAuxCalefacccion = on;    
                     
                       if ( !tAux.PrecalentamientoDePrimarioParaCalefaccion ) {mensajeDeBombaCalefaccion = "PRE_CALENTAMIENTO"; }
                          else { analogWrite ( SALIDA_BOMBA_RADIADOR, 255 ) ; mensajeDeBombaCalefaccion = "MARCHA"; }                                   
                     }
                       if ( !hAux.acsEnHorario ) mensajeDeBombaAcs = "FUERA_DE_HORARIO";             
             
                       if ( !hAux.calefaccionEnHorario ) mensajeDeBombaCalefaccion = "FUERA_DE_HORARIO";        
         
                   GuardarEnBBDD ( params,  mensajeDeBombaCalefaccion, ESTADO_BOMBA_CALEFACCION ) ;//#define  "2"
                   GuardarEnBBDD ( params,  mensajeDeBombaAcs, ESATADO_BOMBA_ACS ) ;//#define "1"
 
          
     return rAux;
}

// control del paro-marcha del quemador
int  ControlDelQuemador ( boolean alarmas, int contadorRetardo, int retardo, relesAuxs rAuxs ) {


        String mensajeDelQuemador = "PARO";
       
        boolean finalDelRetardo = off;
        boolean releAcs = rAuxs.releAuxAcs;
        boolean releCalefaccion = rAuxs.releAuxCalefacccion;
       
        analogWrite ( SALIDA_QUEMADOR, 0 ) ;

        if ( !releAcs && !releCalefaccion ) contadorRetardo = 0;
       
        if (  ( contadorRetardo ) > ( retardo )  ) {
             contadorRetardo = retardo + 10; 
             finalDelRetardo = on;
         }
        else { contadorRetardo++; }

            
         if ( !alarmas && !releAcs && !releCalefaccion ) mensajeDelQuemador = "PARO";
         if ( !alarmas && ( releAcs || releCalefaccion ) && !finalDelRetardo ) mensajeDelQuemador = "RETARDO";                     
         if ( !alarmas && ( releAcs || releCalefaccion ) && finalDelRetardo ) {
                analogWrite ( SALIDA_QUEMADOR, 255 ) ;  
                mensajeDelQuemador = "MARCHA";                     
           }   
         if ( alarmas ) mensajeDelQuemador = "FALLO";                  

          GuardarEnBBDD ( params,  mensajeDelQuemador, ESTADO_DEL_QUEMADOR ) ;//#define  "0"
                   
            return contadorRetardo;
}


boolean  VigilanciaDeAlarmas (int ciclosDeReset) {
       String mensajeDeAlarmas = "NINGUN_FALLO";
       boolean estadoDeAlarmas = off;
       LecturaDeSondas () ;
       SONDAS.resetAlarmSearch(); 
      
       if ( analogRead ( PIN_ENTRADA_ALARMA_EXTERIOR ) >= 1000 ) {
       EjecutarParoPorAlarma ( " FALLO QUEMADOR " ) ;
       estadoDeAlarmas = on;
       mensajeDeAlarmas = "FALLO_EXTERNO";
   }
    if ( getTempImpulsion () <=-50 || getTempExterior () <=-50 || getTempACS () <=-50 ||
       getTempImpulsion () >=120 || getTempExterior () >=120 || getTempACS () >=120 ) {
       estadoDeAlarmas = on;
       EjecutarParoPorAlarma ( "ERROR DE LECTURA" ) ;
       mensajeDeAlarmas = "FALLO_SONDAS";

   } 
     GuardarEnBBDD ( params,  mensajeDeAlarmas, ESTADO_DE_ALARMAS ) ; delay ( 100 ) ;//#define  "7"

     if ( estadoDeAlarmas ) {
         estadoDeAlarmas = off;
         wdt_reset(); 
         if (ciclosDeReset++ ==100)  {Resetea();}    
         VigilanciaDeAlarmas (ciclosDeReset) ;
       } 
   return estadoDeAlarmas;
}

void EjecutarParoPorAlarma ( char tipoAlarma[16] ) {
 
          lcd.clear () ;
          lcd.setCursor ( 0, 0 ) ;
          lcd.write ( "     ALARMA     " ) ;
          lcd.setCursor ( 0, 1 ) ;
          lcd.write ( tipoAlarma ) ;
          analogWrite ( SALIDA_QUEMADOR, 0 ) ;
          analogWrite ( SALIDA_BOMBA_ACS, 0 ) ;
          analogWrite ( SALIDA_BOMBA_RADIADOR, 0 ) ;         
          contadorRetardoDelQuemador = 0; 
         
}

struct horariosAuxs  AnularHorarios ( horariosAuxs hAux ) {
     String mensajeDePinDeAnulacionDeHorarios = "INACTIVO";
     GuardarEnBBDD ( params,  mensajeDePinDeAnulacionDeHorarios, ESTADO_DE_PIN_ANULA_HORARIOS ) ;//#define "5"
     if ( digitalRead ( PIN_ENTRADA_ANULACION_DE_HORARIOS )  ) {
        hAux.calefaccionEnHorario = hAux.acsEnHorario = on;
        mensajeDePinDeAnulacionDeHorarios = "ACTIVO";
        GuardarEnBBDD ( params,  mensajeDePinDeAnulacionDeHorarios, ESTADO_DE_PIN_ANULA_HORARIOS ) ;
      }
      else hAux = Comprobar_Horarios ( hAux ) ;
     return  hAux;
}

struct horariosAuxs Comprobar_Horarios ( horariosAuxs hAux ) {

   
  if ( getHoraDeEncendidoDeAcs () < getHoraDeApagadoDeAcs ()  ) {
        hAux.acsEnHorario = off;
        if (  ( getHoraDelArduino () >= getHoraDeEncendidoDeAcs ()  ) && ( getHoraDelArduino () <=getHoraDeApagadoDeAcs ()  )  ) hAux.acsEnHorario = on;
  }
 
  if ( getHoraDeEncendidoDeAcs () > getHoraDeApagadoDeAcs ()  ) {
        hAux.acsEnHorario = on;
        if (  ( getHoraDelArduino () >=getHoraDeApagadoDeAcs ()  ) && ( getHoraDelArduino () <=getHoraDeEncendidoDeAcs ()  )  ) hAux.acsEnHorario = off;
  }
   
  if ( getHoraDeEncendidoDeCalefaccion () < getHoraDeApagadoDeCalefaccion ()  ) {
        hAux.calefaccionEnHorario = off;
        if (  ( getHoraDelArduino () >=getHoraDeEncendidoDeCalefaccion ()  ) && ( getHoraDelArduino () <=getHoraDeApagadoDeCalefaccion ()  )  ) hAux.calefaccionEnHorario = on;
  }
 
  if ( getHoraDeEncendidoDeCalefaccion () > getHoraDeApagadoDeCalefaccion ()  ) {
        hAux.calefaccionEnHorario=on;
        if (  ( getHoraDelArduino () >=getHoraDeApagadoDeCalefaccion ()  ) && ( getHoraDelArduino () <=getHoraDeEncendidoDeCalefaccion ()  )  ) hAux.calefaccionEnHorario = off;
  }
 
  return  hAux;
}

  float setTempImpulsion ( float valor ) {
  return TempImpulsion = valor;
  }
  float setTempExterior ( float valor ) {
  return TempExterior = valor;
  }
  float  setTempACS ( float valor ) {
  return TempACS = valor;
  }
 
  void  setConsignaDeRadiadores ( int valor ) {
   consignaDeRadiadores = valor;
  }
  void setConsignaMinimaPrimarioDeAcs (int valor) {
   consignaMinimaPrimarioDeAcs = valor;
  }
  void setConsignaMaximaPrimarioDeAcs (int valor) {
   consignaMaximaPrimarioDeAcs = valor;
  }
 
    void setHoraDelSistema (int valor) {
   horaDelSistema = valor;
  }  
 
  void setMinutoDelSistema (int valor) {
   minutoDelSistema = valor;
  } 
    void setHoraDelArduino (int valor) {
   horaDelArduino = valor;  
  }  

  void setMinutoDelArduino (int valor) {
   minutoDelArduino = valor;
  }  
  void setPuntoOrignDeTemperaturaExteriorEnCurvaDeCompensacion (int valor) {
   puntoOrignDeTemperaturaExteriorEnCurvaDeCompensacion = valor;
  }
  void setPuntoLimiteDeTemperaturaExteriorEnCurvaDeCompensacion (int valor) {
   puntoLimiteDeTemperaturaExteriorEnCurvaDeCompensacion = valor;
  }
  void setPuntoDeOrigenDeImpulsionEnCurvaDeCompensacion (int valor) {
   puntoDeOrigenDeImpulsionEnCurvaDeCompensacion = valor;
  }
  void setPuntoLimiteDeImpulsionEnCurvaDeCompensacion (int valor) {
   puntoLimiteDeImpulsionEnCurvaDeCompensacion = valor;
  }
  void setConsignaDeRadiadoresManual (int valor) {
   consignaDeRadiadoresManual = valor;
  } 
  void setConsignaManualDeRadiadoresHabilitada (int valor) {
   consignaManualDeRadiadoresHabilitada = valor;
  }   
  void setConsignaDeConsumoDeAcs (int valor ) {
   consignaDeConsumoDeAcs = valor ;
  } 
  void setHoraDeEncendidoDeCalefaccion (int valor ) {
   horaDeEncendidoDeCalefaccion = valor ;
  }   
    void setHoraDeApagadoDeCalefaccion (int valor ) {
   horaDeApagadoDeCalefaccion = valor ;
  }
    void setHoraDeEncendidoDeAcs (int valor ) {
   horaDeEncendidoDeAcs = valor ;
  }
    void setHoraDeApagadoDeAcs (int valor ) {
   horaDeApagadoDeAcs = valor ;
  }  
  void setCiclosDeRetardoDelQuemador (int valor) {
   ciclosDeRetardoDelQuemador = valor;
  }  
  float getTempImpulsion () {
  return TempImpulsion;
  }
  float getTempExterior () {
  return TempExterior;
  }
  float getTempACS () {
  return TempACS;
  } 
  int getPuntoOrignDeTemperaturaExteriorEnCurvaDeCompensacion () {
  return puntoOrignDeTemperaturaExteriorEnCurvaDeCompensacion;
  }
 
  int getPuntoLimiteDeTemperaturaExteriorEnCurvaDeCompensacion () {
  return puntoLimiteDeTemperaturaExteriorEnCurvaDeCompensacion;
  }
 
  int getPuntoDeOrigenDeImpulsionEnCurvaDeCompensacion () {
  return puntoDeOrigenDeImpulsionEnCurvaDeCompensacion;
  }
 
  int getPuntoLimiteDeImpulsionEnCurvaDeCompensacion () {
  return puntoLimiteDeImpulsionEnCurvaDeCompensacion;
  }

  int getConsignaDeRadiadoresManual () {
  return consignaDeRadiadoresManual;
  }
 
  int getConsignaManualDeRadiadoresHabilitada () {
  return consignaManualDeRadiadoresHabilitada;
  }
 
  int getConsignaDeConsumoDeAcs () {
  return consignaDeConsumoDeAcs;
  }
 
  int getHoraDeEncendidoDeCalefaccion () {
  return horaDeEncendidoDeCalefaccion;
  } 

  int getHoraDeApagadoDeCalefaccion () {
  return horaDeApagadoDeCalefaccion;
  }
 
  int getHoraDeEncendidoDeAcs () {
  return horaDeEncendidoDeAcs;
  }
 
  int getHoraDeApagadoDeAcs () {
  return horaDeApagadoDeAcs;
  }
 
  int getHoraDelSistema () {
  return horaDelSistema;
  }  

  int getMinutoDelSistema () {
  return minutoDelSistema;
  } 
    int getHoraDelArduino () {
  return horaDelArduino;
  }  

  int getMinutoDelArduino () {
  return minutoDelArduino;
  } 

  int getConsignaMinimaPrimarioDeAcs () {
  return consignaMinimaPrimarioDeAcs;
  } 

  int getConsignaMaximaPrimarioDeAcs () {
  return consignaMaximaPrimarioDeAcs;
  }   

  int getCiclosDeRetardoDelQuemador () {
  return ciclosDeRetardoDelQuemador;
  }   
  int getConsignaDeRadiadores () {
  return consignaDeRadiadores;
  } 
 
// modificacion de PARAMETROS
int ModificarValoresDeParametros (parametro prM[39], int parametro, int valor ) {

 
  switch ( parametro ) {
   
     case valorParaOrigenExterior://0
     if ( valor < 12 || valor > 22 ) valor = 20;
     setPuntoOrignDeTemperaturaExteriorEnCurvaDeCompensacion (valor);
     break;
    
    case valorParaLimiteExterior://1

     if ( valor < 0  || valor > 7 ) valor = 1;
     setPuntoLimiteDeTemperaturaExteriorEnCurvaDeCompensacion (valor);
    break;
   
    case valorParaOrigenImpulsion://2
     if (valor < 40  || valor > 50 )      valor = 45;
     setPuntoDeOrigenDeImpulsionEnCurvaDeCompensacion ( valor);
    break;
   
    case valorParalimiteImpulsion://3
     if (valor < 55  || valor > 75 )      valor = 65;
     setPuntoLimiteDeImpulsionEnCurvaDeCompensacion (valor);
    break;

   /* case valorParaRESET://14
      Resetea();
    break;*/

    case valorParaConsignaRadiadoresManual: //5
     if (valor < 40  || valor > 80 )      valor = 60;
     setConsignaDeRadiadoresManual (valor);
    break;

    case valorParaAutoConsigna: //6
     if (valor < 1  || valor > 0 )      valor = 0;
     setConsignaManualDeRadiadoresHabilitada (valor);
    break;

    case valorParaACS:// 7
     if (valor < 35  || valor > 50 )      valor = 43;
     setConsignaDeConsumoDeAcs (valor);
    break;

    case valorParaHoraEncendido_Calefaccion://8
     if (valor < 0  || valor > 23)     valor = 7;
     setHoraDeEncendidoDeCalefaccion (valor);
    break;
   
    case valorParaHoraApagado_Calefaccion://9    
     if (valor < 0  || valor > 23)     valor = 23;
     setHoraDeApagadoDeCalefaccion (valor);
    break;
   
    case valorParaHoraEncendido_ACS://10   
     if (valor < 0  || valor > 23)     valor = 7;
     setHoraDeEncendidoDeAcs (valor);
    break;
   
     case valorParaHoraApagado_ACS://11 
     if (valor < 0  || valor > 23)     valor = 23;
     setHoraDeApagadoDeAcs (valor);
    break;
   
    case valorParaHoraDelSistema://12
     if (valor < 0 || valor > 23)  valor = 9;
     setHoraDelSistema (valor);
    break;
       
    case valorParaMinutoDelSistema://13
     if (valor < 0  || valor > 59)     valor = 17;
     setMinutoDelSistema ( valor );
    break;   

    case valorParaMinimaImpACS://14
     if (valor < 50  || valor > 60)     valor = 55;
     setConsignaMinimaPrimarioDeAcs (valor);
    break;
       
    case valorParaMaximaImpACS://15
     if (valor < 65  || valor > 80 )     valor = 75;
     setConsignaMaximaPrimarioDeAcs ( valor );
    break;
   
    case valorParaRetardoDelQuemador://16
     if (valor < 4  || valor > 20)     valor = 8;
     ciclosDeRetardoDelQuemador = valor;
    break;  
   
}

return valor;
}

TEST DE LA APLICACIÓN:

Demanda prioritaria de ACS:

 

 


  Demanda de calefacción: