domingo, 18 de octubre de 2015

Termostato con Arduino y LM35

En esta entrada os dejo una aproximación a un termostato electrónico hecho con Arduino UNO y el LM35. El software y el hardware de este ejercicio didáctico pretende abrir puertas para que el curioso o estudiante pueda hacerse con facilidad en el diseño con estos elementos programables. En el datasheet del Display DMC16207 que usamos en esta práctica tenemos detallada su utilización, siendo imprescindible sólo conocer cómo tienen que ir vinculadas las patillas del display con las de Arduino. 

El circuito:
 * LCD RS (4) pin a digital pin 12 Arduino
 * LCD Enable (6) pin a digital pin 11 Arduino
 * LCD D4 (11) pin a digital pin 5 Arduino
 * LCD D5 (12) pin a digital pin 4 Arduino
 * LCD D6 (13) pin a digital pin 3 Arduino
 * LCD D7 (14) pin a digital pin 2 Arduino
 * LCD R/W (3) pin a ground (negativo) para escribir
 * Contraste Vee, pin 3 a GND para máximo contraste. No uso el habitual potenciómetro de contraste de 10K entre +5v y GND para disponer de regulación; la toma media iría a Vee.

En las tablas del esquema de la imagen anterior se aclara con detalle su vinculación.


El LM35 es un sensor de temperatura que tiene una pendiente de 10mV por grado Centígrado. Si la entrada analógica A0 de Arduino UNO tiene una sensibilidad de 5mV, ya que tiene una resolución de 10 bits (conversor A/D de 10 bits210 = 1024, Vref(5v) / 1024 = 5mV), el valor que tendremos en el registro de la entrada A0 para 25 ºC, por ejemplo, será el siguiente:

25 ºC x 10 mV/ºC (LM35) = 250 mV; 
250 mV / 5 mV (A0 Arduino) = 50;

Para poder disponer en el display del valor real de la temperatura tendremos que guardar el valor de A0 (50) en una variable y dividirla luego entre 2; así obtendremos 25 ºC. 
 
Ésta es la parte del software que recoge este tema:

valorSensor=analogRead(sensor);
termo=(valorSensor / 2);
La librería empleada para el display, así como el set de instrucciones para controlarlo es la que está disponible en el entorno IDE de Arduino.


FUNCIONAMIENTO:
El LM35 es un sensor de temperatura que proporciona a la entrada analógica del Arduino una tensión de 10mV por grado Centígrado. El pulsador de Modo abre el subprograma Temperatura() para ajustar con el pulsador Adj el umbral de conmutación del LED Rojo; así, si lo ajustamos a 21 grados, cuando supere ese valor el LED Rojo se apaga, pero si es inferior se enciende (simula el relé de un termostato de temperatura de ambiente). El valor por defecto es de 20 grados. En el programa se puede ver que disponemos de un ajuste entre 15 y 23 grados. Para ajustar el valor se pulsa Modo (pulsa1), y luego nos pide un valor que ajustaremos pulsando Adj (pulsa2); para validar ese valor sólo tenemos que pulsar Modo una vez más, quedando almacenado en la variable temp.
En el código del programa disponemos de los comentarios oportunos para percatarnos de su funcionamiento. Ese código os lo dejo aquí para que podáis copiar y pegar en el entorno IDE, debiendo luego funcionar sin problemas si el hardware usado es el mismo que el propuesto en el esquema anterior.

CÓDIGO DEL PROGRAMA TERMOSTATO:
/*
  LiquidCrystal Library - display() and noDisplay()

 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.

Thermostat by Nacho

 The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe
 modified 22 Nov 2010
 by Tom Igoe

 This example code is in the public domain.

 http://www.arduino.cc/en/Tutorial/LiquidCrystalDisplay

 */

// Incluir el código de la biblioteca:
#include <LiquidCrystal.h>

// Inicializa la biblioteca con las conexiones a los pins del interface Arduino:
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Patillas y variables globales

  int sensor=A0; // Sensor en entrada analógica pin A0
  int modo=6; // Pulsador de Modo pin 6
  int adj=7; //Pulsador de ajuste pin 7
  int led=1; // LED de salida pin 1
  float valorSensor=0; // Variable con el contenido de la entrada analógica A0
  float termo=0; // Variable con el valor real de temperatura
  int pulsa1=1;  // Variable con estado de pin 6
  int pulsa2=1;  // Variable con estado de pin 7
  float temp=20; // Variable de conmutación del relé (LED Rojo)

