domingo, 19 de abril de 2020

Cargador de baterías de coche con fuente de PC y controlador basado en Arduino.




Aprovechando estos días de confinamiento he terminado un cargador de baterías a partir de una fuente de PC.




Las fuentes de PC en principio solo suministran 11,6V en su sálida de 12 V, pero con algunas modificaciones en la patilla 1 del chip que controla la tensión esta se puede aumentar hasta superar los 14V y hacerla útil para cargar una batería de automoción.

Las fuentes están diseñadas para mantener los 5V del cable rojo independientemente de la carga de este porqe es la tensión que alimenta los dispósitivos eléctrónicos más criticos no siendo en las otras tensiones importante la exactitud.
Entonces la modificación que tenemos que hacer es que nuestra tensión de 12V sea la regulada en lugar de la de 5V, para ello es necesario hacer unas pequeñas modificaciones, pero que son críticas  y deben hacerse siempre con la fuente desenchufada:

-Buscar el chip TL494 o similar, encargado de la regulación de salida de la fuente, este integrado cuando en su patilla tiene menos de 2,5 V aumenta el tiempo de ciclo alto de la onda de salida para aumentar la tensión, si es mayor de esos 2,5, la disminuye, regulando de esa forma la tensión final de salida de la fuente en 5V.  Nuestro proposito es hacer que esa salida no esté referida a los 5 V, sino a los 12 que es la que nos interesa.
El chip que llevan las fuentes puede ser el TL494, pero también puede ser otro modelo de funcionamiento análogo  en cuyo caso habría que consultar el datasheet para buscar la patilla sobre la que actuar.

Preparación de la fuente:
- De la fuente vamos a utilizar los cables amarillos, los negros, un morado, el verde y un rojo si quisieramos incluir un led extra para indicar que la fuente esta encendida.  Conviene desoldar los grupos de cables rojos y naranja ( dejando uno por si alguna vez queremos utilizar la fuente para otra cosa ).
Sanear los cables que quedan cortandolos a la medida adecuada al proyecto y agrupandolos por colores con bridas para que quepan dentro de la caja sin tocar los ventiladores ni ocupando más espacio del imprescindible.

-Si la fuente tiene interruptor de encendido unimos el cable verde  con uno negro a través de una resistencia de 220 Ohm.  (La unión de estos cables es lo que indica a la fuente que debe encenderse), Si no hay interruptor de encendido podemos colocar el interruptor de encendico entre estos dos cables.

- Modificar la eléctrónica de la fuente para fijar la tensión de los cables amarillos a 14,4V ( En la carpeta de archivos he incluido uno que encontré en internet que describe detalladamente el proceso de modificación).

-Desoldar la patilla 1 de su punto de conexión, extraerla  y hacer la nueva conexión.La modificación debe hacerse sin tensión y de forma cuidadosa, no encender la fuente hasta asegurarnos de que esté todo correcto porque podríamos estropearla. :

- Comprobar la tensión de salida de los cables amarillos y actuando sobre la resistencia variable fijarla a 14,3-14,4V, que es la ideal para cargar las baterías.


Hasta aquí tendriamos una fuente normal, pero que no corta la carga. Con un sencillo circuito y un arduino podemos añadirle esa funcionalidad además de que nos indique con unos led,s como va más o menos el proceso. 


El arduino parará la carga cada rato y verifica la tensión en la batería. Si esta está por debajo de 13,6V continuará cargando. Al alcanzar los 13,6V se abre un relé y la carga se detiene.  El arduino lo vamos a alimentar con la salida de 5V morada, prescindiendo de las rojas de 5V.


Para dejar terminado el proyecto podemos incluir  un voltimetro-amperimetro electronico que nos permite de un rápido vistazo si todo está correcto o si la batería presenta problemas. En mi caso en el momento que escribo esto aún no me había llegado y lo espero para incluirlo a la salida hacia la batería.

Hay que armarse de paciencia y ser meticuloso para ejecutar el circuito de manera que quede dentro de la fuente confinado en el poco  espacio libre que hay, yo he utilizado una lámina plastica y cinta americana para mantener un pequeño espacio aislado del resto y a la vez no obstruya el paso del aire por dentro de la fuente.




Otra opción es situarlo todo en una cajita exterior a la la caja de la fuente, todo es valorar el espacio libre y las distintas posibilidades.






En esta carpeta están varios de los archivos utilizados para el proyecto: un pdf con la descripción completa y detallada  de la modificación de la fuente, el squetch de arduino, las pegatinas e instrucciones, esquema, etc..


https://drive.google.com/drive/folders/1YgTYMvVCEOkUrP3bPd8zOxeWQlujdnsX?usp=sharing




 Sketch:

