Termostato con DS18B20 y 16F877A ajustable.

Bueno pues despues de romperme un poco el coco y partiendo de que soy muy novatillo en el tema, pues creo que realizado un proyecto de este termostato, que a la vez pienso que puede servir a alguien, si es asi me alegro.
De antemano tengo que decir que utilizado un poquito de infomacion de por aqui y otro poquito de por alli y algo de mi cosecha, que es muy poquito, pero bueno algo esss.
De paso, si es posible, de los que teneis mas capacidad en el tema, me gustaria que me echaseis un cable, ya que me gustaria colocar 2 o 3 sensores y hay me atasco vastante, ya que mi idea es poner la informacion en una pantalla de lcd 20x4, con la que tener controlada la temperatura del coche de ciertas zonas,de momento, y mas adelante en una GLCD, pantalla por cierto que me esta costando aprender un monton.
Una pregunta ya que hay algo que no entiendo, si cambio la frecuencia de 20 Mhz a 4 o 10Mhz en pantalla solo me sale 0.0 grados de temperatura pero si pongo 20 todo perfecto y no doy con la tecla. digo esto por que solo tengo cristales de 4 y 10Mhz. Gracias a quien me pueda explicar el por que.
Este es el codigo en C:


Código:
#include <16F877A.h>

#device adc=10

#FUSES NOWDT, HS, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT     
#use delay (clock=20Mhz)

#include <1wire.c>
#include <lcd.c>
#include <ds18b20.c>

float temperatura;
int min = 20;
int max = 28;


   
void main()
{
 lcd_init();
 
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(VREF_LOW|-2);


while (1)
{
   
   temperatura = ds18b20_read();

   lcd_gotoxy(1,1);
   printf(lcd_putc,"TEMP: %3.1f ", temperatura);
   lcd_putc(223);
   lcd_putc("C    ");
   delay_us(10);
   lcd_gotoxy(1,2);
   printf(lcd_putc,"%d<=>%d",min,max);
   
   if(temperatura <min)
      {
      delay_us(10);
   printf(lcd_putc,"   Frio  ");
   output_high(PIN_D3);
   output_low(PIN_B3);
      }
       else if (temperatura >= min && temperatura <= max){
       
       printf(lcd_putc," Perfecta  ");}
       
        if (temperatura >max){
        printf(lcd_putc,"  Calor   ");
                
   output_low(PIN_D3);
   output_high(PIN_B3);}
     
     if(input(pin_A1)==0){
     max=max+1;}
     if(input(pin_A2)==0){
     max=max-1;}
     if(input(pin_A3)==0){
     min=min+1;}
     if(input(pin_A4)==0){
     min=min-1;}
 }

}
 
Última edición por un moderador:
Aqui va un poco mas sobre el tema, con una pantalla lcd 20x4, espero que os guste.
Codigo en C:

Código:
#include <16F877A.h>
#device adc=10
#FUSES NOWDT, HS, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT     
#use delay (clock=20Mhz)
#include <1wire.c>
#include <lcd20x4.c>
#include <ds18b20.c>

float temperatura;
int min = 20;
int max = 28;
  
void main()
{
 lcd_init();
 
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(VREF_LOW|-2);


while (1)
{
   
   temperatura = ds18b20_read();

   lcd_gotoxy(1,1);
   printf(lcd_putc,"TEMP: %3.0f ", temperatura);
   lcd_putc(223);
   lcd_putc("C    ");
   delay_us(10);
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Ref(min)= %d",min);
   delay_us(10);
   lcd_gotoxy(1,3);
   printf(lcd_putc,"Ref(max)= %d",max);
   if(temperatura <min)
      {
      delay_us(10);
      lcd_gotoxy(1,4);
   printf(lcd_putc,"   Frio  ");
   output_high(PIN_D3);
   output_low(PIN_B3);
      }
       else if (temperatura >= min && temperatura <= max){
       delay_us(10);
       lcd_gotoxy(1,4);
       printf(lcd_putc," Perfecta  ");}
       
        if (temperatura >max){
        delay_us(10);
        lcd_gotoxy(1,4);
        printf(lcd_putc,"  Calor   ");
                
   output_low(PIN_D3);
   output_high(PIN_B3);}
     
     if(input(pin_A1)==0){
     max=max+1;}
     if(input(pin_A2)==0){
     max=max-1;}
     if(input(pin_A3)==0){
     min=min+1;}
     if(input(pin_A4)==0){
     min=min-1;}
 }

}

Una cosa mas si quereis el circuito de como lo he diseñado, no hay problema en subirlo.
 
