Termómetro de precisión de dos canales con PIC y sensores DS18B2

Buenas noches colegas
Quedó pendiente en el desarrollo de este proyecto:

Reloj digital/Calendario/Posicionador Geográfico/Termómetro sincronizado por módulo GPS

El diseño del Termómetro de dos canales con con PIC y sensores DS18B20, que mide e indica la temperatura externa e interna del gabinete del equipo, y controla el encendido del ventilador de refrigeración de los Tubos.
Para recordar, en este video del Reloj se ven en la parte derecha los dos displays de los dos canales del Termómetro



Aquí pueden verse las primeras pruebas con los displays, el PIC y los dos DS18D20 dispuestos en protoboard
Luego de una inicialización del PIC y test del display de 4 dígitos, la medición de temperatura en ambos canales se efectúa en simultaneo (alrededor del Seg. 18 del video)
El diseño prevé dos dígitos para el canal A que muestra 19.9 grados (las indicaciones de enteros y decimales 19 y 9.9 se alternan en los dos primeros dígitos)
Y dos dígitos para el canal B que muestra 20.4 grados (20 y 0.4 se alternan en los dos últimos dígitos)
También puede verse en el osciloscopio, las secuencias de pulsos seriales de acceso a los dos sensores DS18D20




El diagrama de bloques del diseño será el siguiente:

Termometro.jpg

Aquí el Termómetro ya funcionando en la plaqueta prototipo:



El programa del PIC comienza testeando los displays de matriz de puntos que son del tipo HP5082-7300 cuya hoja de datos es la siguiente:

displayhp.jpg

Estos displays son del tipo de matriz de puntos con driver y decodificador BCD incluido. Tienen cuatro entradas A,B,C,D de código BCD, una entrada DP para el punto decimal, y una entrada de control ST (Strobe) que habilita y carga el código.
Entonces como se ve en el video en los primeros 10 segundos, el programa testea las 16 combinaciones de las entradas ABCD y el display muestra los 10 números y luego otros símbolos de las combinaciones no BCD.

Continua...
 
Última edición:
Continuando, las hojas de datos de los sensores de temperatura DS18B20 pueden verse aquí:

18b20.pdf

Cada sensor DS18B20 tiene un único ID de 64 bytes que lo identifica (64-BIT LASERED ROM).
El primer byte de todo ID es un identificador de tipo de sensor ( 28h) . Como se ve, en este diseño cada sensor se maneja con una línea de datos separada (RA0 y RA1) entonces no hace falta identificar varios sensores conectados en una misma línea, el programa sólo lee los dos primeros bytes del ID de los dos sensores para verificar su presencia. En caso que un sensor no esté conectado o no responda, el display mostrará un guion (-) en lugar de su ID.
En el video anterior, en los segundos 12 y 14 se ven los ID de ambos sensores que indican que efectivamente están en línea, en uno 28 91, en el otro 28 XX.
Luego de este testeo de presencia, arranca la medición de temperatura y se muestra en los displays, los dos dígitos de arriba corresponden al Sensor DS0 que será el de temperatura interna del Reloj, y los dos dígitos de abajo corresponden al Sensor DS1 que será el de temperatura externa o ambiente.
Ambos sensores DS18B20 trabajan en alta precisión de 12 bits por lo cual los displays que tienen sólo dos dígitos, muestran alternadamente decenas - unidades y unidades - decimales de los valores de temperatura.
Esto puede verse a partir del segundo 15 del video, los display alternan entre 21 y 1.5 ó 1.4 indicando una temperatura de 21.5 ó 21.4 ºC. Los dos sensores pueden verse ahí cercanos a la plaqueta con sus cables, por lo cual medirán valores similares.
A partir del segundo 31 del video puede verse el seteo de temperatura de encendido del ventilador del Reloj con los switches de Down (RA3) en 40, 39, 38... y de Up (RA2) en 30, 31, 32...45

