Blog de Acuariofilia, Biología y Medioambiente (Antonio Castro)

Blog sobre Acuariofilia, Biología, Medioambiente, Mundo animal, Maltrato Animal, Medioambiente, Biodiversidad, Cambio Climátido…

CAO-9: Sensor digital de temperatura DS18x20

Continuamos dedicando artículos al estudio de algunos dispositivos Arduino que son de interés para nuestro proyecto CAO.

Esta vez vamos a comentar las pruebas realizadas con un sensor digital de temperatura. Concretamente se usaron para estas pruebas un par de sensores DS18B20 de Dallas.

Este usa el protocolo OnWire del que ya comentamos algo y tampoco vamos a comentar nada más porque es un protocolo muy complicado de entender en profundidad, pero las cuatro cosillas que aquí se digan serán suficientes para saber usarlo. La librería OnWire de Arduino nos permite un uso muy sencillo de este sensor. Lo que haré será proporcionaros un programita de ejemplo.

Ventajas del sensor digital DS18x20 frente al uso de un simple termistor analógico:

Las ventajas son varias

  • Mayor precisión.
  • Inmunidad frente a interferencias
  • Identificación de sensores por dirección.
  • Con una sola línea de fatos que en Arduino se gestionará con un solo pin, se puede gestionar todo un bus con varios sensores conectados a él.
  • No necesitan calibración.
  • El DS18B20, tiene un rango de temperaturas de funcionamiento de -55 °C a 125 °C. La resolución del sensor de temperatura es configurable por el usuario a 9, 10, 11, o 12 bits, correspondiente a incrementos de 0,5 ° C, 0,25 ° C, 0.125 ° C y 0,0625 ° C.

Este sensor digital DS18B20 es más caro que el sensor basado en un termistor NTC que comentamos en el capítulo anterior. A modo orientativo diremos que un termistor NTC no llegaba a costar más de un euro mientras que el chip DS18B20 está en torno a los 5 euros y la sonda sumergible  DS18B20 se acerca a los 8.

Formas de conectar un dispositivo DS18x20:

Hay dos formas de montar el chip que podéis apreciar en la figuras siguientes. El modo normal ofrece mayor garantía cuando el cable es largo o se conectan muchos sensores al bus y es el que yo voy a usar.

Conexiones_DS18B20

Conexiones del chip DS18B20 (modo normal y modo parásito)

Para probar estos chips DS18B20 estuve mirando varios ejemplitos y tomé varias ideas de algunos de ellos (en el código menciono las URLs).

Si compráis uno de estos maravillosos chips y deseáis probarlo, podéis usar este código que incluyo a continuación. El programa os va a permitir averiguar el código de identificación que vuestro chip tiene grabado de fábrica en ROM. El programa puede funcionar en modo parásito y en modo normal, pero yo solo lo he probado en modo normal. Lo he probado conectando uno o dos sensores. Se podrían conectar los que uno desee aumentando el límite de sensores que yo he puesto en cinco.

Es un programa de prueba, espero que os funcione tan bien como a mí, y se cede para su uso libre, gratuito y exento de garantías.

// **************************************************************************
// Programa para chequear el funcionamiento de sensores DS18x20
//
// Por Antonio Castro Snurmacher (mayo-2013)
//
// Basado en ejemplos de codigo abierto para un uso libre, gratuito y exento de garantias
//
// http://www.dfrobot.com/wiki/index.php/Waterproof_DS18B20_Digital_Temperature_Sensor_(SKU:DFR0198)
// http://blog.elcacharreo.com/2011/11/27/arduinolee-temperaturas-con-mayor-precision-ds18x20/
// http://playground.arduino.cc/Learning/OneWire
// http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20
// https://gist.github.com/kjordahl/1002726
// ***************************************************************************

#include < Onewire.h >

#define  DS18x20_Pin  12        // Definir pin para el bus con sensores DS18x20 
#define MAXDS18x20_SENSORS 3    // Numero maximo de sensores a explorar