Última edición por un moderador:
Pues bueno ya que veo que pasa el tiempo y a mi pregunta de como conectar 2 ds18b20 al 16f877A y nadie me da una idea, pues eso, que vuelvo a preguntar, para ver si se os ocurre alguna idea, ya que, dentro de mi lmitacion, he provado todo lo que se me ocurre pero no doy con la manera, decir que mi idea es conectar uno en RA0 y otro en RA1 y poderlo mostrar en pantalla, como lo hecho para un solo sensor.
 
Puedes hacer una función para leer los dos sensores, por ejemplo...

Void Read_DS18B20 (Int1 Sensor){
If (Sensor ==1)
{
/* Código sensor 1 */

}
Else
/* Código sensor 2 */

}

Es una sugerencia.

Saludos.
 
Saludos.
Sería la función para leer los dos sensores, obviamente todas las funciones tienen que saber que sensor controlar.
Por ejemplo, la de reset, escritura y lectura.
Algo así como esto...
Código:
Int OneWire_Read(Int1 Sensor)
{
Int Count,Data;

   If(Sensor==0)
   {
   For (Count=0; Count<8; ++Count)
   {
   Output_Low(One_Wire_Pin1);                   // Llevar a 0 el Pin RA4
   Delay_Us(2);                                 // Esperar 2uS
   Output_Float(One_Wire_Pin1);                 // Hacer entrada el Pin RA4 (Quedará en alto por Pull up)
   Delay_Us(8);                                 // Esperar a que se estabilice el dispositivo
   Shift_Right(&Data,1,Input(One_Wire_Pin1));   // Cargar el resultado
   Delay_Us(120);                               // Esperar hasta que se lea el fin del bloque.
   }
}
   Else
/* Hacer lo mismo con el otro sensor */  
    For (Count=0; Count<8; ++Count)
   {
   Output_Low(One_Wire_Pin2);
   Delay_Us(2);
   Output_Float(One_Wire_Pin2);
   Delay_Us(8);
   Shift_Right(&Data,1,Input(One_Wire_Pin2));
   Delay_Us(120);
   }
   Return(Data);
}
Entonces, si Sensor es 0, se actúa sobre un sensor, caso contrario, se actúa sobre el otro.
¿Ahora comprendes?

Suerte.
 
Perdona que haya tardado en contestar.
Vamos haber, no lo entiendo y te explico:
1º No se donde ponerlo ya que lo ponga como lo ponga el compilador me dice error
2º Dices if(sensor==0), o lo que es lo mismo, si sensor es == a 0, que ocurra todo
lo que pones dentro del for, pero claro como le digo al micro que sensor esta a 0
3º Tambien me pierdo con " output_low(one_wire_pin1);", ya que dices que pone a 0 el
RA4, pero no tiene sentido ya que yo quiero conectar, es mas he puesto, uno en el pin RA0
y otro en el pin RA1.
Espero que entiendas que me voy defenciendo poco a poco y lo que me gustaria es entender
las instrucciones y el por que, ya que si no las comprendo no voy a ser capaz de hacerlo.
 
Perdona que haya tardado en contestar.
Vamos haber, no lo entiendo y te explico:
1º No se donde ponerlo ya que lo ponga como lo ponga el compilador me dice error
2º Dices if(sensor==0), o lo que es lo mismo, si sensor es == a 0, que ocurra todo
lo que pones dentro del for, pero claro como le digo al micro que sensor esta a 0
3º Tambien me pierdo con " output_low(one_wire_pin1);", ya que dices que pone a 0 el
RA4, pero no tiene sentido ya que yo quiero conectar, es mas he puesto, uno en el pin RA0
y otro en el pin RA1.
Espero que entiendas que me voy defenciendo poco a poco y lo que me gustaria es entender
las instrucciones y el por que, ya que si no las comprendo no voy a ser capaz de hacerlo.
OK. Supuse que tenias algo de conocimientos en C.
Mira, no es difícil de entender.
Vamos a suponer que One_Wire_Pin1 es el sensor que está en el Pin RA0,
y One_Wire_Pin2 es el sensor que está en el Pin RA1.
Entonces a esos pines les ponemos un valor, One_Wire_Pin1 será el 0, y One_Wire_Pin2 será el 1, ¿OK?
Lo que se hará entonces es llamar a cada una de las funciones con el número del sensor que deseas.
Por ejemplo...
Lectura1 = Read_DS18B20 (0); // Leer el sensor 1 (en RA0)
Lectura2 = Read_DS18B20 (1); // Leer el sensor 2 (en RA1)

Como te menciono no es difícil, en cuanto llegue a casa armo la estructura y la subo, para que veas como.



