bclose

Sensor de temperatura y ventilador

Ejemplo sencillo de control de temperatura

Objetivos

 

 

    • Unir un sensor de temperatura y un ventilador.
    • Calculando la temperatura con float.
    • Usando el ventilador para disminuir la temperatura.
    • Ilustrar la idea de un buffer circular

 

Material requerido.

ArduinoUNOArduino Uno o similarEsta sesión acepta cualquier otro modelo.
Img_3_4Img_3_6Una Protoboard más cables.

Img_3_5
Un diodo LED y una resistencia de 330Ω.
2N2222Un transistor 2N2222. Comprobad que lleva rotulada esta referencia, porque el sensor de temperatura es similar.
Motor CC Un ventilador de 5V o un motor de corriente continua.
Sensor de temperaturaUn Sensor de temperatura LM35DZ o similar.Comprobad que lleva rotulada esta referencia, porque es fácil confundirlo con un transistor.

 

Un circuito con sensor y actuador

 

Hemos ido viendo hasta ahora como utilizar un sensor de temperatura y también como usar un pequeño transistor para mover un motor de CC, pero no los habíamos mezclado.

En esta sesión haremos un pequeño ejemplo de control, usando un sensor LM35DZ para determinar la temperatura y un ventilador de 5V, para que cuando la primera alcance un valor crítico, usemos el segundo a fin refrigerar el circuito.

Como no disponemos de ningún sistema a refrigerar, nos conformaremos con enfriar el propio sensor, lo que no resulta especialmente provechoso, pero sin duda, nos servirá para mostraros un ejemplo de control y reacción, en el mejor espíritu de un sistema automático, tal como un regulador de temperatura con nuestros Duinos.

Veremos que la regulación de un sistema tan sencillo no tiene grandes problemas y por eso esta sesión esta mas pensada como un ejercicio de control sencillo y que como una regulación en toda regla.

Además el parámetro que buscamos controlar, la temperatura, tiene la virtud de variar con lentitud, lo que nos deja mucho tiempo para reaccionar y no tener que preocuparnos por cuestión de reaccionar con precisión en tiempo real.

 
  • Hace mucho tiempo, cuando empecé a trabajar en cosas de estas, y alguien preguntaba qué era eso de trabajar en tiempo real, definíamos el tiempo real como el margen que tenías para reaccionar y controlar el parámetro díscolo antes de que algo caro se fuera al guano.
  • Cuando estás en un marrón así, las técnicas que vamos a aplicar aquí no valdrían y tendríamos que empezar a hablar de cosas como el control PID, pero por ahora es pronto, así que mejor lo dejamos aquí.  
 

Vamos por tanto a montar un circuito sencillo con el sensor de temperatura y otro independiente con un transistor para controlar el motor del ventilador en la misma protoboard.

 

Esquema electrónico del circuito.

 

Vamos a montar un pequeño circuito que lea la temperatura de un sensor, imprima el valor en la consola y encienda un diodo cuando esta sobrepase un cierto umbral.

Para conectar el sensor de temperatura LM35DZ y el transistor 2N2222, os incluyo el detalle de sus pines aquí

Detalle pines
Pines del LM35DZ

Aquí tenemos el esquema electrónico del circuito:

Esquema electronico

Y el circuito para protoboard sería muy sencillo también:

Esquema de protoboard

 

Probando el sensor de temperatura.

 

Ya hemos visto en sesiones previas como usar un sensor LM35DZ, pero si alguno queréis revisarlo podéis hacerlo aquí: Sensor de temperatura.

Vamos a empezar probando el sensor para comprobar que funciona correctamente, y para ello vamos a usar este programa:

const int Sensor = 0 ;             // Pin que lee la temperatura

void setup()
   {    Serial.begin(115200);     }

void loop()
   {    int lectura = analogRead(Sensor);
        float voltaje = 5.0 /1024 * lectura ; 
        float temp = voltaje * 100  ;
        Serial.println(temp) ;
        delay(200);
   }