#define ONEWIREPIN   7		// Bus OneWire conectado al pin 7 
#define MAXSENSORS   5		// Maximo numero de sensores en el bus OneWire bus
#define MAXS_ID      20		// Maxima longitud del identificador de usuario

OneWire ds(DS18x20_Pin);        // Instanciamos objeto OnWire con el Pin DS18x20_Pin
byte addr[MAXDS18x20_SENSORS][8];
char buf[80];
int NumDS18x20=0;

// ************************************
// Mostrar la direccion en hexadecimal
// ************************************
void PrintAddr(byte *addr){
    Serial.print("(");
    for(int i = 0; i < 8; i++) {
          if (addr[i] < 16) {
            Serial.print('0'); // Primer digito HEX = 0
          }
          Serial.print(addr[i], HEX);
          if (i < 7) {
            Serial.print(",");
          }
    }
    Serial.println(")");
}

// ********************************************************************
// Buscar todos los sensores conectados al bus, mostrar sus 
// Códigos hexadecimales (direcciones) e inicializar los dispositivos
// Retorna el número de dispositivos encontrados.
// ********************************************************************
int IniAll_DS18x20(){
  int i=0, n=0, err=0;

  Serial.println("\n");
  Serial.print("Buscando dispositivos OneWire conectados al pin digital ");
  Serial.println(DS18x20_Pin);
  while (true) {
      // Permitimos tantos errores como máximo numero de sensores se definieron
      if (err>MAXDS18x20_SENSORS){ 
          Serial.println("Demasiados errores buscando sensores DS18x20");
          return n;
      }
      if ( !ds.search(addr[n])) {
          ds.reset_search();
          sprintf (buf, "En total se han encontrado %d sensores DS18x20", n);
          Serial.println(buf);
          return n;
      }
      else  if ( OneWire::crc8( addr[n], 7) != addr[n][7]) {
          sprintf (buf, "Error de CRC en el sensor %d", n);
          Serial.println(buf);
          err++;
      } 
      else  if ( addr[n][0] == 0x10 ) {
          sprintf (buf, "Sensor%d DS18S20 en direccion ", n);
          Serial.print(buf);
      }
      else  if ( addr[n][0] == 0x28 ) {
          sprintf (buf, "Sensor%d DS18B20 en direccion ", n);
          Serial.print(buf);
          PrintAddr(addr[n]);
      }
      else  {
          sprintf (buf, "El dispositivo %d no se reconoce como un sensor DS18x20", n);
          Serial.println(buf);
          err++;
      }
      n++; // Siguiente
  }      
}

// *******************************************************************
// Obtener en formato de coma flotante el valor en grados celsius
// recogudo por uno de los sensores conectados al bus
// *******************************************************************
float getTemp(int n){
  byte data[12];
  float tempRead; 
  float Temp;

  ds.reset();
  ds.select(addr[n]);
  ds.write(0x44,1); // Indica al dispositivo que tome lectura de la temperatura y la ubique en la EEPROM  
  delay(1000); // Inicialmente no se puso el retardo y podría causar alguna mala lectura
  byte present = ds.reset();
  ds.select(addr[n]);    
  ds.write(0xBE); // Leer la EEPROM 
  for (int i = 0; i < 9; i++) { // Necesitamos leer 9 bytes
    data[i] = ds.read();
  }
  ds.reset_search();
  byte MSB = data[1];
  byte LSB = data[0];
  tempRead = ((MSB << 8) | LSB); 
  Temp = tempRead / 16;
  return Temp;
}

// ********** SETUP *********
void setup(void) {
  Serial.begin(9600);
  NumDS18x20=IniAll_DS18x20(); // Inicializar todos los sensores
  if (NumDS18x20>0){
      Serial.println("** Sensores listos **");
  }
}

// ********** LOOP **********
void loop(void) {
  float temp;
  int n;

  Serial.println("");
  delay(5000); 
  for (n=0; n< numds18x20 ; n++){ // Leer la temperatura de los sensores
          temp = getTemp(n);
          sprintf (buf, "Sensor%d) -> ", n);
          Serial.print(buf);
          Serial.println(temp);
  }
}