Entonces en este caso el DS0 responde con los códigos exadecimales 28 91, y el DS1 responde 28 XX (el XX no se ve porque es un valor exadecimal no displayable). Los restantes 62 bytes de los ID no son leidos pues no hacen falta ya que como vimos, el DS0 se maneja exclusivamente con la linea RA0 y el DS1 con la linea RA1.

Entonces, la secuencia del programa para leer los dos primeros bytes del ID del sensor DS0 de acuerdo al procedimiento aconsejado en su hoja de datos, actuando el PIC como Master y el DS0 como Slave, será la siguiente:

1) Coloca RA0 como salida (TRISA0 = 0) y coloca un estado Bajo ("0") durante 480 uS (Master Reset Pulse)
2) Coloca RA0 como entrada (TRISA0=1), espera de 15 uS a 60 uS y sensa el estado Bajo ("0") de respuesta del DS0 (Slave Presence Pulse) de 60 a 240 uS.
Si el pulso de presencia es detectado significa que el sensor está conectado y listo, en cambio si no se detecta durante un timeout de 480 uS, significa que el sensor no está o no funciona. En ese caso el programa mostrará guiones en el display indicando que el Master Reset falló.
3) Una vez que se detecta la presencia del sensor DS0 y este libera la línea de datos, pasa RA0 nuevamente como salida
4) El Master (PIC) envía sobre la línea, el Read ID Command byte (33h) y a continuación invierte RA0 como entrada
5) Lee el primer byte del ID, lo guarda en memoria. Lee el segundo byte del ID y lo guarda en memoria. Los restantes 62 bytes del ID no son leidos
6) Muestra ambos valores leidos en el display.

A continuación, la secuencia del programa para leer los dos primeros bytes del ID del sensor DS1 será la misma sobre su línea RA1.
Y ambos valores leídos se mostrarán a continuación en el display como puede verse en el video.

Luego de leer y mostrar ambos ID de ambos sensores, el programa entrará en el lazo de medición, muestra y comparación de la temperatura en ambos sensores.
Estos estarán por defecto en su máxima resolución de 12 bits y tendrán un tiempo de conversión de 750 mS.

La medición de temperatura en el DS0 se inicia con la siguiente secuencia:
1) Coloca RA0 como salida y envía el pulso de Reset (Master Reset Pulse)
2) Coloca RA0 como entrada y se verifica el pulso de respuesta del DS0 (Slave Presence Pulse)
3) Coloca RA0 como salida
4) El Master (PIC) envía sobre la linea, el Skip ROM Command byte (CCh)
5) El Master (PIC) envía sobre la linea, el Start Conversion Command byte (44h)
6) Coloca RA0 como entrada, el DS0 (Slave) colocará un Bajo "0" en la línea mientras dura la conversión de temperatura (750 mS)

7) A continuación, La medición de temperatura en el DS1 se inicia con misma secuencia sobre la línea RA1
8 ) Entra en el lazo de espera de fin de conversión sensando el estado Bajo "0" en RA0 forzado por el DSO mientras convierte
9) Una vez que el tiempo de conversión del DS0 finaliza indicado por la liberación de la línea RA0, se verifica también la finalización de conversión en el DS1 indicado por la liberación de la línea RA1.
Ambos sensores disparan su conversión en forma casi simultánea por lo cual ambos tendrán la medición lista en el mismo período de 750 mS

Una vez que se verifica que ambos sensores terminaron su conversión de temperatura, se leen los valores con la siguiente secuencia:

1) Coloca RA0 como salida y envía el pulso de Reset (Master Reset Pulse)
2) Coloca RA0 como entrada y se verifica el pulso de respuesta del DS0 (Slave Presence Pulse)
3) Coloca RA0 como salida
4) El Master (PIC) envía sobre la línea, el Skip ROM Command byte (CCh)
5) El Master (PIC) envía sobre la línea, el Read Scratchpad Command byte (44h), los dos primeros bytes recibidos serán el valor de temperatura en 12 bits
6) Coloca RA0 como entrada
7) Lee el primer byte del Scratchpad, son los 8 bits de menor peso (LS byte) donde están las unidades y los decimales
8 ) Lee el segundo byte del Scratchpad, son los 8 bits de mayor peso (MS byte) donde están los signos y las decenas