;***********************************************************************
Bien, aquí adjunto el programa controlando dos sensores DS18B20
Incluyo las librerías con las funciones que no comprendías y una simulación del proyecto.

Suerte.
 

Adjuntos

  • 16F877A 2 DS18B20.rar
    21.7 KB · Visitas: 758
Última edición:
OK. Supuse que tenías algo de conocimientos en C.
Mira, no es difícil de entender.
Vamos a suponer que One_Wire_Pin1 es el sensor que está en el Pin RA0,
y One_Wire_Pin2 es el sensor que está en el Pin RA1.
Entonces a esos pines les ponemos un valor, One_Wire_Pin1 será el 0, y One_Wire_Pin2 será el 1, ¿OK?
Lo que se hará entonces es llamar a cada una de las funciones con el número del sensor que deseas.
Por ejemplo...
Lectura1 = Read_DS18B20 (0); // Leer el sensor 1 (en RA0)
Lectura2 = Read_DS18B20 (1); // Leer el sensor 2 (en RA1)

Ahora empiezo a entenderlo pero aun con alguna duda y te explico:
Yo intente, y ahora comprendo un pequeño error que cometía, en la librería que tengo de 1Wire, poner #define ONE_WIRE_PIN PIN_A0 y #define ONE_WIRE_PIN PIN_A1 y claro el compilador me decía que estaba duplicando el define, por eso cuando he visto, en la librería que tu has creado 1Wire2, hay como pones los defines: #Define One_Wire_Pin1 PIN_A4 y
#Define One_Wire_Pin2 PIN_A5, que si no te importa, yo por comodidad pondré A0 y A1, espero que no te moleste, es cuando he entendido el por que de duplicado en el compilador.

Tú dices: Lo que se hará entonces es llamar a cada una de las funciones con el número del sensor que deseas.
Por ejemplo...
Lectura1 = Read_DS18B20 (0); // Leer el sensor 1 (en RA0)
Lectura2 = Read_DS18B20 (1); // Leer el sensor 2 (en RA1)

Pues yo intente esa idea pero de diferente forma y te explico, declare el pin RA0 y RA1 como canales de entrada para leer los sensores y no habia manera, aunque también te digo que no lo tenia declarado en el código que tengo con un solo sensor y si me funcionaba bien, cosa que no entendía asta que visto lo del read_ds18b20(0); y read_ds18b20 (1);
Por otro lado te digo que, visto lo que has hecho, me queda todavía mucho por entender pero que con gente como vosotros es mucho más fácil entender estos temas.
Una pregunta, aprovechándome un poquito del tema, tu me dices si es correcto o no, si yo quisiera poner 3 sensores, tal y como tu has hecho, pero añadiendo un else, me explico tu pones if (sensor==0) y luego else, y yo te pregunto declaro los 3 define y todo lo demás y entonces lo hago con if, elseif y else, ¿Qué opinas? podría funcionar?.
 
Última edición:
en la librería que tu has creado 1Wire2, hay como pones los defines:
#Define One_Wire_Pin1 PIN_A4 y #Define One_Wire_Pin2 PIN_A5,
que si no te importa, yo por comodidad pondré A0 y A1, espero que no te moleste, es cuando he entendido el por que de duplicado en el compilador.
OK. Cosas que pasan, y no importa si modificas cualquier cosa de las librerías. (Son Freeware) :)
Lectura1 = Read_DS18B20 (0); // Leer el sensor 1 (en RA0)
Lectura2 = Read_DS18B20 (1); // Leer el sensor 2 (en RA1)

Pues yo intente esa idea pero de diferente forma y te explico, declare el pin RA0 y RA1 como canales de entrada para leer los sensores y no había manera, aunque también te digo que no lo tenia declarado en el código que tengo con un solo sensor y si me funcionaba bien, cosa que no entendía hasta que he visto lo del read_ds18b20(0); y read_ds18b20 (1);
Por otro lado te digo que, visto lo que has hecho, me queda todavía mucho por entender pero que con gente como vosotros es mucho más fácil entender estos temas.
Lo ves, cada día se aprende algo nuevo. Y gracias. :apreton:
Una pregunta, aprovechándome un poquito del tema, tu me dices si es correcto o no, si yo quisiera poner 3 sensores, tal y como tu has hecho, pero añadiendo un else, me explico tu pones if (sensor==0) y luego else, y yo te pregunto declaro los 3 define y todo lo demás y entonces lo hago con if, elseif y else, ¿Qué opinas? podría funcionar?.
Sip. Si debe funcionar y aquí pongo una muestra con 4 sensores, así que inténtalo. (y)

Suerte.
 