Usamos la puerta Analog0 que definimos como una constante sensor, y en el loop leemos la puerta y convertimos el valor de la lectura a grados centígrados (Recordad que la razón de hacerlo así la vimos en la sesión de los sensores de temperatura) e imprimimos sin más el valor de la temperatura. Deberías ver algo parecido a esto:

Consola Arduino

El sensor LM35DZ tiene un margen de error de alrededor de ± 0,5 grados y por eso las lecturas tienen oscilación, dando diferencias de hasta un grado.

 

Para los que van a por nota

 

El baile de las lecturas se debe a que el mundo real nunca es perfecto y hay cosas que van desde la incertidumbre de la medida causada por el propio sensor hasta los errores en los convertidores de nuestro Arduino (Que no son los mejores del mundo) e incluso interferencias electromagnéticas espurias.

Todo ello se confabula para que tengamos ese molesto baile de cifras en la medida y aunque en este caso no tiene importancia puede convenirnos filtrar este tipo de errores y para ello podemos promediar las n ultimas lecturas y presentar esto como el valor de la temperatura.

Para ello podemos guardarlas  digamos 8 últimas lecturas y promediarlas, con lo que aplanaremos fuertemente los errores, y la manera más sencilla es usar un buffer circular (O Ring Buffer)

Buffer circular

La forma de apuntar a la posición a escribir es una variable llamada Índex que empieza en 0 y cada vez que escribe en la posición correspondiente se incrementa en 1 ¿Y cómo evitamos que pase del valor máximo aceptable? Pues tomando el resto del valor de Índex con respecto al número de posiciones del array.

Buffer[ index] = temp ;
index = ++index % 8  ;

Una vez que apuntamos correctamente a la posición a escribir y después de los N valores iniciales en los que la temperatura promedio será falsa (Porque aún no hemos leído N valores) tendremos en Buffer las ultimas N lecturas y el resto es aritmética:

int index = 0 ;        // Posicion a escribir
const int N = 16 ;     // Numero de muestras a considerar
float Buffer[N] ;      // Array donde guardamos las lecturas

Buffer[ index] = temp ;
index = ++index  % N  ;

float Tmedia = 0 ;
for (int i=0 ; I < N ; i++)
     Tmedia = Tmedia + Buffer[i] ;
Serial.println( Tmedia / N) ;

Aquí os dejo el programa complete, por si quieres jugar con el: Prog_130_2. Para N = 32 podéis ver algo así:

Consola arduino

Podéis ver que la temperatura baila mucho menos y el baile desciende a medida que aumentáis el número de muestras que promediáis, pero cuidado, cuanto más crece N también crece el tiempo que tardáis en responder a los cambios ( Para N = 32 a 5 muestras por segundo hay más de 6 segundos de tiempo de reacción).

 
  • Aunque con una temperatura ambiente eso no es grave, puede haber ocasiones en que lo sea, por ejemplo porque un quemador arranca, y en 6 segundos le sobra tiempo para chamuscar lo que sea que estemos controlando, así que ojo 
 

 

Incluyendo el ventilador.

 

Ya tenemos montado el sensor de temperatura y ahora vamos a programar el control de arranque y apagado del motor / Ventilador, definiendo un valor umbral a partir del cual queremos ventilar el sensor. Veamos un posible programa: Prog_130_1

int Sensor = 0 ;             // Pin que lee la temperatura
int umbral = 30 ;            // Temparatura que arranca el ventilador
const int control = 9 ;      // Gobierna el ventilador

void setup()
   {   Serial.begin(115200);
       pinMode(control,  OUTPUT) ;
   }

void loop()
   {   int lectura = analogRead(Sensor);
       float voltaje = 5.0 /1024 * lectura ;    
       float temp = voltaje * 100 -5 ;
       Serial.println(temp) ;

       if (temp >= umbral)
           digitalWrite(control, HIGH);
       else
           digitalWrite(control, LOW);

       delay(200);
   }

La única novedad es que comprobamos que la temperatura medida es inferior al umbral prefijado y si no es así, arrancamos el ventilador para refrescar el sensor.

 
  • Fijaros que al alcanzar el umbral, disparamos el ventilador a tope de modo digital. Es decir todo o nada. En una situación real probablemente convendría hacer un control proporcional de la velocidad del ventilador en función de lo lejos que esta del punto que buscamos ( Aquí es donde entran las cuestiones de control PID)
  • Os propongo que hagáis un ejemplo en el que la velocidad del ventilador sea proporcional a la diferencia entre la temperatura umbral y la temperatura medida.  