El formato de ambos bytes y los pesos de los bits será el siguiente:

LS byte 2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 2^-4 (unidades y decimales)
MS byte S S S S S 2^6 2^5 2^4 (bits de signo y decenas)

Los S son los bits de Signo que serán 0s con temperaturas positivas, el rango a mostrar será de 00.0 ºC a 99.9 ºC

Ejemplos de lectura de temperatura (ver manual del DS18B20)
- Temp= +125 °C , se lee 07D0h, o sea 7x16+13 = 125 . El ultimo digito son los decimales, que son cero
- Temp= +25.0625°C, se lee 0191h, o sea 2x16+5+ 0,0625 x 1 (la resolución en 12 bits es 0,0625 ºC)
- Temp= +0.5°C, se lee 0008h, o sea 0,0625 x 8 = 0,5

La conversión de los valores binarios leídos en los bytes MS y LS a los valores BCD a mostrar en los displays será por tablas en EPROM
El contenido de la tabla de conversión para decenas y unidades será simple, se direcciona con decenas y unidades en binario (hexadecimal) y se obtiene el valor a mostrar en BCD:
Tabla: (arranca en la posición 00h de la EPROM)
de 0x00 ; 00
de 0x01 ; 01
de 0x02 ; 02
de 0x03 ; 03
de 0x04 ; 04
de 0x05 ; 05
de 0x06 ; 06
de 0x07 ; 07
de 0x08 ; 08 - Ejemplo: si los MS y LS bytes son 0080 , el valor BCD a mostrar en decenas y unidades será 08
de 0x09 ; 09
de 0x10 ; 0A
de 0x11 ; 0B
de 0x12 ; 0C
de 0x13 ; 0D - Ejemplo: si los MS y LS bytes son 00D0 , el valor BCD a mostrar en decenas y unidades será 13
de 0x14 ; 0E
de 0x15 ; 0F
...la tabla continua hasta los valores finales...
de 0x90 ; 5A
de 0x91 ; 5B
de 0x92 ; 5C
de 0x93 ; 5D
de 0x94 ; 5E
de 0x95 ; 5F - Ejemplo: si los MS y LS bytes son 05F0 (16x5+15), el valor BCD a mostrar en decenas y unidades será 95
de 0x96 ; 60
de 0x97 ; 61
de 0x98 ; 62
de 0x99 ; 63 - Ejemplo: si los MS y LS bytes son 0630 (16x6+3) , el valor BCD a mostrar en decenas y unidades será 99

El contenido de la tabla de conversión para los decimales será el siguiente, se direcciona con el nibble de decimales ( 2^-1 2^-2 2^-3 2^-4) del LS byte en binario (hexadecimal), y se obtiene el valor redondeado a mostrar en BCD (la resolución en 12 bits es 1/16 o sea 0,0625 ºC)

Tabla (empieza en la posición 70h de la EPROM):
de 0x00 ;70 0 0,0000
de 0x01 ;71 1 0,0625 - se redondea en 1
de 0x01 ;72 2 0,1250
de 0x02 ;73 3 0,1875 - Ejemplo: el nibble de decimales es 3 (03h), la dirección de memoria será 73h, el valor de temp será
de 0x02 ;74 4 0,2500 0,0625x3=0,1875 ºC, el valor redondeado retornado para mostrar será 2
de 0x03 ;75 5 0,3125
de 0x04 ;76 6 0,3750 -se redondea en 4
de 0x04 ;77 7 0,4375 -se redondea en 4
de 0x05 ;78 8 0,5000
de 0x06 ;79 9 0,5625 -se redondea en 6
de 0x06 ;7A A 0,6250
de 0x07 ;7B B 0,6875 - Ejemplo: el nibble de decimales es B (0Bh), la dirección de memoria será 7Bh, el valor de temp. será
de 0x07 ;7C C 0,7500 0,0625x11=0,6875 ºC, el valor redondeado retornado para mostrar será 7
de 0x08 ;7D D 0,8125
de 0x09 ;7E E 0,8750
de 0x09 ;7F F 0,9375