// Inicialización del programa
void setup() {
  // set up del número de columnas y líneas del Display:
  lcd.begin(16, 2);
  // Ajusta la posición inicial de impresión en el Display.
  lcd.setCursor(2, 0);
  // Columna 2 y línea 0, superior
  lcd.print("Nacho's Lab");
  lcd.setCursor(2, 1);
  // Columna 2 y línea 1, inferior
  lcd.print("Termostato");
  lcd.blink(); // Parpadeo de cursor
  delay(3000);

  pinMode(modo,INPUT);
  pinMode(adj,INPUT);
  pinMode(led,OUTPUT);
 
}

// Inicio

void loop() {

    pulsa1 = digitalRead(modo);
  if (pulsa1 == LOW){
      temperatura();
    }
    
  delay(1000);
 
  lcd.display(); // Enciende el display

  lcd.noBlink(); // Apaga parpadeo del cursor
  lcd.setCursor(2,0);
  lcd.print("Temperatura");
  valorSensor=analogRead(sensor);
  termo=(valorSensor / 2);
  lcd.setCursor(2, 1);
  lcd.print(termo);
  lcd.print(" grados   ");
  if (termo < temp){
    digitalWrite(led,HIGH);
  }
  if (termo > temp){
     digitalWrite(led,LOW);
  }
  
} //Fin


// Subprograma de temperatura

void temperatura(){ // Control de temperatura. Ajuste de umbral
    
        pulsa1=1;
    
        lcd.setCursor(1,1);           
        lcd.print(" Valor:");
        lcd.print(temp);
        lcd.blink();
      while(pulsa1 == HIGH) // Umbral de conmutación del relé (LED Rojo)
      {
        delay(500);
       
        pulsa1 = digitalRead(modo);
        pulsa2 = digitalRead(adj);
        if (pulsa2 == LOW){
          temp = temp + 0.5; // Incrementos de 0.5 grados
        }
        if (temp > 23){ // Entre 15 y 23 grados
          temp = 15;
        }
        lcd.setCursor(1,1);           
        lcd.print(" Valor:");
        lcd.print(temp);
        lcd.print("  ");
        lcd.blink();
      }
      lcd.setCursor(2,1);
      lcd.noBlink();
     
      lcd.print(temp);
      lcd.print(" grados");
      delay(1000);
      lcd.setCursor(1,1);
      lcd.print("      OK       ");
      delay(500);
     
} // Fin de código


En el siguiente vídeo podemos apreciar como funciona:

7 comentarios:

  1. el codigo funciona pero al desconectar el arduino no queda guardada la programacion

    ResponderEliminar
    Respuestas
    1. Hola. Gracias por interesarse por este blog. En el vídeo de la entrada se puede ver el funcionamiento del sistema con Arduino UNO, y el código está guardado en el dispositivo. Quizás esté usando un Arduino distinto, con direcciones de memoria que no coinciden con la memoria flash donde guarda el sketch ya compilado. En mi Arduino UNO lo guarda y ejecuta perfectamente. Un saludo

      Eliminar
  2. la temperatura programada laguarda en la memoria??

    ResponderEliminar
  3. la temperatura seleccionada se guarda en la memoria o hay que restituirla cada vvez que conectas el termostato??

    ResponderEliminar
    Respuestas
    1. Hola Antonio: Gracias por interesarte por este blog. Mientras no desconectes la alimentación, la variable temp mantiene la temperatura ajustada manualmente; cuando desconectas el circuito, la variable temp asume su valor por defecto de 20 grados. Un saludo

      Eliminar
  4. como pudieras agregar tiempo de encendido

    ResponderEliminar
    Respuestas
    1. Gracias por el comentario. Entiendo que es añadir tiempo para mantener encendido el LED. A priori, yo le añadiría un delay para prolongar el tiempo de encendido independientemente de que la temperatura alcanzar el valor establecido. Por ejemplo:
      if (termo < temp){
      digitalWrite(led,HIGH);
      delay(1000);
      }
      Cada delay(1000) equivale a un segundo, (2000) 2 segundor, etc.
      Un saludo

      Eliminar