Las sondas que yo he probado eran DS18B20 Waterproof y marcaban casi medio grado de diferencia, dentro de lo admisible. Mi impresión general es muy buena.

Posibilidades para el uso de sensores de temperatura en acuariofilia:

Las necesidades pueden diferir mucho de una instalación a otra. En una sala de acuarios se podría optar por usar un solo Arduino para controlar toda una serie de acuarios y algunos de ellos, que tuvieran un interés especial, podrían usar una sonda digital DS18x20 para mayor seguridad (o incluso redundancia de sensores térmicos) mientras que en otros acuarios menos críticos se podrían usar sensores analógicos baratos. Incluso se podría asumir que en una pequeña batería de acuarios con las mismas características, se podrían gestionar asumiendo en todos ellos idénticas necesidades de calefacción y ahorrarnos la necesidad de poner sensores y termostatos en todos ellos. Uno de los inconvenientes de un planteamiento así sería que un fallo en una resistencia de calefacción en alguno de los acuarios no sería detectado. Estamos acostumbrados a usar los termostatos de acuarios de toda la vida basados en bimetales. Son muy rudimentarios pero muy fiables y todo lo que suponga innovar y automatizar debe hacerse con precaución.

Otra cosa que puede hacerse es medir la temperatura ambiente.

En verano se pueden alcanzar en los acuarios temperaturas superiores a las deseadas poniendo en riesgo la vida de nuestras plantas y peces, y se podría necesitar refrigerarlos de alguna forma.

Precauciones con las sondas autoconstruidas:

En cualquier caso la sonda de temperatura es un elemento importante del cual dependería la salud de los peces. Antes de instalar una chapucilla de sensor conviene pensar en las consecuencias que podría tener un mal funcionamiento. Si este debe controlar un calefactor podemos intercalar un termostato de los tradicionales que actúe como elemento de seguridad ante un eventual fallo de una sonda autoconstruida, por ejemplo por un fallo de la hermeticidad. De esta forma un fallo de un sensor autoconstruido no convertiría nuestro acuario en humeante sopa de pescado.

El modelo de sensor digital que yo he adquirido (unos 8 dólares) venía encapsulado para ser usado como sonda sumergible. Para ello viene con un acabado en acero inoxidable. Hay que advertir que el acero inoxidable no sirve para acuario marino y en un acuario de agua dulce, si bien resiste bastante tiempo  también podría terminar oxidándose o picándose por algún lado.

El acero inoxidable tiene carbono, pero los tipos de acero inoxidable son muy variables dependiendo de su contenido en ciertos metales que les pueden proporcionar mayor resistencia a diferentes tipos de circunstancias. Por definición todos ellos contienen un 10.5% de cromo, pero existen una variedad de materiales aleantes opcionales. Entre ellos destaca el niquel y el molibdeno. Por todo lo expuesto, la simple indicación de acero inoxidable en un componente, a mí no me merece la total garantía de uso, ni siquiera en agua dulce. Para mi gusto, siendo un elemento importante, una sonda debería aguantar 30 años sin dar problemas, no veo razón para conformarse con menos.

La silicona que yo usé para construir mi acuario de 750 litros aguantó 23 años. Parecen muchos años, pero el caso es que al final la silicona falló y me la lió parda. Tuve que regalar todos los peces y construirme un nuevo acuario. Si llega a ocurrir en mi ausencia quizás habría tenido que indemnizar a mi vecino de abajo. Hay cosas que no deberían fallar nunca.

El único metal que se puede usar en un acuario marino es el titanio y su duración en acuarios de agua dulce es muy superior al acero inoxidable.

Las soluciones caseras siempre entrañan riesgos pero aún no son descartables para todos los casos. Algunas veces necesitamos algo barato.

Existe un vídeo que muestra la fabricación de sondas sumergibles a partir del chip DS1820 que valdría casi la mitad.