El Sketch requerirá comprobación y ajustes personalizados en cada circuito, debido a las pecularidades de los componentes utilizados en el divisor de tensión que verifica la tensión de salida ( no hay dos resistencias con un valor igual ).
Armarse de paciencia hasta que nos quede bien ajustado modificando los valores en los que se compara la lectura del pin analógico almacenado en la variable S1, para ello comprobaremos con un voltimetro que la salida de tensión son las indicadas en los comentarios del Sketch.
El programa tiene un sistema de seguridad que si no detecta tensión externa en las pinzas no cerrará el relé ( Tenerlo en cuenta para hacer las verificaciones, por ejemplo desacactivando esa linea, está hacia el final del squetch ... 
if (analogRead(A1)<301 .....="" font="">):

// Visual Micro is in vMicro>General>Tutorial Mode
//
/*
    Name:       Cargador  baterias.ino
    Created:  03/03/2020 22:20:59
    Author:     DESKTOP-H6FCVQ6\Fernando
    Arduino se alimenta a trabvés del cable morado +5V de la fuente.
*/


  int S1;    // Declarar voltimetro.
  int t4=-4;  // Memoria de control de tiempo de muestreo
  int c;  // Multiplicador de tiempo de retardo según carga
  long t0=150000; // Tpo en milisegundos de la revisión

 
void setup()
{
byte x;
    Serial.begin(57600);

    pinMode(2, OUTPUT); // FUNCIONAMIENTO ROJO,<11 br="">    pinMode(3, OUTPUT); // FUNCIONAMIENTO amarillo,>12,1V
    pinMode(4, OUTPUT); // FUNCIONAMIENTO verde,>13,1V
    pinMode(13, OUTPUT);// Rele de control


    Serial.println("Centralita del cargador de Fernando Herraiz");
    Serial.println("Led rojo intermitente indica V> 11,1, fijo indica V> 11,6 ;L2 amarillo intermitente  indica V> 12,1.");
    Serial.println("Led 2 amarillo indica V > 12,6 ; L3 verde intermitente indica V >13,1  fijo indica V>=13,6,");
    Serial.println(" Punto en que abre el rele y se acaba la carga: 13,6V");
    Serial.println("  ");

for (x=0;x<5 x="x+1){<br">      digitalWrite(4, HIGH);digitalWrite(2, LOW);delay(180);digitalWrite(3, HIGH);digitalWrite(4, LOW);delay(160);digitalWrite(2, HIGH);digitalWrite(3, LOW);delay(170);
     
} // Esperar estabilización de la fuente.

} // Fin setup()



void loop()
{
  float t; // Variable temporizaddor
  boolean t2;  //  Control de intermitencia
  int t3;  // Vatiable tpo cada 5 min.; 300000=5 min
  int S2;
 
  t = int(millis() / 70); // t=medios segundos para leds intermitentes
  if (int(t / 2) == t / 2) { t2 = HIGH; } else { t2 = LOW; }


    t3= int(millis()/t0);  //  Tiempo cadda x minutos verificar voltímetro entre 30 y 5 min,  según carga
  //  Serial.println(t3);  Serial.print(" T/5min. : ");  Serial.println(t4);

 
   if (t3 > t4+c) {                                                             // Leer tensión con carga desconectada
       digitalWrite(13, LOW);    // Abrir rele para pausar carga
    
                                //Pausa 1 seg);
      digitalWrite(4, HIGH);digitalWrite(3, HIGH);digitalWrite(2, HIGH);delay(500);
      digitalWrite(2, LOW);digitalWrite(4, LOW);digitalWrite(3, LOW);delay(400);
     
       S1 = analogRead(A1);  // Leer tensión en batería.

       delay(100);

       S2= analogRead(A1); // Hacer segunda lectura de comprobación
       if (abs(S2-S1)<4 br="" correcta.="" lectura="" t4="t3;} ">      
       }
    
 // Serial.print("->  Voltímetro: "); Serial.println(S1);

c=1;
 
  if (S1 > 826) { digitalWrite(2, HIGH);  c=3;} else { digitalWrite(2, LOW); }                     // Encender y apagar led 1 a 11,6.
  if ((S1 > 790)&& ( t2 == HIGH)) { digitalWrite(2, HIGH); }                                  // Intermitencia a 11,1
 
  if (S1 > 898) { digitalWrite(3, HIGH);  c=2;}  else { digitalWrite(3, LOW); }                    // Encender y apagar led 2 a 12,6.
  if ((S1 > 862) && (t2 == HIGH)) { digitalWrite(3, HIGH); }                                  //  Intermitencia a 12,1

  if (S1 > 969) { digitalWrite(4, HIGH); digitalWrite(13, LOW);c=0; t4=-4; }      // Encender y apagar led 3 y rele a 4,4V.
      else { 
        digitalWrite(4, LOW);                         
        if ((millis()<43200000 amp=""> 300)) {digitalWrite(13, HIGH) ; }                 // Mantener alimentación si hay menos de 13,6V, menos de 12 horas de funcionamiento y hay batería en las pinmzas.
      }
     
  if ((S1 > 934) && (t2 == HIGH)) { digitalWrite(4, HIGH); c=0; }                                   //  Intermitencia a 13,1

  if (t3<3 15="" aumentar="" br="" c="0; " camprobaciones="" de="" else="" los="" minutos="" n="" nbsp="" primeros="" t0="300000;}                                                      " tensi=""> 
  if (analogRead(A1)<301 bateria.="" br="" detectan="" en="" hay="" las="" n="" nbsp="" no="" pinzas="" porqueno="" si="" tensi="">    t4=-4;c=-1; 
    digitalWrite(13, LOW);  }
    else {
   delay(130);}  //Pausa
}

martes, 6 de diciembre de 2016

Cronotermostato de calefacción con arduino mega.

Termostato básico para calefacción con arduino mega, tft 2.4'' y 3 sondas de temperatura por cable. Como modulo de reloj he usado un zs-d42.
(Para la calibración de la temperatura he utilizado código de calibracion temperatura según Sketch de David Losada, basado en trabajos de Rafael Torrales y Antonio Moles.) 
 Supondo que sería más facil usar componentes dedicados, pero  teníalas sondas por casa y cuando me dí cuenta ya las estaba utilizando.  :)

Para hacer funcionar de la tft me he basado en el texto y codigo de esta página y las librerías Adafruit_TFTLCD, Adafruit_GFX y TouchScreen.
 Para controlar el modulo de reloj hace falta las librerías  Wire ( Comunicación I2C) y RTClib (Librería modulo reloj )
 En mi pantalla ftf los ejemplos aportados por estas librerías dieron algún problema de orientación, que pude solucionar facilmente cambiando el valor de tft.rotation()

El accionamiento es mediante optoacoplador, que deberá ser adecuado a la tensión e intensidad que vienen de la caldera. En mi caso han sido 18V y 7mA. Es necesario respetar la polaridad en las entradas del optoacoplador para que funcione

Una de las opciones es que muestra una gráfica  con las temperaturas de las últimas 26 horas, dispone de  una alarma que suena si la temperatura del sensor nº2 baja de 1ºC (para la habitación donde está la caldera )
También lleva tres led, uno indica que esta funcionando, otro que el circuito de la caldera está cerrado y por ultimo uno azul que indica que la sonda 3 ( exterior) esta a 0ºC o menos, osea que en la calle está helando.
Lo he testado con mi caldera de gas y funciona perfectamente, esto es para termostatos que cierran el circuito y la caldera se pone en  funcionamiento. 








Aspecto general del montaje.
( Al tocar en la pantalla se pasa al menú.)



 Menú principal con las principales funciones.
( Si no se toca nada a los pocos segundos vuelve a mostrar las temperaturas, los leds de la derecha son encendido, calefacción en funcionamiento y azul de heladas.)


Programación del programador.
(Pulsando sobre la hora se regresa al menú principal.)


Menu de ajuste de la hora de apagado.
( Con las flechas de sube y baja, al pulsar sobre las cifras se acepta.)


Fijación de la temperatura del termostato.
(pulsando sobre la cifra queda ajustado y se regresa al menú principal.)




Modulo de reloj.


Grafica de las temperaturas en las últimas 26 horas. 











Descargar Sketch.




/*  ===============================================================
Cronotermostato arduino mega, ds-1307 y tft 24 pulgadas.

    ==================================================================   */


// *** SPFD5408 change -- Begin
#include     // Core graphics library
#include // Hardware-specific library
#include
// *** SPFD5408 change -- End

#include // Comunicación I2C
#include "RTClib.h" // Librería modulo reloj

RTC_DS1307 RTC;
#if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

//Puertas de lectura del TFT
#define YP A1
#define XM A2
#define YM 7
#define XP 6
 
#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

 

#define YP A1  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 6   // can be a digital pin

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
// optional
#define LCD_RESET A4

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
 
//Colores
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
 
  Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
 
//Calibracion temperatura según Sketch de David Losada, basado en trabajos de Rafael Torrales y Antonio Moles.

//Para ahorrar cálculos, lo vamos a calcular antes del programa
const float TPto1 = -12; //Temperatura en ºC punto 1
const float RPto1 = 69200; // Ohms en punto 1
const float TPto2 = 33.5; // Temp. punto 2
const float RPto2 = 7270; // Ohms en punto 2
const float resistor = 8120; //El valor en ohmnios de la resistencia del termistor a 25ºC
const float voltage = 4.93; // El voltaje real en el punto 5Vcc de tu placa Arduino
//Para ahorrar cálculos lo definimos como constante en esta parte del programa
const float K = 273.15; //Para pasar a grados Kelvin
const float e = 2.718281828459045; //Constante matemática
const float B = log(RPto2 / RPto1) / (1 / (TPto2 + K) - (1 / (TPto1 + K))); //Valor Beta de tu termistor
const float unodivr = 1 / (resistor * pow(e, (-B / 298.15))); //Con pow elevamos e al resultado

unsigned long inicio;// control del tiempo



   byte optoac=2;// Modo: encendido, apagado, cronotermostato
  String texto="Apagado.";

float T[3] = {0}; //Declaramos la variable Temperatura
float tmedia[3] = {0}; //Variable para calcular media
int cnt; //temperatura media y contador

short tp1[320]; // almacen de temperaturas1 para grafico
short tp2[320]; // almacen de temperaturas2 para grafico
short tp3[320]; // almacen de temperaturas3 para grafico
int tp; // puntero almacet Tª
int tpp;

float termostato=21.0; // Temperatura del termostato a 21ºC

char enl;

byte ho=12; byte mi=0; byte hof=12; byte mif=0; // Horas/minutos/ duracion del temporizador

void setup()   {

Wire.begin(); // Inicia el puerto I2C
RTC.begin(); // Inicia la comunicación con el RTC
RTC.adjust(DateTime(__DATE__, __TIME__)); // Establece la fecha y hora
 
  // Iniciamos comunicacion serie con pantalla     
  Serial.begin(9600);

pinMode(45, OUTPUT); // Preparar salida audio pin 45
pinMode(38, OUTPUT); // Salida  optoacoplador y led amarillo 2
pinMode(36,OUTPUT);  digitalWrite(36, HIGH);// Led de encendido
pinMode(34,OUTPUT); // LED AZUL DE HELADAS SENSOR 3
  //
  tft.reset();
  uint16_t identifier = tft.readID();
  Serial.print(F("LCD driver chip: "));
  Serial.println(identifier, HEX);
  tft.begin(identifier);
  tft.fillScreen(BLACK);
  pinMode(13, OUTPUT);
  
  inicio = millis();
 
}

#define MINPRESSURE 100
#define MAXPRESSURE 1000

void loop()
{

  // Selecciona la entrada para el termistor
 
  int sensorValue[3]; // Aqui almacenamos el valor de las sondas
  byte sonda; // sondas
   
  // Parte 1:  Leemos el puerto analógico 0 y convertimos el valor en voltios.
  sensorValue[0] = analogRead(A13); //Leemos analógico 0
  sensorValue[1] = analogRead(A14); //Leemos analógico 1
  sensorValue[2] = analogRead(A15); //Leemos analógico 2

  // medimos la temperatura 10 veces y la almacenamos en tmedia
  for ( cnt = 0; cnt < 10; cnt++)
  {
    sensorValue[0] = analogRead(A13); //Leemos analógico 0
    sensorValue[1] = analogRead(A14); //Leemos analógico 1
    sensorValue[2] = analogRead(A15); //Leemos analógico 2

    tmedia[0] = tmedia[0] + sensorValue[0];
    tmedia[1] = tmedia[1] + sensorValue[1];
    tmedia[2] = tmedia[2] + sensorValue[2];

  }

  for (sonda = 0; sonda < 3; sonda = sonda + 1) { // Bucle para las tres sondas

    // calculamos la media de las medidas
    tmedia[sonda] = tmedia[sonda] / 10;

    //Convertimos a voltios :)
    float v2 = (voltage * float(tmedia[sonda])) / 1024.0f;

    tmedia[sonda] = 0; // limpiamos la variable

    // Parte 2: Calcular la resistencia con el valor de los voltios mediante la ecuación del divisor de voltaje
    //voltage = 4.83
    //R2 = 10000
    //R1 = Thermistor resistance
    //V2= v2
    //so V2=(R2*V)/(R1+R2)
    //and r1=((r2*v)/v2)-r2 <--final br="">
    float r1a = (voltage * float(resistor)) / v2;
    float r1 = r1a - resistor;


    //Parte 3: Calcular la temperatura basandose en la ecuación Steinhart-Hart y la ecuación del valor Beta.
    // T=B/ln(r1/rinfinit)


    T[sonda] = int((10*((B / log(r1 * unodivr)) - 273.15))); T[sonda]=T[sonda]/10; //Convertimos a ºC y ya tenemos la temperatura


  } // Fin for sondas

  if ( millis() - inicio > 300000 ) { // ciclo muestreo datos cada 5 minutos (300000)
    inicio = millis();

      tp=tp+1;
      if (tp>=320){ tp=0;}

    for (sonda = 0; sonda < 3; sonda = sonda + 1) {
     
      // Almacenaje temperaturas
      if (sonda==0){
        tp1[tp]=T[sonda]*100;
      }
     
      if (sonda==1){
        tp2[tp]=T[sonda]*100;
      }
     
      if (sonda==2){
        tp3[tp]=T[sonda]*100;
      }
        }     
  } // Fin del if

        temp(); //Mostrar temperaturas en el tft

if (optoac==1){    // Encendido apagado calefacc´on. Comprobar SOLO termostato
  if (T[0]<=(termostato-0.5)){  // Activar   
  digitalWrite(38, HIGH);
  }
    if (T[0]>(termostato+0.2)){// Desactivar     
  digitalWrite(38, LOW);
   }
}
   if (optoac==3){    // Encendido apagado calefacc´on. Comprobar RELOJ Y termostato
      DateTime now = RTC.now(); // Obtiene la fecha y hora del RTC
    Serial.println(hof-now.hour());
      if (hof*100+mif>=ho*100+mi){    // hora final mayor que hora inicial
        Serial.println("+");
        if ((T[0]<=(termostato-0.5)) && (now.hour()*100+now.minute()>=ho*100+mi) && (now.hour()*100+now.minute()<=hof*100+mif)){  // Activar   
        digitalWrite(38, HIGH);
        Serial.println("On");
        }
          if ((T[0]>(termostato+0.2)) || (now.hour()*100+now.minute()>hof*100+mif) || (now.hour()*100+now.minute()        digitalWrite(38, LOW);
        Serial.println("Off");
         }
        }
          if (hof*100+mif            Serial.println("-");
           
        if ((T[0]<=(termostato-0.5)) && ((now.hour()*100+now.minute()<=hof*100+mif)|| (now.hour()*100+now.minute()>=ho*100+mi))) {  // Activar   
        digitalWrite(38, HIGH);
        Serial.println("On");
        }
          if ((T[0]>(termostato+0.2)) || ((now.hour()*100+now.minute()>hof*100+mif) &&  (now.hour()*100+now.minute()        digitalWrite(38, LOW);
        Serial.println("Off");
         }
        }
 
  }  // fin  if pulsacionn 


if (T[1]<1 -galer="" 1000="" 1500="" a="" alarma="" br="" de="" en="" helada="" nbsp="" t="" tone="">if (T[2]<0 azul="" br="" encender="" led="" nbsp="">  digitalWrite(34, HIGH);}
  else{digitalWrite(34, LOW);}//  Apagar led azul
       
}  // FIN LOOP


  ////////        MOSTRAR MENU PRINCIPAL
void MenuP()
{
byte esquinax;
int ciclo;

//  digitalWrite(13, HIGH);
//  digitalWrite(13, LOW);
    pinMode(XM, OUTPUT); //Pins configures again for TFT control
    pinMode(YP, OUTPUT);
TSPoint p;

  //Texto botoes
  tft.fillScreen(BLACK);
   tft.setRotation(1);
  tft.setTextSize(3);
  tft.setCursor(90, 20);
  tft.setTextColor(YELLOW);
  tft.println("Temporizador");
  tft.setCursor(90, 80);
  tft.setTextColor(GREEN);
  tft.println("Grafica");
  tft.setCursor(90, 140);
  tft.setTextColor(CYAN);
  tft.println(texto);
  tft.setTextColor(WHITE);
  tft.setCursor(90, 200);
  tft.print("Termostato");
    tft.setRotation(0);

//  triangulos
  for (esquinax=25; esquinax<200 esquinax="esquinax+60){<br"> tft.fillTriangle(esquinax+7, 5, esquinax, 75, esquinax-7, 5, (RED));
}
 tft.fillTriangle(200, 5, 213, 5,206 ,75, (RED));

 //Menu principal

  for (ciclo=0; ciclo<10000 br="" ciclo="">      p = ts.getPoint();
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
  {
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));

   tone (45, 300, 180);
    // PULSACIÓN
   
       if (p.y <70 br="" temporizador="">       {
        tempor();
        ciclo=10000;
              }
             
       else if (p.y <140 amp="" p.y=""> 70)         //Testar grafica
       {        
         lecturaD();
        ciclo=10000;
                }
               
       else if (p.y < 210 & p.y >140)            // On/off/Temporizado
       {
         enc();   
       }
      
       else if (p.y >210)        //Fija la temperatura del termostato
       {
       termost();
       ciclo=10000;
         }
  }
}// fin for ciclo
}


//                Mostrar temperatura en tft
void temp() {
  char temp[2]; 
  byte num;
 
    pinMode(XM, OUTPUT); //Pins configures again for TFT control
    pinMode(YP, OUTPUT);

     tft.fillScreen(BLACK);
   tft.setRotation(1);
  
 // Mostrar Tª Habitación
  tft.setTextSize(7);
  tft.setTextColor(WHITE);          
 //tft.fillRect(10, 0, 309,104, BLACK);
  tft.setCursor(20, 15);
   tft.print(T[0]);
  tft.println("C");
 
 tft.setTextSize(3);
  tft.setCursor(60,90);
  tft.setTextColor(WHITE);
  tft.println("Habitacion");


 // Mostrar Tª galeria
 tft.setTextSize(3);
  tft.setTextColor(YELLOW);
//  tft.fillRect(20, 160, 159,49, BLACK);
  tft.setCursor(10, 160);    

   tft.print(T[1]);         
  tft.println("C");

   tft.setTextSize(2);
  tft.setCursor(25, 200);
  tft.setTextColor(YELLOW);
  tft.println("Galeria");


 // Mostrar Tª exterior
 tft.setTextSize(3);
  tft.setTextColor(CYAN); 
  tft.setCursor(180, 160);      

   tft.print(T[2]);         
  tft.println("C");

    tft.setTextSize(2);
  tft.setCursor(190, 200);
  tft.setTextColor(CYAN);
  tft.println("Exterior");
  
waitOneTouch();

}


void lecturaD() {// Hacer grafica de temperaturas
   
short mx; //Maximo
short mn; //Minimo
float escala;

int x1;

    pinMode(XM, OUTPUT); //Pins configures again for TFT control
    pinMode(YP, OUTPUT);


  tft.setRotation(3);
   tft.fillScreen(BLACK);
       tft.setTextSize(2);
      
    mx=int(tp1[1]);      mn=int(tp1[1]); //Define máximos y mínimos

   for (tpp =0; tpp < 320; tpp = tpp+ 1) {          //Registro máximos y mínimos
    mx=max(mx,tp1[tpp]);    mn=min(mn,tp1[tpp]);
    mx=max(mx,tp2[tpp]);    mn=min(mn,tp2[tpp]);
    mx=max(mx,tp3[tpp]);    mn=min(mn,tp3[tpp]);
   }
   mx=mx+100;
if (mn>0){ mn=0; }
else {mn=mn-100;}

escala= 240/(float(mx)-float(mn)); // =240/(mx-mn)/100, alto/100

// dibujar escala
tft.setCursor(300,(0-mn)*(escala));
 tft.setTextSize(2);
  tft.setTextColor(RED);
  tft.println("0");
tft.drawFastHLine(0,((0-mn)*(escala)) , 319, RED); // Dibuja linea 0º

 for (x1=24; x1<= 288; x1 =x1+24) { tft.drawFastVLine(x1,0 , 239, GREEN);} // linea vertical cada 2H


 for (x1=-2500; x1<= 4500; x1 =x1+500) {                  // linea horizontal cada 5º
 if (x1!=0) {
   tft.setRotation(3);
  tft.drawFastHLine(0,((x1-mn)*(escala)), 319, BLUE);
 tft.setRotation(1);
 tft.setCursor(2,240-(x1-mn)*(escala)); // escribir graduación
  tft.setTextColor(BLUE);
  tft.println(x1/100);
 }
 }

 tft.setRotation(3);

   for (tpp =tp+1; tpp < 320; tpp = tpp+ 1) {  // representar 1ª parte de datos

        tft.fillCircle(319-(tpp-tp),(tp1[tpp]-mn)*(escala),1, WHITE);
                tft.fillCircle(319-(tpp-tp),(tp2[tpp]-mn)*(escala),1, CYAN);
                        tft.fillCircle(319-(tpp-tp),(tp3[tpp]-mn)*(escala),1, YELLOW);
}

    for (tpp =0; tpp < tp; tpp = tpp+ 1) {   // representar 2ª parte de datos
       
    tft.fillCircle((tp-tpp),(tp1[tpp]-mn)*(escala), 1, WHITE);
    tft.fillCircle((tp-tpp),(tp2[tpp]-mn)*(escala), 1, CYAN);
    tft.fillCircle((tp-tpp),(tp3[tpp]-mn)*(escala), 1, YELLOW);
}
delay(4000);
   waitOneTouch();
}


// Esperar pulsación

void waitOneTouch() {
int ciclo;
   TSPoint p;
  
       pinMode(XM, OUTPUT); //Pins configures again for TFT control
    pinMode(YP, OUTPUT);

  for (ciclo=0; ciclo<4000 br="" ciclo="ciclo+1){  " pausa="">    p= ts.getPoint();
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE){ // Detectar Pulsacion pantalla
     tone (45, 200, 280);
     MenuP(); 
     ciclo=4000;  }
  }
}


// Boton Activar termostato/ desactivar

void enc()
{
switch (optoac) {
   case 1:   // APAGAR
      texto="APAGADO.";
      optoac=2;     
      digitalWrite(38,LOW);
      break;
     
   case 2:    //  FUNCIONAMIENTO TEMPORIZADO
      texto="TEMPORIZADO";
      optoac=3;
      digitalWrite(38,LOW);
      break;
     
   case 3:     // ENCENDER
       texto="ENCENDIDO.";
       optoac=1;
       break;
    }
    MenuP();
}


//  Menu Fijar temp. Termostato
void termost()
{
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);

   //Menu
  tft.fillScreen(BLACK);
   tft.setRotation(1);
  
  tft.setTextSize(3);
  tft.setCursor(50, 2);
  tft.setTextColor(WHITE);
  tft.println("Termostato:");
  tft.setTextSize(9);
  tft.setCursor(30, 40);
  tft.println(termostato);
 
  tft.setTextSize(5);
  tft.setCursor(110, 140);
  tft.setTextColor(RED);
  tft.println("Subir");
  tft.setTextColor(CYAN);
  tft.setCursor(110, 200);
  tft.print("Bajar");
    tft.setRotation(0);

//  flechas
 tft.fillTriangle(70,22, 100, 57, 70,92, (RED));
 tft.fillTriangle(35, 22, 5, 57, 35, 92, (CYAN));

   termost2();
}

 
void termost2()
{  //  Captura de pulsación para fijar termostato
  int ciclo;
   TSPoint p;
  
  for (ciclo=0; ciclo<4000 br="" ciclo="ciclo+1){  " pausa="">   p = ts.getPoint();
 
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
  {
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
  
   tone (45, 400, 180);
  
      if (p.y <170 br="" de="" fija="" sale="" termostato="" y="">         {

           ciclo=4000;// volver al loop
                }
               
         else if (p.y <256 amp="" p.y=""> 170)  // Sube temp. termostato
         {
               if (termostato<28 termostato="termostato+0.2;}<br">               termost();
           ciclo=1000;
                  }
                 
         else if (p.y >256)    //Baja la temperatura del termostato
        
         {
           if (termostato>5) {termostato=termostato-0.2;}
           ciclo=1000;
           termost();
           }
    }
  }  // fin for ciclo
  tone (45, 400, 180);
}

void tempor(){                   // Menu TEMPORIZADOR
pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);

DateTime now = RTC.now(); // Obtiene la fecha y hora del RTC

   //Presentar hora
  tft.fillScreen(BLACK);
   tft.setRotation(1);

  tft.setTextSize(4);
  tft.setCursor(10, 10);
  tft.setTextColor(WHITE);
  tft.println("Hora:");
  tft.setTextSize(10);
  tft.setCursor(10, 60);
 
  if (now.hour()<10 br="" nbsp="" tft.print="">  tft.print(now.hour());// mostrar hora
  tft.print(':');
 
  if (now.minute()<10 br="" nbsp="" tft.print="">  tft.print(now.minute());//

 
 tft.fillRect(10,170, 300,59,(YELLOW));// BOTON
  tft.setTextSize(3);
  tft.setTextColor(BLACK);
  tft.setCursor(20, 190);
  tft.print("AJUSTAR COMIENZO.");
    tft.setRotation(0);

tempor2(); // Recepcion tactil
}

void tempor2()
{  //                   Ajusta la programación del temporizador
  int ciclo;
   TSPoint p;
  
  for (ciclo=0; ciclo<4000 br="" ciclo="ciclo+1){  " pausa="">   p = ts.getPoint();
 
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
  {
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
  
   tone (45, 400, 180);
  
      if (p.y <160 br="" del="" reloj="" sale="">         {

           ciclo=4000;// volver al loop
                }
               
         else if ( p.y > 160)  // Entra en ajustes
         {
             ajust();   // Ajustar hora comienzo
             ajust3(); // Ajustar hora final
           ciclo=1000;
                  }
                 
    }
  }  // fin for ciclo
  tone (45, 400, 180);
}


void ajust()
{   //                   Presenta hora:minutos y botones temporizador
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);

   //Menu
  tft.fillScreen(BLACK);
   tft.setRotation(1);
  
  tft.setTextSize(3);
  tft.setCursor(20, 2);
  tft.setTextColor(WHITE);
  tft.println("Hora comienzo:");
  tft.setTextSize(9);
  tft.setCursor(30, 40);

  if (ho<10 br="" nbsp="" tft.print="">  tft.print(ho);tft.print(':'); 
  if (mi<10 br="" mi="" nbsp="" tft.print=""> 
    tft.setRotation(0);
//  flechas izq
 tft.fillTriangle(70,52, 100, 87, 70,122, (RED));
 tft.fillTriangle(35, 52, 5, 87, 35, 122, (CYAN));
//  flechas dcha
 tft.fillTriangle(70,200, 100, 235, 70,270, (RED));
 tft.fillTriangle(35,200, 5,235, 35, 270, (CYAN));

   ajust2();
}

void ajust2()
{  //  Captura de pulsación para fijar hora de comienzo en el termostato
  int ciclo;
   TSPoint p;
  
  for (ciclo=0; ciclo<5000 br="" ciclo="ciclo+1){  " pausa="">
   p = ts.getPoint();
 
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
  {
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
  
   tone (45, 400, 80);

   if (p.x>160){  //  Ajustar hora de comienzo
      if (p.y <160 br="" de="" fija="" sale="" termostato="" y="">         {
           ciclo=5000;// volver al loop
                }
               
         else if (p.y <240 amp="" p.y=""> 160)  // AUMENTAR
         {
                    ho=ho+1;
               if (ho==24) {ho=0;}
           ajust();
                  }
                 
         else if (p.y >240)    //DISMINUIR
        
         {
           if (ho==0) {ho=23;}
           else
           {ho=ho-1;}
               ajust();         
           }
   } // fin hora
   if (p.x<159 ajustar="" br="" minutos="" nbsp="">      if (p.y <160 br="" de="" fija="" sale="" termostato="" y="">         {
           ciclo=5000;// volver al loop
                }
               
         else if (p.y <240 amp="" p.y=""> 160)  // AUMENTAR
         {
                    mi=mi+15;
               if (mi==60) {mi=0;}
           ajust();
                  }
                 
         else if (p.y >240)    //DISMINUIR
        
         {
           if (mi==0) {mi=45;}
           else
           {mi=mi-15;}
               ajust();         
           }
   } // fin minutos
    }
  }  // fin for ciclo
}


void ajust3()
{   //                   Presenta hora:minutos y botones temporizador finalización
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);

   //Menu
  tft.fillScreen(BLACK);
   tft.setRotation(1);
  
  tft.setTextSize(3);
  tft.setCursor(20, 2);
  tft.setTextColor(YELLOW);
  tft.println("Hora apagado:");
  tft.setTextSize(9);
  tft.setCursor(30, 40);

  if (hof<10 br="" nbsp="" tft.print="">  tft.print(hof);tft.print(':'); 
  if (mif<10 br="" mif="" nbsp="" tft.print=""> 
    tft.setRotation(0);
//  flechas izq
 tft.fillTriangle(70,52, 100, 87, 70,122, (RED));
 tft.fillTriangle(35, 52, 5, 87, 35, 122, (CYAN));
//  flechas dcha
 tft.fillTriangle(70,200, 100, 235, 70,270, (RED));
 tft.fillTriangle(35,200, 5,235, 35, 270, (CYAN));

   ajust4();
}

void ajust4()
{  //  Captura de pulsación para fijar hora de comienzo en el termostato
  int ciclo;
   TSPoint p;
  
  for (ciclo=0; ciclo<5000 br="" ciclo="ciclo+1){  " pausa="">
   p = ts.getPoint();
 
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
  {
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
  
   tone (45, 400, 80);

   if (p.x>160){  //  Ajustar hora de comienzo
      if (p.y <160 br="" de="" fija="" sale="" termostato="" y="">         {
           ciclo=5000;// volver al loop
                }
               
         else if (p.y <240 amp="" p.y=""> 160)  // AUMENTAR
         {
                    hof=hof+1;
               if (hof==24) {hof=0;}
           ajust3();
                  }
                 
         else if (p.y >240)    //DISMINUIR
        
         {
           if (hof==0) {hof=23;}
           else
           {hof=hof-1;}
               ajust3();         
           }
   } // fin hora
  
   if (p.x<159 ajustar="" br="" finalizacion="" minutos="" nbsp="">      if (p.y <160 br="" de="" fija="" sale="" termostato="" y="">         {
           ciclo=5000;// volver al loop
                }
               
         else if (p.y <240 amp="" p.y=""> 160)  // AUMENTAR
         {
                    mif=mif+15;
               if (mif==60) {mif=0;}
           ajust3();
                  }
                 
         else if (p.y >240)    //DISMINUIR
        
         {
           if (mif==0) {mif=45;}
           else
           {mif=mif-15;}
               ajust3();         
           }
   } // fin minutos
    }
  }  // fin for ciclo
}

////       FIN DEL SKETCH

////

miércoles, 23 de noviembre de 2016

Termostato de calefacción con Arduino Mega y 2.4'' TFT

Termostato básico para calefacción con arduino mega, tft 2.4'' y 3 sondas de temperatura por cable.
(Para la calibración de la temperatura he utilizado código de calibracion temperatura según Sketch de David Losada, basado en trabajos de Rafael Torrales y Antonio Moles.)  Supondo que sería más facil usar componentes dedicados, pero  teníalas sondas por casa y cuando me dí cuenta ya las estaba utilizando.  :)

Para el funcionamiento de la tft me he basado en el texto y codigo de esta página y las librerías Adafruit_TFTLCD, Adafruit_GFX y TouchScreen.
 En mi pantalla ftf los ejemplos aportados por estas librerías dieron algún problema de orientación, que pude solucionar facilmente cambiando el valor de tft.rotation()

El accionamiento es mediante optoacoplador, que deberá ser adecuado a la tensión e intensidad que vienen de la caldera. En mi caso han sido 18V y 7mA. Es necesario respetar la polaridad en las entradas del optoacoplador. 

Muestra una gráfica  con las temperaturas de las últimas 26 horas, dispone de  una alarma que suena si la temperatura del sensor nº2 baja de 1ºC (para la habitación donde está la caldera )

En esta página muestro la versión con temporizador.

Descargar  sketch











Aspecto general.






                                           Sondas de temperatura.






Menú ptrincipal.







                         Fijando la temperatura de disparo.





 Gráfica de temperaturas








Código:



/*  ===============================================================
Termostato Arduino Mega y tft 2.4''
    ==================================================================   */

//#include

// *** SPFD5408 change -- Begin
#include     // Core graphics library
#include // Hardware-specific library
#include
// *** SPFD5408 change -- End


#if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

//Puertas de lectura del TFT
#define YP A1
#define XM A2
#define YM 7
#define XP 6
 
#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

 

#define YP A1  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 6   // can be a digital pin

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
// optional
#define LCD_RESET A4

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
 
//Colores
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
 
  Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
 
//Calibracion temperatura según Sketch de David Losada, basado en trabajos de Rafael Torrales y Antonio Moles.

//Para ahorrar cálculos, lo vamos a calcular antes del programa
const float TPto1 = -12; //Temperatura en ºC punto 1
const float RPto1 = 69200; // Ohms en punto 1
const float TPto2 = 33.5; // Temp. punto 2
const float RPto2 = 7270; // Ohms en punto 2
const float resistor = 8120; //El valor en ohmnios de la resistencia del termistor a 25ºC
const float voltage = 4.93; // El voltaje real en el punto 5Vcc de tu placa Arduino
//Para ahorrar cálculos lo definimos como constante en esta parte del programa
const float K = 273.15; //Para pasar a grados Kelvin
const float e = 2.718281828459045; //Constante matemática
const float B = log(RPto2 / RPto1) / (1 / (TPto2 + K) - (1 / (TPto1 + K))); //Valor Beta de tu termistor
const float unodivr = 1 / (resistor * pow(e, (-B / 298.15))); //Con pow elevamos e al resultado

unsigned long inicio;// control del tiempo



   bool optoac=0;
  String texto="Encender";

float T[3] = {0}; //Declaramos la variable Temperatura
float tmedia[3] = {0}; //Variable para calcular media
int cnt; //temperatura media y contador

short tp1[320]; // almacen de temperaturas1 para grafico
short tp2[320]; // almacen de temperaturas2 para grafico
short tp3[320]; // almacen de temperaturas3 para grafico
int tp; // puntero almacet Tª
int tpp;

float termostato=21.0; // Temperatura del termostato a 21ºC

char enl;

void setup()   {
  // Iniciamos comunicacion serie con pantalla     
  Serial.begin(9600);

pinMode(45, OUTPUT); // Preparar salida audio pin 45
pinMode(38, OUTPUT); // Salida  optoacoplador
  //
  tft.reset();
  uint16_t identifier = tft.readID();
  Serial.print(F("LCD driver chip: "));
  Serial.println(identifier, HEX);
  tft.begin(identifier);
  tft.fillScreen(BLACK);
  pinMode(13, OUTPUT);
  
  inicio = millis();
 
}

#define MINPRESSURE 100
#define MAXPRESSURE 1000

void loop()
{

  // Selecciona la entrada para el termistor
 
  int sensorValue[3]; // Aqui almacenamos el valor de las sondas
  byte sonda; // sondas
   
  // Parte 1:  Leemos el puerto analógico 0 y convertimos el valor en voltios.
  sensorValue[0] = analogRead(A13); //Leemos analógico 0
  sensorValue[1] = analogRead(A14); //Leemos analógico 1
  sensorValue[2] = analogRead(A15); //Leemos analógico 2

  // medimos la temperatura 10 veces y la almacenamos en tmedia
  for ( cnt = 0; cnt < 10; cnt++)
  {
    sensorValue[0] = analogRead(A13); //Leemos analógico 0
    sensorValue[1] = analogRead(A14); //Leemos analógico 1
    sensorValue[2] = analogRead(A15); //Leemos analógico 2

    tmedia[0] = tmedia[0] + sensorValue[0];
    tmedia[1] = tmedia[1] + sensorValue[1];
    tmedia[2] = tmedia[2] + sensorValue[2];

  }

  for (sonda = 0; sonda < 3; sonda = sonda + 1) { // Bucle para las tres sondas

    // calculamos la media de las medidas
    tmedia[sonda] = tmedia[sonda] / 10;

    //Convertimos a voltios :)
    float v2 = (voltage * float(tmedia[sonda])) / 1024.0f;

    tmedia[sonda] = 0; // limpiamos la variable

    // Parte 2: Calcular la resistencia con el valor de los voltios mediante la ecuación del divisor de voltaje
    //voltage = 4.83
    //R2 = 10000
    //R1 = Thermistor resistance
    //V2= v2
    //so V2=(R2*V)/(R1+R2)
    //and r1=((r2*v)/v2)-r2 <--final br="">
    float r1a = (voltage * float(resistor)) / v2;
    float r1 = r1a - resistor;


    //Parte 3: Calcular la temperatura basandose en la ecuación Steinhart-Hart y la ecuación del valor Beta.
    // T=B/ln(r1/rinfinit)


    T[sonda] = int((10*((B / log(r1 * unodivr)) - 273.15))); T[sonda]=T[sonda]/10; //Convertimos a ºC y ya tenemos la temperatura


  } // Fin for sondas

  if ( millis() - inicio > 300000 ) { // ciclo muestreo datos cada 5 minutos (300000)
    inicio = millis();

      tp=tp+1;
      if (tp>=320){ tp=0;}

    for (sonda = 0; sonda < 3; sonda = sonda + 1) {
     
      // Almacenaje temperaturas
      if (sonda==0){
        tp1[tp]=T[sonda]*100;
      }
     
      if (sonda==1){
        tp2[tp]=T[sonda]*100;
      }
     
      if (sonda==2){
        tp3[tp]=T[sonda]*100;
      }
        }     
  } // Fin del if

        temp(); //Mostrar temperaturas en el tft

if (optoac==1){    // Encendido apagado calefacc´on. Comprobar termostato
  if (T[0]<=(termostato-0.5)){  // Activar   
  digitalWrite(38, HIGH);
  }
 
    if (T[0]>(termostato+0.2)){// Desactivar     
  digitalWrite(38, LOW);
   }
  }  // fin  if pulsacionn 


if (T[1]<1 -galer="" 1000="" 1500="" a="" alarma="" br="" de="" en="" helada="" nbsp="" t="" tone="">       
}  // FIN LOOP


  ////////        MOSTRAR MENU PRINCIPAL
void MenuP()
{
byte esquinax;
int ciclo;

//  digitalWrite(13, HIGH);
//  digitalWrite(13, LOW);
    pinMode(XM, OUTPUT); //Pins configures again for TFT control
    pinMode(YP, OUTPUT);
TSPoint p;

  //Texto botoes
  tft.fillScreen(BLACK);
   tft.setRotation(1);
  tft.setTextSize(3);
  tft.setCursor(90, 20);
  tft.setTextColor(YELLOW);
  tft.println("Temperatura");
  tft.setCursor(90, 80);
  tft.setTextColor(GREEN);
  tft.println("Grafica");
  tft.setCursor(90, 140);
  tft.setTextColor(CYAN);
  tft.println(texto);
  tft.setTextColor(WHITE);
  tft.setCursor(90, 200);
  tft.print("Termostato");
    tft.setRotation(0);

//  triangulos
  for (esquinax=25; esquinax<200 esquinax="esquinax+60){<br"> tft.fillTriangle(esquinax+7, 5, esquinax, 75, esquinax-7, 5, (RED));
}
 tft.fillTriangle(200, 5, 213, 5,206 ,75, (RED));

 //Menu principal

  for (ciclo=0; ciclo<10000 br="" ciclo="">      p = ts.getPoint();
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
  {
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));

   tone (45, 400, 180);
    // PULSACIÓN
   
       if (p.y <70 br="" temperatura="" testar="">       {
        temp();
              }
             
       else if (p.y <140 amp="" p.y=""> 70)         //Testar grafica
       {        
         lecturaD();
                }
               
       else if (p.y < 210 & p.y >140)            // On/off 
       {
         enc();       
       }
      
       else if (p.y >210)        //Fija la temperatura del termostato
       {
       termost();
       ciclo=10000;
         }
  }
}// fin for ciclo
}


//                Mostrar temperatura en tft
void temp() {
  char temp[2]; 
  byte num;
 
    pinMode(XM, OUTPUT); //Pins configures again for TFT control
    pinMode(YP, OUTPUT);

     tft.fillScreen(BLACK);
   tft.setRotation(1);
  
 // Mostrar Tª Habitación
  tft.setTextSize(7);
  tft.setTextColor(WHITE);          
 //tft.fillRect(10, 0, 309,104, BLACK);
  tft.setCursor(20, 15);
   tft.print(T[0]);
  tft.println("C");
 
 tft.setTextSize(3);
  tft.setCursor(60,90);
  tft.setTextColor(WHITE);
  tft.println("Habitacion");


 // Mostrar Tª galeria
 tft.setTextSize(3);
  tft.setTextColor(YELLOW);
//  tft.fillRect(20, 160, 159,49, BLACK);
  tft.setCursor(10, 160);    

   tft.print(T[1]);         
  tft.println("C");

   tft.setTextSize(2);
  tft.setCursor(25, 200);
  tft.setTextColor(YELLOW);
  tft.println("Galeria");


 // Mostrar Tª exterior
 tft.setTextSize(3);
  tft.setTextColor(CYAN); 
  tft.setCursor(180, 160);      

   tft.print(T[2]);         
  tft.println("C");

    tft.setTextSize(2);
  tft.setCursor(190, 200);
  tft.setTextColor(CYAN);
  tft.println("Exterior");
  
waitOneTouch();

}


void lecturaD() {// Hacer grafica de temperaturas
   
short mx; //Maximo
short mn; //Minimo
float escala;

int x1;

    pinMode(XM, OUTPUT); //Pins configures again for TFT control
    pinMode(YP, OUTPUT);


  tft.setRotation(3);
   tft.fillScreen(BLACK);
       tft.setTextSize(2);
      
    mx=int(tp1[1]);      mn=int(tp1[1]); //Define máximos y mínimos

   for (tpp =0; tpp < 320; tpp = tpp+ 1) {          //Registro máximos y mínimos
    mx=max(mx,tp1[tpp]);    mn=min(mn,tp1[tpp]);
    mx=max(mx,tp2[tpp]);    mn=min(mn,tp2[tpp]);
    mx=max(mx,tp3[tpp]);    mn=min(mn,tp3[tpp]);
   }
   mx=mx+100;
if (mn>0){ mn=0; }
else {mn=mn-100;}

 //  mx=mx/100; mn=mn/100-1 ;
escala= 240/(float(mx)-float(mn)); // =240/(mx-mn)/100, alto/100

// dibujar escala
tft.setCursor(300,(0-mn)*(escala));
 tft.setTextSize(2);
  tft.setTextColor(RED);
  tft.println("0");
tft.drawFastHLine(0,((0-mn)*(escala)) , 319, RED); // Dibuja linea 0º

 for (x1=24; x1<= 288; x1 =x1+24) { tft.drawFastVLine(x1,0 , 239, GREEN);} // linea vertical cada 2H


 for (x1=-2500; x1<= 4500; x1 =x1+500) {                  // linea horizontal cada 5º
 if (x1!=0) {
   tft.setRotation(3);
  tft.drawFastHLine(0,((x1-mn)*(escala)), 319, BLUE);
 tft.setRotation(1);
 tft.setCursor(2,240-(x1-mn)*(escala)); // escribir graduación
  tft.setTextColor(BLUE);
  tft.println(x1/100);
 }
 }

 tft.setRotation(3);

   for (tpp =tp+1; tpp < 320; tpp = tpp+ 1) {  // representar 1ª parte de datos

        tft.fillCircle(319-(tpp-tp),(tp1[tpp]-mn)*(escala),1, WHITE);
                tft.fillCircle(319-(tpp-tp),(tp2[tpp]-mn)*(escala),1, CYAN);
                        tft.fillCircle(319-(tpp-tp),(tp3[tpp]-mn)*(escala),1, YELLOW);
}

    for (tpp =0; tpp < tp; tpp = tpp+ 1) {   // representar 2ª parte de datos
       
    tft.fillCircle((tp-tpp),(tp1[tpp]-mn)*(escala), 1, WHITE);
    tft.fillCircle((tp-tpp),(tp2[tpp]-mn)*(escala), 1, CYAN);
    tft.fillCircle((tp-tpp),(tp3[tpp]-mn)*(escala), 1, YELLOW);
}
delay(4000);
   waitOneTouch();
}


// Esperar pulsación

void waitOneTouch() {
int ciclo;
   TSPoint p;
  
       pinMode(XM, OUTPUT); //Pins configures again for TFT control
    pinMode(YP, OUTPUT);

  for (ciclo=0; ciclo<4000 br="" ciclo="ciclo+1){  " pausa="">    p= ts
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE){ // Detectar Pulsacion pantalla
     tone (45, 400, 180);
     MenuP(); 
     ciclo=4000;  }
  }
}


// Boton Activar termostato/ desactivar

void enc()
{
      if (optoac==0){
      texto="Apagar";
      optoac=1;
    }else{
      texto="Encender";
      optoac=0;
      digitalWrite(38,LOW);
    }
    MenuP();
}


//  Menu Fijar temp. Termostato
void termost()
{
////  digitalWrite(13, HIGH);
//  digitalWrite(13, LOW);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);

   //Menu
  tft.fillScreen(BLACK);
   tft.setRotation(1);
  
  tft.setTextSize(3);
  tft.setCursor(50, 2);
  tft.setTextColor(WHITE);
  tft.println("Termostato:");
  tft.setTextSize(9);
  tft.setCursor(30, 40);
  tft.println(termostato);
 
  tft.setTextSize(5);
  tft.setCursor(110, 140);
  tft.setTextColor(RED);
  tft.println("Subir");
  tft.setTextColor(CYAN);
  tft.setCursor(110, 200);
  tft.print("Bajar");
    tft.setRotation(0);

//  flechas
 tft.fillTriangle(70,22, 100, 57, 70,92, (RED));
 tft.fillTriangle(35, 22, 5, 57, 35, 92, (CYAN));

   termost2();
}

 
void termost2()
{  //  Captura de pulsación para fijar termostato
  int ciclo;
   TSPoint p;
  
  for (ciclo=0; ciclo<4000 br="" ciclo="ciclo+1){  " pausa="">  Serial.println(ciclo);
   p = ts.getPoint();
 
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
  {
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
  
   tone (45, 400, 180);
  
      if (p.y <170 br="" de="" fija="" sale="" termostato="" y="">         {
         // delay(300);
           ciclo=4000;// volver al loop
                }
               
         else if (p.y <256 amp="" p.y=""> 170)  // Sube temp. termostato
         {
               if (termostato<28 termostato="termostato+0.2;}<br">               termost();
           ciclo=1000;
                  }
                 
         else if (p.y >256)    //Baja la temperatura del termostato
        
         {
           if (termostato>5) {termostato=termostato-0.2;}
           ciclo=1000;
           termost();
           }
    }
  }  // fin for ciclo
  tone (45, 400, 180) 

<--final br="">} 

<--final br="">// Fin del  sketch
<--final br="">//