Adjuntos

  • 4_DS18B20_Sample.rar
    20 KB · Visitas: 296
Bueno pues como lo prometido es deuda, y aunque me ha costado un poco pues aqui esta con 3 sensores y una lcd de 20x4, espero que te guste y va por ti, gracias por haberme hechado un grandisimo cable. Si ves algo raro dimelo, entiende que voy poco a poco.
 

Adjuntos

  • 3-DS18B20.rar
    31.2 KB · Visitas: 216
Bueno pues como lo prometido es deuda, y aunque me ha costado un poco pues aquí esta con 3 sensores y una lcd de 20x4, espero que te guste y va por ti, gracias por haberme echado un grandisimo cable. Si ves algo raro dímelo, entiende que voy poco a poco.
Tras algunas modificaciones para poder compilar el programa que subiste, lo adjunto con los cambios.
Algunas funciones no estaban bien terminadas y las corregí de otra forma.
Como no incluiste la librería que usaste para controlar el LCD, use la de CCS. (LCD420.C)
También modifique el diseño de la simulación para evitar la sobre carga de memoria.
Como dato extra, también se puede hacer uso de la instrucción Switch para tal efecto.

Bien, pues ya tienes la base y podrás modificarlo a tu gusto para lo que requieras hacer.

PD. Gracias por el agradecimiento en el programa. (y)

Saludos.
 

Adjuntos

  • 3-DS18B20.rar
    45.4 KB · Visitas: 252
Mil gracias, un fallo lo de la libreria lcd, no me di cuenta, te la adjunto, la que has puesto tu la tengo pero con una pequeña modificacion para que al hacer el esquema me quede esteticamente mejor.
Tienes razon en lo de la sobrecarga de memoria, tampoco habia caido en ese detalle.
Una ultima pregunta, si no te importa, ¿por que cuando hago la prueba en proteus en la pantalla cada vez que hace la lectura de los sensores se ve como si se resetease la lectura de las temperaturas?, digo esto por que, si se puede evitar, como imagen queda mas bonito.
Te comento de paso que con un poquito de paciencia lo colocare para tener un poco mas controlada la temperatura en mi vieja renault kangoo y para mejorar el control, en el reactor, de mi produccion casera de biodiesel.
bueno un saludote y yo creo que este tema, gracias a ti a quedado muy majo, ¿no te parece?.
 

Adjuntos

  • lcd20x4.rar
    2.2 KB · Visitas: 151
Mil gracias, un fallo lo de la librería lcd, no me di cuenta, te la adjunto, la que has puesto tu la tengo pero con una pequeña modificación para que al hacer el esquema me quede estéticamente mejor.
OK. Ya hice pruebas con la librería y funciona bien, salvo que produce advertencias por contención lógica.
Esto en proteus, ya que físicamente no hay problemas al mostrar los datos en la pantalla.
No tengo una de 20x4 como la de tu proyecto, pero hice las pruebas con una de 16x2 y todo bien.
Una última pregunta, si no te importa, ¿por que cuando hago la prueba en proteus en la pantalla cada vez que hace la lectura de los sensores se ve como si se resetease la lectura de las temperaturas?, digo esto por que, si se puede evitar, como imagen queda mas bonito.
Eso es normal al estar borrando la pantalla cada vez que se muestra una nueva lectura de datos.
Y se realiza aquí: printf(lcd_putc,"\fTemp1: %03.2f ßC ",temp1);
\f es el comando para borrar la pantalla, y \n es el comando para pasar a la siguiente línea.
Se puede evitar el parpadeo de la pantalla si se hace esto.
Código:
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Temp1: %03.2f ßC     ",temp1);
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Temp2: %03.2f ßC     ",temp2);
   lcd_gotoxy(1,3);
   printf(lcd_putc,"Temp3: %03.2f ßC     ",temp3);
Con los espacios que se colocan después de mostrar los datos, se garantiza borrar todos los caracteres.
Y ahí ya van 5 espacios por línea, que harán que se borren los caracteres que existan de una escritura previa.
Te comento de paso que con un poquito de paciencia lo colocare para tener un poco mas controlada la temperatura en mi vieja renault kangoo, y para mejorar el control en el reactor de mi producción casera de biodiesel.
Bueno un saludote y yo creo que este tema, gracias a ti a quedado muy majo, ¿no te parece?.
Bien hecho, algo vi sobre eso en Discovery Channel, y me parece muy bien. (y)
Y pues si, ya cambio de 2 sensores a 3, y como te diste cuenta, se puede aumentar la cantidad sin problemas.
El problema es que con cada sensor agregado, se va aumentando el tiempo de proceso.

