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):
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:
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.