Archivo de la etiqueta: temperatura

Arduino y sensores de temperatura DS18B20


Os traigo un ejemplo de como usar los sensores de temperatura DS18B20 con nuestro Arduino. La ventaja principal que presentan estos sensores es que se pueden conectar hasta 100 dispositivos a un único pin y a una distancia máxima de nuestro Arduino de 200 metros. Dichos sensores emplean el protocolo de comunicación en serie 1-wire diseñado por Dallas Semiconductor.

Pero, ¿en que se basa este protocolo de comunicación? pues básicamente y para no entrar en muchos tecnicismos, es un bus donde disponemos de un maestro y varios esclavos en una sola línea de datos (pin de nuestro Arduino) en la que se alimentan. Por supuesto, necesita igualmente una referencia a tierra común a todos los dispositivos. También debemos conocer que la línea de datos/alimentación debe de disponer de una resistencia de pull-up conectada a alimentación para cuando no se produzca la transmisión de datos cuando tengamos 5 voltios en dicha línea.

En este tipo de sensores podemos encontrar dos tipos de alimentación:

* El primero de ellos alimenta a los dispositivos en modo parásito, esto quiere decir que solo suministra alimentación mientras se realizan las operaciones de conversión de temperatura, se deben puentear las patillas GND y VDD del DS18B20 a GND del Arduino.

* El segundo es alimentación de los sensores mediante una fuente de alimentación externa conectada a la patilla VDD del DS18B20, y la patilla GND al pin GND de Arduino.

Ahora vamos al lío, aquí tenéis el esquema de conexionado de los tres sensores y dos led indicadores de temperatura:

NOTA: Las conexiones a GND de los sensores 2 y 3 están mal en el esquema de Fritzing, tienen que ir donde GND del Arduino.

Como podéis ver uso la alimentación tipo parasito y en el programa que he realizado básicamente indicamos el pin por el que vamos a comunicar nuestros sensores con el Arduino, añadiendo para ello dos librerías, las cuales son OneWire.h y DallasTemperature.h. Leemos la temperatura de los 3 sensores DS18B20 y mostramos mediante el monitor serie dichas temperaturas, además mostramos una temperatura media de las tres, y guardamos la temperatura mínima y máxima para mostrar también. Los diodos led se encienden dependiendo de la temperatura media que tengamos, el led verde se enciende para una temperatura de menos de 22ºC y el led rojo indica una temperatura mayor de 22ºC.

Aquí podéis ver un vídeo del funcionamiento del programa:

Aquí dejo el código:

/*Programa realizado por Regata para tallerarduino.wordpress.com*/
/*Medición de temperatura mediante varios sensores 1-wire DS18B20+*/

#include <OneWire.h>
#include <DallasTemperature.h>

// DQ esta conectado al pin 10 de Arduino
#define ONE_WIRE_BUS 10

// Configuramos para comunicar con otros dispositivos 1-Wire
OneWire oneWire(ONE_WIRE_BUS);

// Indicamos el pin asignado al sensor 1-Wire a DallasTemperature 
DallasTemperature sensores(&oneWire);

int ledverde=11;  //indicamos que le led verde esta conectado en el pin 11 de Arduino
int ledrojo=12;  //indicamos que el led rojo esta conectado en el pin 12 del Arduino
float val=0; // variable donde guardaremos la temperatura leida del sensor
int i;  //variable que contiene el numero de sensores empleados en el caso de ser mas de 1
float tempmin=100;  //Variable donde guardamos la temperatura minima registrada
                    //Le pongo 100 por que en donde lo he probado no llega a esa temperatura
                    //y así puede coger el menor valor de temperatura que aparezca
float tempmax=0;    //Varibale donde guardamos la temperatura maxima registrada

void setup(void)
{
  //Indicamos ledverde y ledrojo como salidas  
  pinMode(ledverde,OUTPUT);
  pinMode(ledrojo,OUTPUT);
  // Iniciamos el puerto serie a 9600 baudios
  Serial.begin(9600);
  // Inicializamos la libreria
  sensores.begin();
  //Ponemos a 0 las salidas ledverde y ledrojo
  digitalWrite(ledverde,LOW);
  digitalWrite(ledrojo,LOW);
}

void loop(void)
{ 
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  float media=0;
  for(i=0;i<=2;i++)
  {
    sensores.requestTemperatures(); //Enviamos el comando para obtener la temperatura  
    Serial.print("Temperatura Sensor ");
    Serial.print(i);
    Serial.print(": ");
    float val =  sensores.getTempCByIndex(i); // Almacenamos la temperatura en la variable val
    media=media+val;  //Vamos sumando para poder calcular la media de las temperaturas
    Serial.println(val);  //Mostramos por puerto serie el valor de la temperatura leida
    if (val<tempmin)
      tempmin=val;
    if (val>tempmax)
      tempmax=val;
  }
    media=media/i;  //Calculamos la media de las temperaturas
    Serial.print("La temperatura media es: ");  //Mostramos la temperatura media de todas las temperaturas
    Serial.println(media);
    Serial.print("La temperatura minima registrada es: ");  //Mostramos la temperatura minima registrada
    Serial.println(tempmin);
    Serial.print("La temperatura maxima registrada es: ");  //Mostramos la temperatura maxima registrada
    Serial.println(tempmax);
    //Si la temperatura media es mayor o igual a 22ºC encendemos el led rojo y apagamos el led verde
    if(media>=22)
     {
      digitalWrite(ledverde,LOW);
      digitalWrite(ledrojo,HIGH);
     }
     //Si es menor a 22ºC encendemos el led verde y apagamos y el led rojo
     else
     {
        digitalWrite(ledrojo,LOW);
        digitalWrite(ledverde,HIGH);
     }
    Serial.println();
    delay(1500);  //Esperamos 1500ms
}