Bien, pues ahora agrega esas nuevas líneas de código y ve como funciona la pantalla con ese cambio.

Suerte, y gracias por los comentarios.
 
Hola, una preguntilla, ¿es posible poner dos termómetros en un mismo bus one wire, o hay que ubicarlos en buses diferentes? Tengo entendido que con un solo bus se pueden controlar varios dispositivos one wire, lo que ya no se es si se puede con dos dispositivos iguales.
 
Hola, una preguntilla, ¿es posible poner dos termómetros en un mismo bus one wire, o hay que ubicarlos en buses diferentes? Tengo entendido que con un solo bus se pueden controlar varios dispositivos one wire, lo que ya no se es si se puede con dos dispositivos iguales.

Hola..se puede controlar mas de un dispositivo en el mismo "bus"( no recuerdo cuantos pero el identificador es de 64bit) aunque sean del mismo tipo debido a que cada uno tiene un identificador único...el problema pasa por "hacerse" de dicho identificador con un "bus" con varios dispositivos "hablando" y depurar el de todos ellos para después direccionar la informacion de cada dispositivo en sí.
Saludos.

Ric.
 
Última edición:
Hola,

Muchas gracias por contestar, ya tengo dos termómetros funcionando en un mismo bus one wire, lo que hago es, como bien dices, en primer lugar identificar e número de termómetros que hay en el bus y su código de 64 bit, los almaceno en una variable de arrays, destinada para tal fin (asocio un código al dispositivo 1, 2, 3 ...), para finalmente leer el termómetro que yo elija.

Me he ayudado de una biblioteca en c que encontré en la red (la cual he adaptado a mi biblioteca one wire), del manual del ds18b20 y del driver one wire creado por mi para mi MCU.

Lo único extraño que no logro averiguar es lo siguiente:

Mi MCU te da la opción de configurar la patilla en modo Pull-up, sin necesidad de colocar resistencia de pull-up, pues bien, si configuro la patilla como no-pull y le coloco la resistencia de 4k7 de pull-up no me funciona el bus one wire, sin embargo, sin resistencia y configurando la patilla como pull-up sí.

Por poner un ejemplo, con el bus I2C, me funciona de las dos maneras, pero prefiro ponerlo con resistencias externas, así que con el one wire me conformaré con que me funcione.

Es un poco lioso de explicar... lo se.

De todas formas solo escribía para darte las gracias puesto que tu post, aunque no lo creas, me ha ayudado mucho para conseguir que todo funcione.

saludos,

juankry
 
Hola,

Muchas gracias por contestar, ya tengo dos termómetros funcionando en un mismo bus one wire, lo que hago es, como bien dices, en primer lugar identificar e número de termómetros que hay en el bus y su código de 64 bit, los almaceno en una variable de arrays, destinada para tal fin (asocio un código al dispositivo 1, 2, 3 ...), para finalmente leer el termómetro que yo elija.

Me he ayudado de una biblioteca en c que encontré en la red (la cual he adaptado a mi biblioteca one wire), del manual del ds18b20 y del driver one wire creado por mi para mi MCU.

Lo único extraño que no logro averiguar es lo siguiente:

Mi MCU te da la opción de configurar la patilla en modo Pull-up, sin necesidad de colocar resistencia de pull-up, pues bien, si configuro la patilla como no-pull y le coloco la resistencia de 4k7 de pull-up no me funciona el bus one wire, sin embargo, sin resistencia y configurando la patilla como pull-up sí.

Por poner un ejemplo, con el bus I2C, me funciona de las dos maneras, pero prefiro ponerlo con resistencias externas, así que con el one wire me conformaré con que me funcione.

Es un poco lioso de explicar... lo se.

De todas formas solo escribía para darte las gracias puesto que tu post, aunque no lo creas, me ha ayudado mucho para conseguir que todo funcione.

saludos,

juankry


Ok...Entiendo que te funciona con el Pull-up interno programable del MCU pero no al des-habilitar el mismo y hacerlo mediante una resistencia externa...es extremadamente raro pero no se que MCU estas usando y como tiene implementada dicha salida/entrada en cuanto al hardware interno en el momento que se des-habilitan dichas "resistencia"...en los proyectos que he echo no he tenido la necesidad de compartir el bus así que por simplicidad a la hora de programar y viendo las complicaciones que acarreaba el echo de identificar los dispositivos opte por tenerlos independientes y alimentados externamente así como su Pull-up.
Ric.
 
Última edición:
hola darbyte disculpa con que programa puedo compilar tu archivo que dejas
y con que programa funciona su archivos que dejan por que yo lo quiero compilar en mikroC v6.0 y me sale error
 
Atrás
Arriba