Mi sonda analógica con la NTC, la hice sumergible con un procedimiento similar al del vídeo, y la uso para pruebas nada más.

Estoy pensando en cubrir la sonda de acero inoxidable  con un tubo lleno de silicona para alargar su vida útil que no tengo ni ideal de cual sería. La silicona y una buena funda de plástico me parecen los materiales idóneos para sellar este tipo de sondas y hacerlas impermeables. La pérdida de conductividad térmica del sensor por el aislamiento térmico de la cubierta plástica, no me parece un factor demasiado crítico. La sonda tardará un poco más en reaccionar a los cambios de temperatura, pero en un acuario donde los cambios son lentos no me parece que sea importante.

Mi idea es que CAO sea un sistema flexible y configurable que ofrezca varias alternativas para la automatizacion de acuarios.

En este sentido, si los sensores van a tomar parte en la automatización del control de la temperatura,  la medición de la misma habrá que considerarla como un factor muy importante y deberá ser muy fiable.

NOTA 20-jul-2013:

Después de usarlo con algunas librería que han sido publicadas para Arduino. Observo que en un funcionamiento prolongado y normal tras hacer cientos de lecturas enormemente precisas, aparece  ocasionalmente una lectura erronea con un desvío de la temperatura de  unos 8 grados centígrados y no he conseguido averiguar la razón de ello. Inicialmente era incluso peor su comportamiento, pero conseguí reducir bastante el problema intercalando el delay(1000); después de leer la EEPROM (podeis ver que lo he actualizado en el código) sin embargo el problema no ha desaparecido totalmente.

En mi software esto conduce a situaciones de falsas alarmas y agradecería que alguien comentara sobre este tipo de errores.

 

Anterior

La crisis de las abejas podría desembocar en una crisis alimentaria global.

Siguiente

Cultivo de colémbolos para la alimentación de alevines (incluye vídeo).

