![]() |
Fig1. DS18B20 (a) KT-040 y (b) Punta de prueba |
Un gran saludo a los visitantes de este blog, creado para compartir el mutuo interés en la electrónica y en especial la
programación de microcontroladores PIC, antes de empezar quiero recordarte que
estoy atento a cualquier sugerencia o critica constructiva relacionada
con esta publicación, dicho esto al final de esta entrada esta los mis datos de contacto.
En esta ocasión veremos como utilizar uno o mas sensores de temperatura DS18B20 con nuestro microcontrolador PIC16F887, tanto el programa asi como el esquema del circuito que utilizare se encuentran disponibles en mi repositorio https://github.com/pablinza/piclab2.
La programación del microcontrolador PIC se llevara a cabo utilizando el software MPLABX y el compilador C XC8. Ambas aplicaciones están disponibles en la pagina oficial de microchip en sus versiones gratuitas. Aquí dejo los enlaces de las versiones utilizadas para nuestro ejemplo: <<MPLABX v6.20>> <<XC8 v2.45>>
Mencionar que una adecuada comprensión de los códigos descritos, es aconsejable poseer conocimientos básicos de la programación en lenguaje C y microcontroladores PIC16F.
Explicaremos brevemente dos aspectos que involucran el proceso de medir la temperatura con el microcontrolador, estos son el protocolo 1-Wire y el sensor DS18B20.
Protocolo 1-Wire: Es un protocolo de comunicaciones serial asíncrono que utiliza un esquema de conexión punto a multipunto, donde hay un maestro (host) que se comunica con el resto de dispositivos (esclavos). Un aspecto interesante de este protocolo es que utiliza sola una linea de comunicación, este canal bidireccional usualmente requiere adicionar una resistencia pull-up, asegurar un nivel logico alto en el bus, cuando esta en modo inactivo, en la figura 2 se muestran las diferentes topologías de conexión que pueden implementarse con este protocolo. para que todos los dispositivos conectados utilicen el tercer estado como mecanismo para liberar el bus. 1-Wire puede implementarse en una topología lineal, fraccionada o estrella.
La implementación de una red 1-wire presenta limitaciones similares a cualquier otro protocolo, y tiene que ver por ejemplo con la distancia maxima para la transmisión debido a la degradación y retardo de la señal por la resistencia interna del cable, pese a ello podemos encontrar dos modos de operación que son: el modo standar que permite una tasa de hasta 16.3kbps, y el modo overdrive que eleva la velocidad
Con respecto a la señalización utilizada por el protocolo 1-Wire de este sensor, el dispositivo maestro sera nuestro microcontrolador PIC y los dispositivos esclavos serán los sensores DS18B20, tome las referencias publicadas en los documentos SPMA057C y AN1119 con el siguiente detalle:
Reset Slot: Es una señal obligatoria que emite el maestro antes de enviar los comandos para comunicarse con un sensor, como vera en la figura 3, el maestro solo el bus en nivel bajo por 480us, y luego libera el bus en nivel alto, entonces en los siguientes 240us un dispositivo esclavo debe responder colocando el bus a nivel bajo, con lo cual el maestro detectara la presencia de un dispositivo activo en el bus.
![]() |
Fig3. Señal (Reset Slot) |
Write Slot 0: Esta es la señalización que emite el maestro para enviar un bit 0 al dispositivo esclavo, observe la figura 4 donde, el maestro coloca el bus en nivel bajo por 60us suficientes para que el dispositivo esclavo realice la lectura del nivel bajo (bit 0).
![]() |
Fig4. Señal (Write Slot 0) |
Write Slot 1: Esta es la señalización que emite el maestro para enviar un bit 1 al dispositivo esclavo, observe la figura 5 donde, el maestro coloca el bus en nivel bajo por máximo 15us, para luego libera el bus en nivel alto hasta completar los 60us, entonces el dispositivo esclavo realizara la lectura del nivel alto (bit 1) a partir de los 15us.
![]() |
Fig4. Señal (Write Slot 1) |
Read Slot 0: Con esta señalización el maestro recibe desde el dispositivo esclavo un bit0. Para la lectura el maestro coloca el bus en nivel bajo por un tiempo de 5 a 15us y luego
lo libera en nivel alto, entonces el dispositivo esclavo contestara colocando el bus en
nivel bajo (bit 0), por lo que el maestro debe hacer lectura del nivel antes de los 60us que dura esta señal, observe la figura 5.
![]() |
Fig5. Señal (Read Slot 0) |
Read Slot 1: Esta señal permite al maestro recibir un bit0 desde el dispositivo esclavo. Para la lectura el maestro coloca el bus en nivel bajo por un tiempo de 5 a 15us y luego lo libera en nivel alto, entonces el dispositivo esclavo contestara manteniendo el bus liberado en nivel alto (bit 1), por lo que el maestro debe hacer lectura del nivel antes de los 60us que dura esta señal, observe la figura 6.
![]() |
Fig6. Señal (Read Slot 1) |
El tiempo mínimo de espera o tiempo de recuperación por cada bit transmitido por el bus 1-Wire es de al menos 10us, pero refiérase a las especificaciones del dispositivo esclavo para un dato mas preciso.
Sensor de Temperatura DS18B20: Describiré un breve resumen acerca de este sensor tomando como referencia la hoja de datos DS18B20 del fabricante Maxim Integrated.
El ds18b20 esta disponible en los encapsulados TO-92, SOIC y SOP, opera con voltaje de alimentación de 3.3 - 5.5V y un consumo de 1.5mA en su modo activo.
Se trata de un sensor digital de temperatura con una resolución ajustable de 9 a 12-bit, con un rango de operación que va desde los -55°C a 125°C.
El sensor tiene la ventaja de ser un dispositivo direccional gracias a que utiliza el protocolo serial asíncrono 1-Wire, donde cada sensor tiene asignado en su memoria ROM un código único de 64-bit para su identificación.
Se sugiere revisar la hoja de datos para conocer mas detalles de los tiempos mínimos y máximos establecidos para la señalización del bus.
La conexión del sensor se puede realizar de dos maneras, una de ellas se denomina parasite-powered que no trataremos en esta publicación, y el otro modo es el external-power supply, utilizaremos la segunda opción llevando a cabo las conexiones del sensor como se observa en la figura 7.
![]() |
Fig7. Conexión del Sensor |
Como notara en el esquema de conexión, se necesita una resistencia externa de 4.7k en modo pull-up para garantizar un nivel logico alto, cuando el bus es liberado. La secuencia de señales que requiere el microcontrolador (maestro) para comunicarse con el sensor (esclavo) se muestra en la figura 8 y es la siguiente:
Inicialización: El maestro emite el Reset Slot, y espera respuesta de un esclavo
Direccionamiento: El maestro emite el comando ROM para la identificación de un esclavo, siendo las posibles opciones, los siguientes comandos:
- Search ROM[0xF0]: Permite que el maestro inicie una procedo de lectura secuencial de los códigos ROM cada sensor conectado al bus
- Read ROM[0x33]: Cuando existe un solo dispositivo esclavo conectado en el bus, este comando permite leer su código ROM.
- Match ROM[0x55]: Cuando se conoce el código ROM del dispositivo esclavo, este comando permite al maestro seleccionar al dispositivo esclavo del resto de dispositivos conectados.
- Skip ROM[0xCC]: Permite la selección todos los dispositivos conectados con las que se realizara una operación común, por ejemplo que todos los sensores inicien el proceso de conversión.
- Alarm Search[0xEC]: Permite al maestro identificar los sensor que se encuentran con estado de alarma.
Función: Una vez establecida la identificación (Direccionamiento) con un dispositivo esclavo, el maestro enviara un comando de función para el sensor DS18B20, las posibles opciones son:
ConverT[0x44]: El sensor iniciara el proceso de conversion que se completara después de un tiempo mínimo (Tiempo de Conversión). Este tiempo depende de la resolución del sensor, siendo los valores mínimos 94ms a 9-bit, 188ms a 10-bit, 375ms a 11-bit y 750ms a 12-bit(defecto).
Read Scratchpad[0xBE]: El scratchpad hace referencia al conjunto de 8 registros o bytes que contienen informacion del sensor, entre las cuales están el valor de temperatura en grados centígrados y configuracion del sensor tal como se observa en la figura 9.
Write Scratchpad[0x4E]: El comando permite escribir tres bytes de configuracion que son accesibles a la memoria EEPROM, estos bytes corresponden a los registros 2, 3 y 4 del Scratchpad.
Copy Sractchpad[0x48]: Almacena el valor de los registros 2, 3 y 4 del Scratchpad en la memoria no volátil EEPROM.
Recall E2[0xB8]: Recupera desde la memoria no volátil EEPROM los valores de configuracion para los registros 2, 3 y 4 del Scracthpad.
Read Power Supply[0xB4]: No se detalla en el blog, ya que esta relacionado con el modo de operación parasite-powered.
Ahora detallaremos el formato de algunos registros del Scratchpad, empezando por los dos primeros que contienen el resultado de una conversion, observe que en la figura 10, se muestra que el bit11 al bit15 tiene repetida la indicación del signo, luego los bit4 al bit10 representa la parte decimal del resultado y finalmente los bit0 al bit3 es la fracción del resultado.
Observe que la resolución de bits utilizada afecta únicamente a la fracción del resultado, por ejemplo si utilizamos la resolución por defecto que es 12-bit, haremos uso de los cuatro bit0 al bit3, logrando una precisión con incrementos de 1/16 = 0.0625 °C en la fracción, en cambio si utilizamos 9-bit, haremos uso solo del bit3, logrando incrementos de 1/2 = 0.5 °C
El registro 4 que se muestra en la figura 11, corresponde al byte de configuración donde se encuentran los bits R1 y R0, estos permiten ajustar la resolución del sensor, siendo la combinación del par R[1:0]=11 para 12-bit, R[1:0]=10 para 11-bit, R[1:0]=01 para 10-bit y [R1:0]=00 para 9-bit.
![]() |
Fig11. Registro de configuracion (12-bit defecto) |
La propuesta como ejemplo de uso para el sensor ds18b se ilustra en el esquema del circuito de la figura 12, en el esquema no se muestran las conexiones relacionadas con la alimentación de 5V y tampoco los componentes mínimos necesarios para el funcionamiento del microcontrolador.
![]() |
Fig12. Esquema del Circuito PIC |
El microcontrolador utilizara el oscilador interno configurado a 8MHZ para proveer un ciclo de instrucción de tan solo 0.5us, notara que todos los sensores están conectados de forma simultanea al pin RB0 del PIC sin la resistencia pull-up 4.7k, esto es así porque activaremos la resistencia interna que poseen los pines del PORTB en el microcontrolador. El pulsador identificado como BUT1, servirá para indicar en el programa que se realice la lectura del código de identificación ROM del sensor conectado al bus para que pueda enviarse como mensaje a través del puerto serie.
En funcionamiento normal, los datos de temperatura de cada sensor se enviaran como mensaje serial a intervalos de un segundo.
Para poder explicar el programa del microcontrolador, es importante conocer el esquema de programación por estados y la ejecución concurrente de tareas que utilizo en la mayoría de los ejemplos de mi blog. Para lo cual te sugiero puedas repasar lo descrito en las siguientes entradas:
Utilizaremos los procedimientos y funciones de la librería "ds18b20.c" y nos enfocaremos en dos de las tres tareas que se ejecutan en el programa principal cada 1ms, donde la tarea taskLED1() tiene como propósito únicamente destellar el diodo LED del pin RE2 para indicar que el Microcontrolador opera con normalidad y las otras dos tareas son:
taskBUT1(): Esta tarea espera que el pulsador del pin RB1 se mantenga presionado por intervalo mínimo de 200ms para iniciar la lectura del código ROM de un sensor. La idea de este procedimiento es utilizarlo para identificar de forma física cada sensor y elaborar una lista de todos los sensores que se consideraran en el código principal para la lectura de temperatura, la lista final de los tres sensores para nuestro ejemplo seria:
uint8_t dev0rom[8]={0x28,0xFF,0x97,0xD8,0x61,0x16,0x04,0x9A}; //Sensor 1
uint8_t dev1rom[8]={0x28,0xFF,0xA0,0xD5,0x61,0x16,0x04,0xD2}; //Sensor 2
uint8_t dev2rom[8]={0x28,0xFF,0x5C,0x8A,0x61,0x16,0x03,0x94}; //Sensor 3
![]() |
Fig13. Mensaje Serial para lectura de códigos ROM |
La codificación de este procedimiento es el siguiente:
void taskBUT1(void)
{
static uint8_t state = 0, cnt;
switch(state)
{
case 0: //Detecta nivel bajo en pulsador
if(BUT1pin == 0)
{
if(cnt++ > 200) //Pulsador presionado min 200ms
state = 1;
} else cnt = 0;
break;
case 1: //Lectura del código ROM sensor
INTCONbits.GIE=0;
if(DS18Reset())
{
DS18ReadROM(dev0rom); //Comando para lectura ROM
printf("ROM CODE:");
printHEX(dev0rom[0]);
printHEX(dev0rom[1]);
printHEX(dev0rom[2]);
printHEX(dev0rom[3]);
printHEX(dev0rom[4]);
printHEX(dev0rom[5]);
printHEX(dev0rom[6]);
printHEX(dev0rom[7]);
printf("\n");
}
INTCONbits.GIE=1;
cnt = 0;
state++;
break;
case 2: //Espera liberación del pulsador
if(BUT1pin)
{
if(cnt++ > 200) //Pulsador liberado min 200ms
state = 0;
} else cnt = 0;
}
}
taskDS18(): Es la tarea principal que ejecuta el programa, ya que realizar la lectura secuencial de los tres sensores conectados al bus con intervalos de un segundo, por lo que sera necesario tres segundos para completar un ciclo de lectura de todos los sensores. Este tiempo puede ser menor, sobre todo si consideramos que el tiempo de conversion a resolución de 10-bit es aproximadamente 187ms y existe la posibilidad de ejecutar el comando de función ConverT de forma simultanea en todos los sensores, algo que no se esta aplicando en nuestro ejemplo.
Note que el procedimiento utiliza la variable devi para determinar con que sensor se establecerá la comunicación, esta variable esta condicionada en el ultimo estado. Si desea incrementar la cantidad de sensores también deberá condicionar el rango de esta variable. La figura 14 muestra los resultados que arroja el procedimiento a través del puerto serial UART.
![]() |
Fig14. Resultados de medición por UART |
A continuación se detalla la codificación del procedimiento taskDS18:
{
static uint8_t state = 0, devi = 0;
static uint16_t cnt = 0;
uint16_t res;
switch(state)
{
case 0: //Verifica y inicia conversion del sensor
INTCONbits.GIE = 0;
if(DS18Reset()) //Si hay presencia de sensor
{
if(devi == 0) DS18StartDev(dev0rom);
if(devi == 1) DS18StartDev(dev1rom);
if(devi == 2) DS18StartDev(dev2rom);
cnt = 200; //TConv 10-bit min 187ms
state = 1;
}
else
{
cnt = 1000; //Espera próxima lectura 1s
state = 2;
}
INTCONbits.GIE = 1;
break;
case 1://Lectura del sensor por turno
if(cnt-- == 0) //TConv 10-bit 187
{
INTCONbits.GIE = 0;
if(DS18Reset())
{
if(devi == 0) res=DS18GetValue(dev0rom);
if(devi == 1) res=DS18GetValue(dev1rom);
if(devi == 2) res=DS18GetValue(dev2rom);
}
INTCONbits.GIE = 1;
temr = (uint8_t) (res & 0x000F);
temr = (100/16) * temr; //1/16 = 0.0625
tem = (uint8_t) ((res & 0x7FFF) >> 4);
/*Muestra informacion de temperatura*/
putch('T');
printByte(devi);
putch(':');
printByte(tem);
putch('.');
if(temr < 10) putch('0'); //Padding 0
printByte(temr);
putch('\n');
if(devi++ >= 2) devi = 0;
cnt = 800; //Espera 800ms
state = 2; //Next state to wait
}
break;
case 2: //Intervalo de espera entre intentos
if(cnt-- == 0) state = 0;
break;
}
}
El programa completo y funcional desarrollado con MPLABX lo encontraras en el siguiente enlace a mi repositorio Git: <https://github.com/pablinza/piclab2>
También dejo este vídeo que resume la programación de PIC y las pruebas realizadas durante el laboratorio.
Las pruebas efectuadas en nuestro programa nos muestran el funcionamiento adecuado de este sensor, considerando las buenas prestaciones, su bajo coste y gran disponibilidad en las electrónicas locales, lo convierten en una excelente opción para muchas aplicaciones de medición. Seguidamente se listan algunas recomendaciones a considerar si vas a implementar un proyecto con este sensor:
Los tiempos de requerimiento utilizan retardos provisto por el compilador que fueron levemente ajustados a la frecuencias de 8MHz, en caso de usar otra frecuencia, deberá efectuar cambios en la definicion _XTAL_FREQ o en todo caso hacer uso de temporizadores para conseguir los retardos.
Debido a que los requerimientos de tiempo para validar los datos son fijos, es conveniente evitar cualquier interrupción una vez iniciada la comunicación, si el programa hace uso de interrupciones deberá considerar una correcta aplicación de los procedimientos y funciones de este proyecto.
El estado inactivo del bus siempre sera un nivel alto, si por alguna razón la comunicación es suspendida, se debe asegurar que el bus permanezca en su estado inactivo, porque de otra forma un nivel bajo mayor a 120us provocara el reinicio del bus en los dispositivos esclavos.
Puede reducir el tiempo de espera en la conversión si su aplicación no requiere de la precisión establecida por defecto de 12-bit(0.0625°C) lo que representa un mínimo de 750ms, entonces configurando a 9-bit(0.5°C) se podría reducir a tan solo 94ms.
Sin
mas que mencionar agradezco tu visita al blog y espero que el ejemplo
visto pueda ser útil en tu formación y el proyecto que desarrollas.
Atentamente, Pablo Zárate Arancibia email: pablinza@me.com / pablinzte@gmail.com, @pablinzar
Santa Cruz de la Sierra - Bolivia