Os dejo también los documentos necesarios para realizar el montaje:

http://www.mediafire.com/?x5h64n3k82c6pkg

Ante las preguntas de varios visitantes del blog, he estado mirando la forma de leer los sensores a través de su dirección de dispositivo, ya que bien podemos tener distintos sensores colocados en varios sitios y queremos leer independientemente cada uno de ellos. Un ejemplo de dirección de dispositivo de estos sensores puede ser {0x28, 0xC7, 0xE8, 0x06, 0x05, 0x00, 0x00, 0xDC}. Arriba hemos visto la forma de leer los sensores por Index, que para varios sensores la verdad no es muy recomendado ya que la propia librería se encarga de asignar la posición de los sensores para ser leídos, por eso vamos a trabajar con la dirección específica para cada sensor y así tener el control sobre ellos.

Lo primero que vamos a tener que hacer es detectar cual es la dirección del dispositivo, para ello conectamos el sensor a nuestro Arduino (en este caso he realizado la prueba con un Arduino Mega 2560, pero vale con cualquier otro Arduino, lo único que tenéis que cambiar es el pin donde conectamos el sensor):

DS18B20 Address

El código para obtener la dirección del sensor es el siguiente:

/*Programa realizado por Javier Couto Rego (Regata) para www.tallerarduino.wordpress.com

Programa de lectura de sensores de temperatura DS18B20 de Dallas Semiconductor a través de
su direccion de dispositivo en lugar de lectura indexada.*/

//Incluimos las librerias para controlar los sensores de temperatura
#include <OneWire.h>
#include <DallasTemperature.h>

//Estoy trabajando con un Arduino Mega, indico que los sensores estan conectados al pin 33
#define ONE_WIRE_BUS 33
OneWire oneWire(ONE_WIRE_BUS);  // Configuramos para comunicar con otros dispositivos 1-Wire
DallasTemperature sensores(&oneWire); // Indicamos el pin asignado al sensor 1-Wire a DallasTemperature 
DeviceAddress Sensor;  // Array donde almacenamos la direccion del sensor DS18B20

void setup(void)
{
  Serial.begin(9600);  //Iniciamos la comunicacion serie a 9600 baudios
  Serial.println("Comprobación Direccion Sensores DS18B20:");
  sensores.begin();  //Iniciamos la libreria para la lectura de los sensores
  //Obtenemos la direccion del sensor de temperatura
  if (!sensores.getAddress(Sensor, 0)) 
    Serial.println("Imposible encontrar direccion del sensor.");
}

//Funcion que muestra la direccion del sensor de dicha direccion
void Mostrar_Direccion(DeviceAddress direccion)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (direccion[i] < 16) Serial.print("0");
    Serial.print(direccion[i], HEX);
  }
}

void loop(void)
{ 
  //Mostramos la direccion del sensor
  Serial.print("Direccion del sensor: ");
  Mostrar_Direccion(Sensor);
  Serial.println();
  delay(1000);
}

Un ejemplo de uso de estos comando con la librería DallasTemperature y 5 sensores DS18B20:

Ejemplo DS18B20 5 Sensores

El código es:

/*Programa realizado por Javier Couto Rego (Regata) para www.tallerarduino.wordpress.com

Programa de lectura de sensores de temperatura DS18B20 de Dallas Semiconductor a través de
su direccion de dispositivo en lugar de lectura indexada.*/

//Incluimos las librerias para controlar los sensores de temperatura
#include <OneWire.h>
#include <DallasTemperature.h>

//Estoy trabajando con un Arduino Mega, indico que los sensores estan conectados al pin 33
#define ONE_WIRE_BUS 33
                              
OneWire oneWire(ONE_WIRE_BUS);  // Configuramos para comunicar con otros dispositivos 1-Wire
DallasTemperature sensores(&oneWire); // Indicamos el pin asignado al sensor 1-Wire a DallasTemperature 