Luego agregaré algo del código que hace todo esto.

Saludos
 
Código de programa ( parcial)

;------------------------------------------------------
;empezar lecturas

;Manejo de los sensores DS18B20, S0 (en A0) y S1 (en A1)
;se usa el clock interno de 4MHz, se hacen lazos para generar los retardos
;Inicializacion del DS: poner un 0 de 480 uS minimo, despues liberar la linea, esperar 15 a 60 uS
; el DS deberá poner un 0 de 60 a 240 uS. Si en 480 uS no contesta, no esta el sensor
; la linea es única y bidireccional para cada sensor, siempre estará como entrada manejada por el Pull Up o el DS
; para poner un cero, el cero ya está puesto, solo pongo el pin como salida
;------------------------------------------------------------------------

;1) Leer el ID del DS0, solo los dos primeros bytes del ID de 48 bytes son leidos y mostrados
leer_S0 ; (el display no da para mas)
call init_S0 ;mandar el pulso Reset Init del DS0
btfsc BITDS0,7 ;Testear el init fallado que retorna el Flag de error. - Si el DS0 no está o no
goto leer_S0 ;si se encendio el flag de error reintentar - contesta el lazo continua y el display
; - queda indicando el codigo de error guion
movlw 0x33 ;mandar el read ID command
movwf TXBYTE ;
call txbyte0 ;al Sensor0
;
call rxbyte0 ; leer el primer byte ID0 (segun el manual es el ID de typo y es 28)
movfw RXBYTE ; aca retorna el ID leido
movwf DS0UN ; para mostrarlo se guarda en el registro de unidades
movwf DS0DE ; y en el registro de decenas
swapf DS0DE,1 ; se intercambian los bits de decenas
; solo se mostraran según los 4 bits < peso en ABCD del display, aparecerá el 28 en el display
call rxbyte0 ; leer el segundo byte ID0 de abajo
movfw RXBYTE
movwf DS1UN ;y se opera igual con el display de arriba,
movwf DS1DE ;aparecera el valor del segundo byte en el display de arriba
swapf DS1DE,1 ;ojo por ahi es un codigo no visible y el display muestra cualquier cosa
;
clrf DP3210 ;apagar los DP puntos decimales de los dos displays
call d0deun ;entonces se usan los 4 displays para mostrar los dos 1ros bytes del ID del S0
call d1deun ;estan son las rutinas que strobean decenas y unidades en los displays
;y se borra el codigo de error guion

call ret07 ;retardo para ver el ID , solo los dos primeros bytes
call ret07
call ret07

; goto init_e0

init_e1
call guion4 ;indicar por default el error de sensor no presente
;si el sensor responde se borrara

;2) Leer el ID del DS1, solo los dos primeros bytes del ID de 48 bytes son leidos y mostrados
leer_S1
call init_S1 ;mandar el pulso Reset Init del DS1
btfsc BITDS0,7 ;Testear si vuelve el Flag de Init fallado
goto leer_S1 ;si se encendio el flag de error reintentar ¡¡¡LEER TODOS LOS
; COMENTARIOS DEL
movlw 0x33 ;mandar el read ID command SENSOR 0 !!!
movwf TXBYTE ;
call txbyte1 ; al S1
;
call rxbyte1 ; leer el primer byte ID (28)
movfw RXBYTE ; aca se carga el ID leido
movwf DS1UN ; para mostrarlo
movwf DS1DE
swapf DS1DE,1
;
call rxbyte1 ; leer el segundo byte ID
movfw RXBYTE
movwf DS0UN ;para mostrarlo
movwf DS0DE
swapf DS0DE,1
;
clrf DP3210 ;apagar los DP
call d0deun ;se usan 4 displays para mostrar los dos 1ros bytes del ID
call d1deun ;