7 comentarios

  1. Juan

    Una mejora sustancial en tu código es sustituir el código

    ds.write(0x44,1); // Indica al dispositivo que tome lectura de la temperatura y la ubique en la EEPROM
    delay(1000); // Inicialmente no se puso el retardo y podrí­a causar alguna mala lectura

    por el siguiente código:

    myds.write(0x44,1); // start conversion, with parasite power on at the end
    long unsigned ix = millis();
    while ((!myds.read()) && ((millis() < ix + 1500) || (millis() < ix - 1000))) { // Bucle controlando 1.5 segundos y overflow de millis()
    // do nothing
    }

    Resulta que en tu código, te demoras 1 segundo por cada sonda (total, 3 segundos). Resulta que cada sonda responde en un intervalo variable de tiempo que va desde los 45ms hasta los 350 ms. Con este código, ahorras un tiempo considerable por cada sonda. Puedes hacer pruebas mostrando el tiempo que tarda en la conversión y verás que llevo razón. Yo tengo 4 sondas y compruebo su temperatura cada 20-30 segundos. Con lo cual el Ardu no se dedica exclusivamente a comprobar la temperatura.
    Saludos.

  2. Antonio Castro

    Para el refrigerador me puedo permitir malgastar ese tiempo. Lleva más de un año funcionando perfectamente.

    En mi controlador CAO1, cuyo código completo te puedes descargar, necesito más velocidad, por ello implementé un módulo que hace que las lecturas de temperatura sean instantáneas.

    En mi libro lo explico, pero puede que solo te interese ese detalle. Te copio el párrafo del libro que explica esa mejora. Gracias por tu interés.

    Módulo Cao1_DS18x20
    Para la programación de este módulo se ha recurrido a la reutilización de código basado en ejemplos de código abierto para un uso libre, gratuito y exento de garantías. Para más información sobre estas fuentes originales consulte la URLs siguientes:
    http://www.dfrobot.com/wiki/index.php/Waterproof_DS18B20_Digital_Temperature_Sensor_(SKU:DFR0198)
    http://blog.elcacharreo.com/2011/11/27/arduinolee-temperaturas-con-mayor-precision-ds18x20/
    http://playground.arduino.cc/Learning/OneWire
    http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20
    https://gist.github.com/kjordahl/1002726
    Se ha recogido información de diversas fuentes para confeccionar este módulo. La pregunta inmediata que puede surgir es si no se podría haber utilizado tal cual alguno de esos módulos de librerías. La respuesta es que existen al menos dos motivos importantes por los cuales se ha preferido desarrollar un módulo para esta aplicación. El primero es que la comunicación de los sensores con la interfaz de usuario necesitaba adecuarse al uso de nuestro display LCD de 20×4. El segundo motivo importante es que en las propuestas que consulté la lectura del sensor de temperatura implicaba el uso de una operación que consumía mucho tiempo. Eso en una aplicación que intenta hacer muchas cosas a la vez no resulta adecuado. Nosotros lo que hacemos es dividir la operación de lectura en dos operaciones suficientemente distanciadas en el tiempo. Una primera que es preparatoria, y una posterior que entregará el resultado de la primera. La primera esta definida de forma privada en el módulo y sería _PrevGetTempPos(int pos). El usuario de este módulo no necesita saber siquiera que existe. Su implementación es la siguiente:
    void Cao1_DS18x20::_PrevGetTempPos(int pos){
    ds.reset();
    ds.select(_addr[pos]);
    ds.write(0x44,1); // Indica al dispositivo que tome lectura de la temperatura y la ubique en la EEPROM
    }
    Esta función preparatoria se va a usar al inicio del módulo, y posteriormente se usará dentro de la función que entrega el valor de lectura de la temperatura recibida por un sensor y se usará en ambos casos de forma transparente (sin que el usuario necesite saberlo). Es decir, una lectura de temperatura preparará la lectura siguiente. Al hacerlo así y dado que la aplicación en su modo normal de funcionamiento va hacer una lectura de todos los sensores cada dos segundos, obtendremos la temperatura de un dato que se solicitó dos segundos antes. Con ello nos evitamos esperar inútilmente 750 milisegundos. No soy el único que implementó algo de este tipo. Otro motivo es que nosotros necesitamos obtener el dato como entero y devolveremos décimas de grados centígrado aunque internamente se trabaje en coma flotante.
    La función de lectura de la temperatura es GetTempPos(int pos) que necesita recibir la posición del sensor, pero para un uso adecuado dentro de la aplicación nosotros identificamos a los sensores por su dirección interna y este módulo nos proporciona para ello una función GetTempAddr(char *sAddr) que averiguará primero la posición del sensor y luego llamará a GetTempPos(int pos).

  3. lalo

    hola como se puede configurar la resolucion de este sensor
    mencionas que es de 9 a 12 bits
    me ayudarias mucho
    quiero que los saltos sean mas pequeños y no de 0.5 en 0.5

  4. Guillermo

    En este artículo dice que el sensor 18B20 NO NECESITA CALIBARCIÓN, entonces como explica que tengo 4! !! sensores con lectura simultánea y TODOS muestran valores diferentes de temperatura entre el max. valor y el mínimo hay 4°C de diferencia (16 °C y 11.9 °C respectivamente) el correspondiente al valor máx es el que mas se acerca a valores de 6 diferentes termómetros funcionando simultáneamente(Termocupla, RTD, NTC, Fibra de hewlett packard, Pt100). Quizás en estos años haya aprendido algo antes de afirmar que no necesitan calibración.

    • Antonio Castro

      Yo he hecho muchas pruebas con distintos sensores (del orden de una docena) y miden directamente la temperatura con la precisión indicada en las datasheet sin ningún tipo de calibración. No te voy a pedir que me des detalles de lo que has hecho porque no estás usando unas formas educadas de pedir ayuda, y no voy a invertir más tiempo en ayudarte, pero sí que te remito a la información del fabricante que quizás sepa un poco más que tú sobre lo que fabrica. https://cdn-shop.adafruit.com/datasheets/DS18B20.pdf

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Funciona con WordPress & Tema de Anders Norén