//Indicamos las direcciones de los distintos sensores
DeviceAddress S1 = {0x28, 0xC7, 0xE8, 0x06, 0x05, 0x00, 0x00, 0xDC};  //Sensor 1
DeviceAddress S2 = {0x28, 0xD7, 0xF2, 0x07, 0x05, 0x00, 0x00, 0xC9};  //Sensor 2
DeviceAddress S3 = {0x28, 0xC4, 0xF0, 0x07, 0x05, 0x00, 0x00, 0x48};  //Sensor 3
DeviceAddress S4 = {0x28, 0xC9, 0xB6, 0x07, 0x05, 0x00, 0x00, 0x77};  //Sensor 4
DeviceAddress S5 = {0x28, 0x8D, 0xE9, 0x06, 0x05, 0x00, 0x00, 0xAB};  //Sensor 5

void setup(void)
{
  Serial.begin(9600);  //Iniciamos la comunicacion serie a 9600 baudios
  sensores.begin();  //Iniciamos la libreria para la lectura de los sensores
}

//Funcion que muestra la direccion del dispositivo de dicha direccion
void Mostrar_Direccion(DeviceAddress direccion)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (direccion[i] < 16) 
      Serial.print("0");
    Serial.print(direccion[i], HEX);
  }
}

//Funcion que muestra la temperatura en grados centigrados del sensor de dicha direccion
void Mostrar_Temperatura(DeviceAddress direccion)
{
  float tempC = sensores.getTempC(direccion);
  Serial.print("Temperatura: ");
  Serial.print(tempC);
}

//Funcion que muestra la resolucion del sensor de dicha direccion
void Mostrar_Resolucion(DeviceAddress direccion)
{
  Serial.print("Resolucion: ");
  Serial.print(sensores.getResolution(direccion));
  Serial.println();    
}

//Funcion que muestra los datos del sensor de dicha direccion
void Mostrar_Datos(DeviceAddress direccion)
{
  Serial.print("Direccion del dispositivo: ");
  Mostrar_Direccion(direccion);
  Serial.print(" ");
  Mostrar_Temperatura(direccion);
  Serial.println();
}

void loop(void)
{ 
  Serial.println("Comprobación Direccion Sensores DS18B20:");
  //Podemos ver el numero de dispositivos que estan conectados al bus 1-Wire
  Serial.print("El numero de dispositivos es: ");
  Serial.println(sensores.getDeviceCount(), DEC);
  //Podemos comprobar si el sensor esta alimentado en modo Parasito
  Serial.print("Alimentacion en modo Parasito: "); 
  if (sensores.isParasitePowerMode()) 
    Serial.println("ON");
  else 
    Serial.println("OFF");
  Serial.print("Direccion Sensor 1: ");
  Mostrar_Direccion(S1);
  Serial.println();
  Serial.print("Direccion Sensor 2: ");
  Mostrar_Direccion(S2);
  Serial.println();
  Serial.print("Direccion Sensor 3: ");
  Mostrar_Direccion(S3);
  Serial.println();
  Serial.print("Direccion Sensor 4: ");
  Mostrar_Direccion(S4);
  Serial.println();
  Serial.print("Direccion Sensor 5: ");
  Mostrar_Direccion(S5);
  Serial.println();
  //Establecemos la resolucion para cada sensor, PRECISION es a 9 bits
  sensores.setResolution(S1, 9);  //Resolucion a 9 bits 0.50 ºC
  sensores.setResolution(S2, 9);  //Resolucion a 9 bits 0.50 ºC
  sensores.setResolution(S3, 10); //Resolucion a 10 bits 0.25 ºC
  sensores.setResolution(S4, 11); //Resolucion a 11 bits 0.125 ºC
  sensores.setResolution(S5, 12); //Resolucion a 12 bits 0.0625 ºC
  //Si queremos mostrar la resolucion que tiene cada sensor:
  Serial.print("Resolucion Sensor 1: ");
  Serial.print(sensores.getResolution(S1), DEC); 
  Serial.println();
  Serial.print("Resolucion Sensor 2: ");
  Serial.print(sensores.getResolution(S2), DEC); 
  Serial.println();
  Serial.print("Resolucion Sensor 3: ");
  Serial.print(sensores.getResolution(S3), DEC); 
  Serial.println();
  Serial.print("Resolucion Sensor 4: ");
  Serial.print(sensores.getResolution(S4), DEC); 
  Serial.println();
  Serial.print("Resolucion Sensor 5: ");
  Serial.print(sensores.getResolution(S5), DEC); 
  Serial.println();
  sensores.requestTemperatures();  //Enviamos el comando para obtener los datos de los sensores
  //Mostramos los datos de todos los sensores
  //Llamamos a la funcion Mostrar_Datos indicando la direccion del sensor que queremos leer
  Serial.print("Sensor 1 --> ");
  Mostrar_Datos(S1);
  Serial.print("Sensor 2 --> ");  
  Mostrar_Datos(S2);
  Serial.print("Sensor 3 --> ");
  Mostrar_Datos(S3);
  Serial.print("Sensor 4 --> ");
  Mostrar_Datos(S4);
  Serial.print("Sensor 5 --> ");
  Mostrar_Datos(S5);
  delay(2000);  //Retardo de 2 segundo
}

Espero que os guste!!!

Si te ha servido de ayuda esta entrada, puedes realizar un donativo para agradecer el tiempo que dedico al blog y ayudar a hacer más entradas.

donativo_paypal