call ret07 ;retardo para ver el ID
call ret07
call ret07

; goto init_e0

call guion4 ;volver a poner el código de error en los 4 display
;-----------------------------------------------

;3) Iniciar medición de temperatura sensor S0
init_T0

init_TX
call init_S0 ;mandar el pulso Reset Init
btfsc BITDS0,7 ;Testear el init fallado
goto init_TX ;si se encendió el flag de error reintentar
;
movlw 0xCC ;mandar el ROM command SKIP ROM 1100.1100
movwf TXBYTE ;
call txbyte0 ;mandar a S0

movlw 0x44 ;start conversion command
movwf TXBYTE ;
call txbyte0 ;arranca la conversión en el S0

;--------------------------------------------------------------
;4) Iniciar medición de temperatura sensor S1
init_T1
call init_S1 ;mandar el pulso Reset Init
btfsc BITDS0,7 ;Testear el init fallado
goto init_T1 ;si se encendió el flag de error reintentar
;
movlw 0xCC ;mandar el ROM command SKIP ROM 1100.1100
movwf TXBYTE ;
call txbyte1 ;mandar a S1

movlw 0x44 ;start conversion command
movwf TXBYTE ;
call txbyte1 ;arranca la conversion en el S1

;Ambos sensores estan midiendo y convirtiendo con presicion de 12 bits, tardan 750 mS

lazo_T0 ;sensar si el S0 terminó, ojo que ambos laburan juntos, cuando S0 termine, seguro tambien termina S1
; call chkvnt ;llamar chequear ventilador ESTO NO VA, LO MANDO DIRECTO
call read_d0 ;mientras convierte el DS0 va a poner 0s en lectura de su linea de datos
btfss BITDS0,0
goto lazo_T0
;se lee un 1, la conversión termino, el valor esta en los registros internos del S0
lazo_T1
; call chkvnt ;llamar chequear ventilador
call read_d1 ;mientras convierte el DS1 va a poner 0s en lectura de su linea de datos
btfss BITDS0,0 ;- de este lazo sale al toque porque el lazo anterior
goto lazo_T1 ;- ya tardo los 750 mS para que ambos sensores conviertan
;se lee un 1, la conversion termino, el valor de la temp esta en los registros internos del S1


;5) Los valores están listos, leer valores de temperatura de los dos sensores en 12 bits
; Leer la temperatura en 12 bits (configuración power up default) , los bits vienen en dos bytes asi:
; LS byte 2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 2^-4 acá vienen unidades y decimales
; MS byte S S S S S 2^6 2^5 2^4 acá vienen decenas y signos
; los S son los bits de Signo que serán 0 con temperaturas positivas, - el rango a mostrar sera
; los de exponentes negativos son los decimales - de 00.0 a 99.9 en BCD
; Ejemplos de la pagina 4 del manual
; Temp= +125 °C , se lee 07D0h, o sea 7x16+13 = 125 . El ultimo dígito son los decimales, son cero
; Temp= +25.0625°C, se lee 0191h, o sea 2x16+5+ 0,0625 x 1 (la resolución en 12 bits es 0,0625)
; Temp= +0.5°C, se lee 0008h, o sea 0,0625 x 8 = 0,5
;
;La visualización será en dos digitos alternando decenas y unidades, con unidades y decimales
;Por ejemplo si la temp en BCD es 37.5 se vera 2 segundos 37 con DP apagado, y 2 segundos 7.5 con DP encendido
;Aca no hay signo, porque se supone que las temp serán siempre positivas
;
;Leer los registros de ambos sensores y mostrar los valores convertidos a BCD en los displays
leer_T0 ;leer el sensor S0
...
Con esto doy por finalizado el hilo
Cualquier duda a disposición
Saludos
 
Atrás
Arriba