Aquí tenéis un pequeño vídeo mostrando el montaje:

 

 

Resumen de la sesión

 

 

    • Mezclamos en un único proyecto un sensor y un actuador para conseguir control.
    • Presentamos la idea de buffer circular para promediar las lecturas instantáneas.
    • Vimos un principio de regulación de temperatura.

 
 
 

 

 

 

 

 

 

(38) Comments

  • Buenas noches. Me pueden ayudar sobre cómo controlar la potencia en este ejemplo. y me pueden explicar sobre PID. Gracias y saludos.

    • Hola Jimmy, no sé muy bien a qué te refieres con lo de controlar la potencia.

      En cuanto a los PID, es un tema que dan para mucho. Es un sistema de control que tiene tres acciones diferentes: proporcional, integral y derivativa. A grandes rasgos se utiliza para evitar las oscilaciones alrededor del setpoint de la variable que queremos controlar. Intentaremos dedicar alguna sesión a explicar el tema un poco por encima.

      Un saludo.

    • Hola Jimmy.

      Prueba a usar PWM. En vez de mandar un HIGH o un LOW para encender y apagar el ventilador, mandas un valor entre 0 y 255 para controlar la velocidad del mismo.
      Aunque en este tutorial no está por utilizar un ventilador pequeño, si vas a usar uno grande y de cierta potencia, debes agregar un diodo 1N4007 (o similar) para evitar dañar el transistor. Se coloca en paralelo junto a éste pero invertido.

      Saludos.

  • Buenas noches. Sobre el transistor 2N2222, es lo mismo que un ksp2222a?

    • Hola Jimmy, creo que son transistores equivalentes, y que la diferencia esta en el encapsulado. Un saludo.

    • EFREN

    y para trabajar con un lm35 y L293D seria el mismo código o que cambiaria ahí

    • Hola Efren, No estoy seguro de comprender tu pregunta porque el LM35dz es un sensor de temperatura y el L293D un circuito H_Bridge que nos son ni parecidos y por tanto no son equiparables

    • Anthony Sandoval

    Solo consegui un ventilador de 12 voltios, es necesario que sea de 5 voltios, podria ayudarme alguien diciendome si cambia el codigo de arduino?

    • Hola Anthony, en principio el codigo es exactamente el mismo, pero si alimentas un ventilador de 12V a 5V lo que puede pasar es que vaya muy lento o incluso que no llegue a arrancar.

      Lo que puedes hacer es alimentar el ventilador de 12V con una fuelte de 12 y controlarlo con un transistor cuya base regula arduino

    • Carlos

    hola admin me podrias pasar el programa completo??

    • Busca en la pagina esto : Prog_130_1

  • hola que tal, como seria el código si deseo mostrar la temperatura y el setpoint en una lcd?

  • y al usar este sensor dht11 no pasa nada con la programacion, o se modifica??? Gracias y saludos….

    • Hola Alejandro.

      Hay que modificar el sketch, porque son sensores diferentes. El primero es analógico y el segundo digital.

      Saludos.

  • hola , quisiera saber si se puede utilizar un sensor DHT11 en vez de un LM35 !!!!!! ….

    • Hola Alejandro, claro que podrías usarlo. Un saludo.

  • Hola, quisiera saber si se puede usar un sensor de temperatura LM335. Saludos!

    • Hola Frank, naturalmente que si y tienes un tutorial sobre ello

  • Hola que tal, me parece un excelente aporte, pero si quisiera saber las rpm que da mi ventilador como debería hacerlo?, eh estado intentando pero no eh conseguido hacerlo

    • Hola Erick, estos ventiladores baratos no incorporan ningun sistema de informacion sobre su velocidad, pero podrias emplear un LED o un laser y un receptor al otro lado del ventilador y de esa forma detectar los pulsos de luz a medida que el ventilador pasa por delante. En la tienda tenemos los wheel encoders http://www.prometec.net/producto/wheel-encoder-tacometro/ que basicamente son esto, pero tendrias que montarlos de algun modo en el ventilador

    • Marote

    ¡¡¡¡Ojo!!!!!
    El botón “Siguiente” tiene el link mal y no te lleva a la siguiente lección, va al apartado de Comunicaciones

    Ya está comunicado, a la espera de que lo arreglen, tenerlo en cuenta.

    • Estos Gremlins saltan donde menos te lo esperas, pero gracias a que me avisáis espero haberlo corregido. Muchas gracias por indicarmelo

    • Fonsov

    Ahh, lo de leer el pin 13 fue ya a la desesperada intentando que funcione, en otro codigo primero lo pongo a “HIGH
    Gracias y disculpa “el rollo”

    • Fonsov

    Muchas gracias por el aporte que haces. Estoy realizando algo muy parecido, prácticamente lo mismo, pero mi idea es que en lugar de definir esta variable “int umbral = 30 ; // Temparatura que arranca el ventilador”, dicho valor se tome de la primera lectura que haga el sensor, de esta manera si quiero que el ventilador, en este caso, se dispare cuando la temperatura suba 2 grados con respecto a la temperatura actual no habría problema, en caso contrario la temperatura ambiental puede hacer que en días de más calor dispare el ventilador nada más encender el circuito.
    El problema lo tengo en que no consigo en que esa variable mantenga el valor, sino que coge el valor de cuando la defino.
    Me permito enviar mi código, en realidad lo he tocado ya tanto que este no es el más sencillo, pero creo que puedes ver el problema.
    Muchas Gracias, me trae de cabeza.
    const int sensorPin = A0;// Defino una constante para el pin donde se pone el sensor
    int led = 13;
    float baselineTemp;
    void setup()
    {
    pinMode(9, OUTPUT);
    pinMode(led, OUTPUT);
    Serial.begin(9600);// Se abre una conexión serie para visualizar los valores en la consola
    // Declaro la temperatura base como la temperatura ambiental en el momento del encendido
    if (digitalRead(led) == HIGH)
    {
    int sensorVal = analogRead(sensorPin);
    float voltage = (sensorVal / 1024.0) * 5.0;
    static float baselineTemp = (voltage – .5) * 100;
    Serial.print(” – Temperatura Base establecida en: “);
    Serial.println(baselineTemp);
    digitalWrite(led, LOW);
    }
    if (digitalRead(led) == HIGH)
    {
    int sensorVal = analogRead(sensorPin);
    float voltage = (sensorVal / 1024.0) * 5.0;
    static float baselineTemp = (voltage – .5) * 100;
    Serial.print(” – Temperatura Base establecida en: “);
    Serial.println(baselineTemp);
    digitalWrite(led, LOW);
    }
    }

    void loop()
    {
    // Lee el valor del pin A0 y lo almacena en una variable
    int sensorVal = analogRead(sensorPin);
    Serial.print(” – Temperatura Base establecida en: “);
    Serial.println(baselineTemp);
    // Envia el valor de los 10-bit obtenidos del sensor al puerto serie
    Serial.print(“Temperatura del Sensor: “);
    Serial.print(sensorVal);
    // Convierto el valor del sensor en voltaje
    float voltage = (sensorVal / 1024.0) * 5.0;
    // Send the voltage level out the Serial port
    Serial.print(“, Voltios: “);
    Serial.print(voltage);
    // Convierte el voltaje a temperatura en Centígrados.Por cada grado centígrado el sensor varía 10 mV.
    Serial.print(“, degrees C: “);
    float temperature = (voltage – .5) * 100;
    Serial.println(temperature);
    //Serial.print(“Temperatura base: “);
    //Serial.println(baselineTemp);
    // Si la temperatura aumenta 2 grados con respecto a la establecida como base hago sonar el buzz
    if (temperature >= baselineTemp + 2) {
    // Emito un tono por el pin 9, el tono dado por el número puesto, el tiempo indicado en ms
    //noTone(9);
    tone(9, 440, 3000);
    delay(500);
    }

    delay(10000);
    }

    • Hola Fonsov

      Es un poco dificil leer el programa porque al eliminar los indentados, resulta complicado seguirlo, pero vamos a ver.

      En primer lugar te recomendaria que hagas una funcion llamada GetTemp o algo asi, que cuando la llames te devuelva un int con la temperatura actual, lo que simplificaria bastante la lectura.

      Y para hacer lo que me comentas a grandes rasgos podrias hacer algo asi:

      int baselineTemp = GetTemp() ;

      void setup()
      { }
      Void Loop()
      { in T = GetTemp() ;

      if ( T > baselineTemp + Delta)
      lo que sea
      else

  • hola buenos dias disculpa que te moleste pero soy nuevo en esto y necesito controlar la temperatura es para un proyecto los valores son 30°C y 38°C como se puede hacer la modificacion a tu codigo espero me puedas ayuda y muchas gracias.

    • Leon no te disculpes,eres bienvenido y todos hemos tenido que aprender. Podrias hacer algo asi:
      if (temp >= Superior)
      digitalWrite(control, HIGH);
      else if ( temp <= inferior) digitalWrite(control, LOW);delay(200);

  • float temp = voltaje * 100 -5 ;

    por que el -5

    • Hola pato. EL -5 es porque este sensor a 0º devuelve 50 mV y hay que restarselos para fijar el cero, creo que tenemos otra sesion por ahi en la que explicamos el funcinamiento de este sensor

  • Una pregunta, en el for del array circular, el segundo parámetro es I < N….
    I no debería ser minúscula?

    Salu2

    • Desde luego que si Abraham, muchas gracias por indicarmelo, lo corregire en cuanto pueda

  • Muy bueno el tuto, admin… Gracias

    • Víctor Pérez

    Que sucede si en lugar de un transistor 2N2222 tego un 2N2222A? En mi tienda de electronica no disponen de otro. Gracias

    • Hola ictor, puedes usar el 2N2222A exactamente igual y es 100% compatible con el que hemos usado aqui. No recuerdo de memoria pero sino receurdo mal la ultima letra indica la forma del encapsulado

        • Víctor

        Gracias, ya me funcinó. Tenias razon el encapsulado era metálico en lugar de plástico, pero cumple la misma función.

  • Lo primero, darte la enhorabuena por tu web y tu curso. Me asalta una duda cuando hablas del buffer circular. No entiendo cuando dices “La forma de apuntar a la posición a escribir es una variable llamada Índex que empieza en 0 y cada vez que escribe en la posición correspondiente se incrementa en 1 ¿Y cómo evitamos que pase del valor máximo aceptable? Pues tomando el resto del valor de Índex con respecto al número de posiciones del array.”

    index = index ++ % N

    Con la anterior expresión, ¿no nos saltaríamos valores que deben ir desde 0 a N (0, 1, 2, 3, 4, …., N)? ¿No podríamos solucionar esto con un for?

    Gracias de antemano!!!

    • Normalmente usas un buffer circular cuando quieres almacenar un numero dado de lecturas de algo, por ejemplo y se puede hacer de muchas maneras incluyendo un for dentro de un while (true) por ejemplo. Prueba este programa. Simplemente imprime el valor de index:

      int index = 0 ; // Posicion a escribir
      const int N = 16 ; // Numero de muestras a considerar
      float Buffer[N] ; // Array donde guardamos las lecturas

      void setup()
      { Serial.begin(9600); }

      void loop()
      {
      index = ++index % N ;
      Serial.print(index) ;
      Serial.print(“,”);
      if (N == index + 1 ) Serial.println();
      }
      EL bucle del loop va haciendo que index vaya tomando valores desde 0 hasta N, sin que N llegue a tomar el valor 16 que le hemos definido. Es una especie de costumbre en C++ que no se alcancen los indices como en los arrays

      Te puede parece una solucion extraña y lo es …. hasta que te acostumbres y veras que es una solucion muy util en cantidad de ocasiones, pero naturalmente hay mil maneras de hacerlo

Give a Reply

WordPress Anti-Spam by WP-SpamShield