# LM35 + PIC programación en PIC C



## Orfiel (Jul 15, 2012)

Hola a todos 

Estoy haciendo un proyecto de temperatura con lm35 y el 16F877A programando en PIC C, el código lo conseguí en Internet y le cambie algunas cosas y lo e terminado. Lo simule en proteus funciona de maravilla sin ningún tipo de errores. Pero el problema es cuando lo pruebo físicamente  ya que las lecturas varían mucho y muestran números muy elevados o muy pequeños, las lecturas varían constantemente sin permanecer fijo, ejemplo esta en 70°C y pasa a 120°C o a 10°C o 0°C. No se que puede estar pasando.
Aquí les dejo el código para que lo observen:


```
#include <LM_35.h>
#include <LCD.c>

void main()
{
   lcd_init();
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);
   //setup_pp(PMP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);

   //TODO: User Code
   
   float temper,medicion;

   printf(LCD_PUTC, "\f");    // limpia o borra el LCD
   lcd_gotoxy(1,1);
   printf(LCD_PUTC, "Termometro");
   delay_ms(2000);
   
   printf(LCD_PUTC, "\f");
      lcd_gotoxy(1,1);
      printf(LCD_PUTC, "Tempet: ");
      delay_ms(2000);
   
   while (true){
   
      lcd_gotoxy(1,1);
      printf(LCD_PUTC, "");
      
      setup_adc_ports(AN0);
      setup_adc(ADC_CLOCK_INTERNAL);
      set_adc_channel (0);                // Elige canal a medir RA0
      delay_us (10);
      medicion=read_adc ();              // Hace conversión AD 
      setup_adc (adc_off);                // Apaga ADC
      temper=medicion*(0.48875);     // Pasa binario a °C
  
      printf(lcd_putc,"%02.3f",temper);   // xxx.x °C
      delay_ms (1000);
      }

   

}
```


----------



## Limako (Jul 15, 2012)

yo te recomendaria hacer esto lo primero, para evitar repetir procesos en el bucle while.
-estas tres lineas las pondria en los encabezados:
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel (0); // Elige canal a medir RA0
-quitaria esta linea:
setup_adc (adc_off); // Apaga ADC
- y bueno lo de pasar de bianrio a ºC mejor que lo expliques que yo no entinedo esa conversion jajaja

y bueno tal vez podrias cambiar la veocidad del conversor analogico setup_adc(ADC_CLOCK_INTERNAL);

tambien puede ser fallo en el montaje


----------



## Rigeliano (Jul 15, 2012)

Como es el circuito que montaste. A mi me parece que si lo conectas directo al PIC este va llegar a solo 1V cuando tenga 100 grados con lo cual pierdes presicíon, el ADC siempre va oscilar pero si oscila por ejemplo +-20mV son 40 grados de diferencia entre las lecturas maximas y minimas, creo que deberias de amplificar primero la señal X3 por lo menos para que cuando tengas 150C este te de un maximo de 4.5V.


----------



## Orfiel (Jul 15, 2012)

Rigeliano dijo:


> Como es el circuito que montaste. A mi me parece que si lo conectas directo al PIC este va llegar a solo 1V cuando tenga 100 grados con lo cual pierdes presicíon, el ADC siempre va oscilar pero si oscila por ejemplo +-20mV son 40 grados de diferencia entre las lecturas maximas y minimas, creo que deberias de amplificar primero la señal X3 por lo menos para que cuando tengas 150C este te de un maximo de 4.5V.



Pues si lo estoy conectando directamente al PIC, en la simulación funciona bien pero ya físico varia mucho sucesivamente de 80°C a 15°C de 35°C a 100°C inclusive de 70°C a 0°C 
Ahí adjunto el plano del circuito.





Limako dijo:


> yo te recomendaria hacer esto lo primero, para evitar repetir procesos en el bucle while.
> -estas tres lineas las pondria en los encabezados:
> setup_adc_ports(AN0);
> setup_adc(ADC_CLOCK_INTERNAL);
> ...




jejejeje cambio la linea que me dijiste y funciono en la simulación pero ya en la parte física no siguió el mismo error. Revisare lo del montaje.
Lo del proceso de conversión lo tome de una pagina y aquí esta la explicación:

el "0.48875" sale de dividir 5/1023 y el resultado de eso multiplicarlo por 100
el 5 sale de los 5 voltios aplicado a el voltage de referencia, los 1023 salen
de los 10 bit de resolucion del conversor analogico digital que seleccionamos.
Si utlizaramos la resolucion de 8 bits del conversor analogico digital, la
formula fuera (5/255)*100 ya que con 8 bits el numero maximo posible es de 0-255


----------



## Rigeliano (Jul 15, 2012)

Prueba con un condensador entre el ADC y tierra 100nF por ejemplo y si con eso no basta entonces tienes que amplificar la señal como te dije y recalcular tus valores de salida.


----------



## Dano (Jul 15, 2012)

Rigeliano dijo:


> Como es el circuito que montaste. A mi me parece que si lo conectas directo al PIC este va llegar a solo 1V cuando tenga 100 grados con lo cual pierdes presicíon, el ADC siempre va oscilar pero si oscila por ejemplo +-20mV son 40 grados de diferencia entre las lecturas maximas y minimas, creo que deberias de amplificar primero la señal X3 por lo menos para que cuando tengas 150C este te de un maximo de 4.5V.



+1

O usas un amplificador, o modificas V+ REF


----------



## bombu29 (Jul 16, 2012)

El lm35 a temperatura máxima te tira 1.5v osea que si usas +vref a 5 voltios tenes 1023 bytes máximos que con 1.5v de tu sensor estas usando 307 bytes nomas. Después de eso se te mete interferencia y por eso tenes tanta oscilación. 

Hace como te dicen ellos Pone VRef a 1.5voltios o utiliza un amplificador no inversor que te entregue a la salida 5v cuando en la entrada tengas 1.5


----------



## Orfiel (Jul 17, 2012)

Hola a todos 
Hice lo que me sugirieron puse una etapa de amplificación de la señal que salia del lm35 y deje el vref a 5V.
Normalmente donde vivo la temperatura oscila entre 28°C - 37°C, al probarlo físicamente arrojaba una temperatura de 90°C lo cual es muy elevada fuera de los rangos normales pero ya no oscilaba tanto como anteriormente.
Se me dio por quitar la etapa y de amplificación y conecte la salida del lm35 al PIC directamente como lo tenia anteriormente y sorprendentemente esta funcionando correctamente marcando 34°C que era la temperatura en ese momento.
La verdad no se que habrá pasado... pero ya funcionara jejejejeje
De todas maneras muchas gracias a todos porque me han aclarado muchas dudas y e aprendido un poco mas sobre esto.



Ahora probare con sensores un poco mas profesionales que el lm35 por así decirlo.
Con uno que tiene incorporado un sensor de temperatura y humedad.
Con otro de solo humedad.
Mas adelante les comentare como me fue.


----------



## julrockk (Sep 26, 2012)

Me encuentro en un lio, pues  estoy realizando un sensor de temperatura con el lm35 para así visualizar su información en el display lcd y adyacentemente reducir la temperatura para mantenerla estable.
Sin embargo solo he tenido éxito en las simulaciones, ya que al montar el circuito este no me funciona.  

Así que de verdad me vendría bien una ayuda, para saber cual es mi error.
Este es mi programa:


```
#include <16F876A.h>
#fuses NOWDT,XT
#use delay(clock=4000000)

#include <ce_lcd.c>

void main() {
   
   lcd_init();
   delay_ms(6);
   
   printf(lcd_putc,"Sensor On");
   delay_ms(500);
   
   int x=0,temp=0;
   setup_adc_ports(AN0_VREF_VREF);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_spi(SPI_SS_DISABLED);
   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(FALSE);
   set_adc_channel(0);
   lcd_init();
   delay_ms(100);
   lcd_gotoxy(0,1);
    do //define un bucle infinito
   {
   
   x=read_adc();                                
   temp=(x*2)/5;
  
   lcd_gotoxy(1,1);                             
   printf(lcd_putc,"TEMPERATURA (C°) ");       
   lcd_gotoxy(1,2);                            
   printf(lcd_putc,"%03u",temp);                
   delay_ms(500);
   output_toggle(pin_b2);
   
   if
   (temp>20)
   {
   output_high(pin_b0);
   output_low(pin_b1);
   }  
   
   else {
   
   output_low(pin_b0);
   output_low(pin_b1);
   }
   
   }while(TRUE);
   
   
}  
   

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


ce_lcd:

   

struct lcd_pin_map {                
           BOOLEAN unused;           
           BOOLEAN rw;               
           BOOLEAN rs;               
           BOOLEAN enable;           
           int     data : 4;         
        } lcd;


#if defined use_portb_lcd
   #locate lcd = getenv("sfr:PORTB")    
   #define set_tris_lcd(x) set_tris_b(x)
#else
   #locate lcd = getenv("sfr:PORTC")    
   #define set_tris_lcd(x) set_tris_c(x)
#endif


#define lcd_type 2           
#define lcd_line_two 0x40    


BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
                            
                            


                           
                            

struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; 
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; 



BYTE lcd_read_byte() {
      BYTE low,high;
      set_tris_lcd(LCD_READ);
      lcd.rw = 1;
      delay_cycles(2);
      lcd.enable = 1;
      delay_cycles(10);
      high = lcd.data;
      lcd.enable = 0;
      delay_cycles(10);
      lcd.enable = 1;
      delay_us(10);
      low = lcd.data;
      lcd.enable = 0;
      set_tris_lcd(LCD_WRITE);
      return( (high<<4) | low);
}


void lcd_send_nibble( BYTE n ) {
      lcd.data = n;
      delay_us(50);
      lcd.enable = 1;
      delay_us(50);
      lcd.enable = 0;
      delay_ms(1);
}


void lcd_send_byte( BYTE address, BYTE n ) {

      lcd.rs = 0;
      while ( bit_test(lcd_read_byte(),7) ) ;
      lcd.rs = address;
      delay_us(50);
      lcd.rw = 0;
      delay_us(50);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
      delay_ms(1);
}


void lcd_init() {
    BYTE i;
    set_tris_lcd(LCD_WRITE);
    lcd.rs = 0;
    lcd.rw = 0;
    lcd.enable = 0;
    delay_ms(50);
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(10);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
       lcd_send_byte(0,LCD_INIT_STRING[i]);
}


void lcd_gotoxy( BYTE x, BYTE y) {
   BYTE address;

   if(y!=1)
     address=lcd_line_two;
   else
     address=0;
   address+=x-1;
   lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy(1,2);        break;
     case '\b'   : lcd_send_byte(0,0x10);  break;
     default     : lcd_send_byte(1,c);     break;
   }
}

char lcd_getc( BYTE x, BYTE y) {
   char value;

    lcd_gotoxy(x,y);
    while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
    lcd.rs=1;
    value = lcd_read_byte();
    lcd.rs=0;
    return(value);
}
```


----------



## jose011 (Oct 24, 2012)

Hola comunidad electrónica!! tengo un problemilla, cuando compilo este programa que adjunto no me da error pero cuando lo pruebo en proteus no me funciona, no se que me falta en el programa o me sobra. Quiero que me lea el valor de temperatura (LM35) y lo muestre por la barra de leds según la temperatura, a más temperatura mas leds encendidos. Espero que me podáis dar ideas para solucionarlo y que funcione.


----------



## tannke (Oct 24, 2012)

Bueno, mirando por encima y suponiendo que no tienes ningun error de programación (no uso ccs), decirte que el lm35 da una tensión proporcional a la temperatura, creo recordar que 10mV por grado.

A todo esto estamos suponiendo que no tienes ningun circuito que adapte las señales
Ahora en tu codigo estas leyendo esta tensón con "temp=read_adc();" y luego comparas esta lectura con distintos valores que suponemos temperaturas.

Ahora que esta pasando realmente, seguramente solo se te encienda el pin_B7.
Suponemos 30º
10mV por grado son: 30*0.01 = 0.3V
lectura ADC de 10bits con referencia 5v tenemos 5v/1024 = ~ 0.004883v cada bit
entonces cuando hacemos "temp=read_adc();" el valor de temp será 0.3/0.004883 = *61*.43 (0000111101)

Si te fijas el resultado no coincide con los numeros que estas comparando. Soluciones varias.
-Adaptar la entrada para que la lectura te coincida con los grados (es una tonteria, dificil, perdida de resolucion, inestable por la poca tensión que representaria cada bit.......)
-Una vez hecha la lectura hacer la ecuación para convertir ese numero en grados
-En cada "if" comparar el resultado con el nº ya calculado (para 30º el 61)

Edit. Lo que sí es recomendable es adaptar la entrada amplificando la tensión del LM35 o bajando la referencia del pic para aprobechar mas la resolución.

Un saludo


----------



## jose011 (Oct 24, 2012)

gracias tannke!! no habia caido en eso que me comentas de la tension asi que voy a modificarlo y haber si funciona bien. un saludo


----------



## Psyke (Nov 7, 2012)

Hola a todos, yo hice mi termómetro digital con 2 displays de 7 segmentos y esta funcionando de maravillas, adjunto el enlace del código y a continuación les muestro como modificarlo para mostrar el valor en un display LCD, espero no tener errores ya que no estoy en mi computadora.
Hay que agregarle unas modificaciones para que mida correctamente temperatuas menores a 10 grados y mayores a 99

http://db.tt/3KvYgsLP

```
#include <16F877A.h>
#device adc=10
#fuses XT,NOWDT,NOPUT,NOPROTECT,NOWRT,NOBROWNOUT
#use delay(clock=4000000)

void main ()
{
int16 q;
float p,Temp;
unsigned int Unidad, Decena;
int Numeros[10] = {0b00111111,0b00000110,0b01011011,0b01001111,0b01100110,0b01101101,0b01111101,0b00000111,0b01111111,0b01101111};

setup_adc_ports (AN0);
setup_adc(ADC_CLOCK_INTERNAL);


      while(true){
      set_adc_channel(0);
      delay_us(20);
      q = read_adc();
      p = (float)(q * 5) / 1024;
      Temp = (p * 100) / 3;
       //  if(Temp<=99)
       //  {
         Unidad=(int)Temp % 10;
         Decena=(int)Temp / 10;
         output_d(Numeros[Decena]);
         output_b(Numeros[Unidad]);
         delay_ms(800);
         }
      //else
         //   {
          //  Decena=(int)(Temp - 100) / 10;
          //  Unidad=(int)(Temp - 100) - (Decena * 10);
         //   }
       //           
  }
```

Para visualizarlo en un display LCD debemos borrar todo lo que dice 

Unidad=(int)Temp % 10;
         Decena=(int)Temp / 10;
         output_d(Numeros[Decena]);
         output_b(Numeros[Unidad]);

Y debemos agregar el #include <lcd.c> y colocamos un
Printf(lcd_putc, "\f temperatura=%d, temp); 
Espero no haberme equivocado, suerte a todos y cualquier problema me escriben


----------



## micronica (Nov 7, 2012)

Si vas a usar otros sensores y quieres ver también la humedad, te recomiendo que mires el SHT11 de Sensirion, te da la temperatura y la humedad y no pasa por convertidor A/D, se comunica en 'digital', de esta forma puedes 'obviar' los problemas de tener una buena tensión de referencia y márgenes de conversión que no aprovechan todo el recorrido. Yo he pasado por esa experiencia y al final me he hecho 'fan' de estos circuitos.


----------



## jose011 (Nov 21, 2012)

Buenos días!! estoy haciendo un proyecto en el cual quiero que por el LCD me muestre siempre la temperatura actual (dada por un lm35) y la temperatura mínima y máxima deseada, pero que cuando descienda la temperatura de la mínima deseada o suba de la máxima, me muestre durante 2 segundos otro mensaje en la pantalla del LCD y vuelva a mostrar la actual. 
He conseguido que me muestre el mensaje cuando baja de la mínima o sube de la máxima pero la pantalla ya no varía, quiero que me vuelva a mostrar la temperatura actual y no consigo como hacerlo, haber si alguien podría darme ideas. gracias!!


```
#include <16f876A.h>
#fuses XT,NOWDT   
#device adc=10                               //Utilizamos 10 bits para la conversion A/D.
#use delay(clock=4000000)
#use standard_io(a)                          //Defino puerto A para su utilización como entradas o salidas.
#use standard_io(b)                          //Defino puerto b para su utilización como entradas o salidas.
#use standard_io(c)                          //Defino puerto c para su utilización como entradas o salidas.
#include <LCD.c>                             //Libreria del LCD
#include <stdio.h>                           
#include <string.h>
#define use_portb_lcd TRUE                   //Para usar el puerto B para el LCD
#locate lcd = getenv("sfr:PORTB")            //Para usar el puerto B para el LCD

//#define subirmax PIN_A1
//#define bajarmax PIN_A2
//#define subirmin PIN_A4
//#define bajarmin PIN_A5

void main()
{ 
float temp,leer;                             //Variable para leer valores obtenidos por el convertidor A/D.                            
int max=30;                                  //Para ajustar la maxima
int min=25;                                  //y la minima

lcd_init();

set_tris_a(0xff);                          //Entrada.
set_tris_b(0x00);                          //Salida.

while(TRUE){
setup_adc_ports(AN0);                       //Entrada analógica utilizada, pin0 del puerto A.
setup_adc (adc_clock_div_32);               //Necesario para que funcione bien el adc.

set_adc_channel (0);                  //Elige canal a medir RA0
leer=read_adc ();                    //Hace conversión A/D 
//setup_adc (adc_off);           //Apaga ADC
temp=(leer*(0.48873));               // EL NUMERO (0.48875) viene de dividir (5/1023) y el resultado de la conversión

lcd_gotoxy(1,1);                          //escribe en la 1ª linea del LCD
lcd_putc(" T actual: ");
delay_us(100);
printf(lcd_putc,"%f",temp);          //muestra los grados según el lm35

lcd_gotoxy(1,2);                       //escribe en la 2ª linea, 1ª posicion del LCD
lcd_putc("max: ");
delay_us(100);
printf(lcd_putc,"%d",max);       //muestra la temperatura maxima elegida

lcd_gotoxy(9,2);                       //escribe en la 2ª linea, 9ª posicion del LCD
lcd_putc("min: ");
delay_us(100);
printf(lcd_putc,"%d",min);       //muestra la temperatura minima elegida

//while((temp<min)||(temp>max)){        
while (temp<min)
      {
         lcd_gotoxy(1,1);     //mostrar 2 segundos
         printf(lcd_putc,"      Frio!     "); 
         lcd_gotoxy(1,2);  
         printf(lcd_putc,"   Calentando   "); 
         delay_us(2000);
        //lcd_putc(" /f");                // Limpio LCD
      }    
while(temp>max)
      {
         lcd_gotoxy(1,1);    //mostrar 2 segundos
         printf(lcd_putc,"     Calor!     "); 
         lcd_gotoxy(1,2);  
         printf(lcd_putc,"   Enfriando   "); 
         delay_us(2000); 
       //lcd_putc(" /f");                 //Limpio LCD
       }
      //else
      {
         //lcd_gotoxy(1,1);  
        //printf(lcd_putc,"Temperatura OK  ");
      }
}

//setup_adc_ports(AN1);                       //Entrada analógica utilizada, pin0 del puerto A.
//setup_adc_ports(AN2);                       //Entrada analógica utilizada, pin0 del puerto A. 

//while(~input(subirmax));
//while(input(subirmax));
//delay_us(5);
//max=max+1;

//while(~input(subirmin));
//while(input(subirmin));
//delay_us(5);
//min=min+1;
}
```


----------



## micronica (Nov 21, 2012)

Hola,

el circuito, ¿lo estás simulando o es real?. Una idea que puede ser una tontería pero por si las moscas. Estas comparando temp (float), con min y max(int). ¿Podrías verificar via debugger o simulación que esa comparación se hace bien?.

Saludos


----------



## jose011 (Nov 21, 2012)

De momento lo estoy simulando el proteus; en cuanto a la comprobación sí la hace correctamente ya que cuando la temperatura baja de 25º a 24º, por ejemplo, me cambia la pantalla del lcd pero cuando vuelve a subir a 25º o 26º la mantiene y lo que quiero es que la cambie.  un saludo!!


----------



## micronica (Nov 22, 2012)

Hola de nuevo,

ya tenemos el código, si pones por aquí el esquema que estas usando, intentaré ponerlo en marcha en el simulador y comentarte el posible error. Los bucles 'while' como los estas aplicando no son muy aconsejables en programación ya que te dejan 'congelada' la aplicación en una zona y te impide leer las teclas (por ejemplo). Una solución podría ser leer las teclas mediante una interrupción por un timer, aunque esto no tiene nada que ver con el problema que comentas te serviría más adelante.

Saludos


----------



## jose011 (Nov 23, 2012)

Aquí pongo donde lo estoy probando en proteus.
**todos los pulsadores que aparecen no los uso (de momento), los tengo puestos para usarlos en un futuro


----------



## micronica (Nov 23, 2012)

Hola de nuevo,

he 'montado' el circuito y compilado el código, el fallo es evidente pero hasta que no me he puesto, no lo he visto. Cuando entra en un bucle de mayor o menor, no vuelves a leer la temperatura y la variable 'temp' no se actualiza aunque la temperatura varíe. Te lo adelanto por si quieres ponerte a ello, yo modificaré el código y lo pondré en un post próximo.

Saludos



Hola,

aquí tienes el código con ligeras correcciones, he cambiado algo los mensajes para simplificar y he sacado fuera del while principal el inicio del lcd, solo es necesario hacerlo una vez al principio.

Como te comenté, los while juegan malas pasadas. Otra cosa respecto al esquema, cuando los pulsadores no están pulsados en la entrada no tienes ni '1' ni '0', deberías ponerles una resistencia a masa en las entradas, así cuando no pulses, el valor será de '0'. Proteus puede que lo tolere, pero en un circuito real tendrías problemas.

Saludos


```
#include <16f876A.h>
#fuses XT,NOWDT
#device adc=10                               //Utilizamos 10 bits para la conversion A/D.
#use delay(clock=4000000)
#use standard_io(a)                          //Defino puerto A para su utilización como entradas o salidas.
#use standard_io(b)                          //Defino puerto b para su utilización como entradas o salidas.
#use standard_io(c)                          //Defino puerto c para su utilización como entradas o salidas.
#include <stdio.h>
#include <string.h>
#define use_portb_lcd TRUE                   //Para usar el puerto B para el LCD
#include <LCD.c>                             //Libreria del LCD
#locate lcd = getenv("sfr:PORTB")            //Para usar el puerto B para el LCD

//#define subirmax PIN_A1
//#define bajarmax PIN_A2
//#define subirmin PIN_A4
//#define bajarmin PIN_A5

void main()
{
float temp,leer;                             //Variable para leer valores obtenidos por el convertidor A/D.
int max=30;                                  //Para ajustar la maxima
int min=25;                                  //y la minima

lcd_init();

set_tris_a(0xff);                          //Entrada.
set_tris_b(0x00);                          //Salida.

// Setup de ADC
setup_adc_ports(AN0);                       //Entrada analógica utilizada, pin0 del puerto A.
setup_adc (adc_clock_div_32);               //Necesario para que funcione bien el adc.

// Bucle sin fin... programa principal
while(TRUE){
  set_adc_channel (0);                  //Elige canal a medir RA0
  leer=read_adc ();                    //Hace conversión A/D
  temp=(leer*(0.48873));               // EL NUMERO (0.48875) viene de dividir (5/1023) y el resultado de la conversión

  lcd_gotoxy(1,1);                          //escribe en la 1ª linea del LCD
  //-lcd_putc(" T actual: ");
  //-delay_us(100);
  //-printf(lcd_putc,"%f",temp);          //muestra los grados según el lm35
  printf(lcd_putc," T actual: %f",temp);

  lcd_gotoxy(1,2);                       //escribe en la 2ª linea, 1ª posicion del LCD
  //- lcd_putc("max: ");
  //-delay_us(100);
  //-printf(lcd_putc,"%d",max);       //muestra la temperatura maxima elegida

  //-lcd_gotoxy(9,2);                       //escribe en la 2ª linea, 9ª posicion del LCD
  //-lcd_putc("min: ");
  //-delay_us(100);
  //-printf(lcd_putc,"%d",min);       //muestra la temperatura minima elegida
  printf(lcd_putc,"max: %d min: %d",max,min);

  while(temp<min){
       lcd_gotoxy(1,1);     //mostrar 2 segundos
       printf(lcd_putc,"      Frio!     ");
       lcd_gotoxy(1,2);
       printf(lcd_putc,"   Calentando   ");
       delay_us(2000);
       set_adc_channel (0);                  //Elige canal a medir RA0
       leer=read_adc ();                    //Hace conversión A/D
       temp=(leer*(0.48873));               // EL NUMERO (0.48875) viene de dividir (5/1023) y el resultado de la conversión
      }

  while(temp>max){
      lcd_gotoxy(1,1);    //mostrar 2 segundos
      printf(lcd_putc,"     Calor!     ");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"   Enfriando   ");
      delay_us(2000);
      set_adc_channel (0);                  //Elige canal a medir RA0
      leer=read_adc ();                    //Hace conversión A/D
      temp=(leer*(0.48873));               // EL NUMERO (0.48875) viene de dividir (5/1023) y el resultado de la conversión
      }

}

//setup_adc_ports(AN1);                       //Entrada analógica utilizada, pin0 del puerto A.
//setup_adc_ports(AN2);                       //Entrada analógica utilizada, pin0 del puerto A.

//while(~input(subirmax));
//while(input(subirmax));
//delay_us(5);
//max=max+1;

//while(~input(subirmin));
//while(input(subirmin));
//delay_us(5);
//min=min+1;
}
```


----------



## Eduardo Mota (Ago 4, 2014)

hola, buenas tardes, yo también tengo un problema en el termómetro que estoy haciendo, uso un PIC16F819, un 7448, dos displays de catodo comun y el sensor de temperatura LM35DZ, el lenguaje de programación es ccs, el programa ya lo hice y en ccs no marca ningun error, pero en el momneto de probarlo en placa fenolica solo se muestran leds encendidos y al aumentar o disminuir la tempratura del sensor no hay cambio en la salida del pic, que parte del programa puede estar mal y como deberia de estar conectado realmente en la placa fenolica??, abajo estan los archivos adjuntos.... y muchas gracias y saludos


----------



## Saint_ (Ago 6, 2014)

...aqui algunas correcciones.

```
#include <16f819.h>
#fuses   NOBROWNOUT
#device  adc=10
#use     delay(internal=4MHz)
int valor,temp,digito1,digito2;
void main()
{
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_adc_ports(AN0);
   setup_oscillator(OSC_4MHz);
   set_tris_b(0x00);
   set_tris_a(0x01);
   set_adc_channel(0);
   delay_us(10);
   output_b(0);
   do{
        valor= read_adc(); 
        temp=valor*0.488;
        digito1=temp/10;
        digito2=temp-10*digito1;
        output_b(0b00000000|digito1);
        output_b(0b00010000|digito1);
        delay_ms(5);
        output_b(0b00000000|digito1);
        output_b(0b00000000|digito2);
        output_b(0b00100000|digito2);
        delay_ms(5);
        output_b(0b00000000|digito2);  
     }while (TRUE);
}
```


----------



## Eduardo Mota (Ago 8, 2014)

gracias Saint_ me sirvio mucho, en proteus funciona de maravilla, muchas gracias. Solo que me sale un problema menor, es el caso del LM35, el sensor si mide correctamente la temperatura, antes de conectarlo al AN0 del pic muestra correctamente el voltaje, al conectarlo sube a 2.37V a veces hasta 3V, mire el datasheet y conecte el la salida con un condensador de 1µF y una resitencia de 100Ω, ahi relice pruebas de ensayo y error, pero estos arreglos no me funcionan, ya que el adc del pic16f819 los toma como si fuesen los 2.37V o los 3V, que se podria relizar en estos casos??? 

gracias por la info de nuevo Saint


----------



## Saint_ (Ago 9, 2014)

hola Eduado Mota, ten en cuenta que el an0 del pic es un pin de entrada, antes de conectar el LM35 mide el voltaje que existe en el an0..., debería marcar 0 o un valor similar. Si marca un valor (ejemplo 1.2v) esto indicaría que ese pin se encuentra en mal estado.


----------



## Eduardo Mota (Ago 9, 2014)

Y tendria que reacomodar el trisa y porta del programa me imagino o seria problema del pic?


----------



## Saint_ (Ago 10, 2014)

mejo prueba usando otro canal del adc por ejemplo el an2


----------



## Eduardo Mota (Ago 13, 2014)

ya probe con cada uno de los canales, en el programa si queria la an0 escribia set_tris_a (0x01);  si es an1 era set_tris_a (0x02); an3 era set_tris_a(0x04); y asi sucesivamente, pero en la salida de los dos display me salia el mismo numero en cada una de las configuraciones osea en portb era 0xC1 y 0x42 y casualmente mido los voltajes de salida en cada configuracion de los canales y todos me marcan 3.68V y 0.04V aquellos que no estan habilitados alguien sabe que se puede hacer en estos casos y saludos a todos.


----------



## Saint_ (Ago 13, 2014)

pues de la forma en que se presentan las cosas da la impresion que estas dañadas las entradas analogicas, que tal si subes otra ves el prorama que tiene echo y tambien el esquema tal cual armaste el circuito.


----------



## Eduardo Mota (Ago 13, 2014)

asi tengo el circuito en mi protoboard y tambien tengo asi el programa, lo modifique aunque tambien probe con el programa original y el resultado es el mismo


----------



## AleSergi (Ago 13, 2014)

Eduardo, vos mismo te esforzas en que no te ayuden....  en estos casos debes subir TODOS los archivos de la simulación, unica forma que los interezados en ayudarte puedan experimentar que sucede. Haces dar la impresion que ni la simulación querés compartir.
En ese código que has subido, elimina los 
   set_tris_b(0x00);
   set_tris_a(0x02);
porque el compilador solo se ocupa de configurar esas cuestiones según se requiera.

Aqui        
 temp=valor*0.488;
mezclas zanahorias con papas, Todos los valores deben ser int, tenes uno decimal.

        digito1=temp/10;
        digito2=temp-10*digito1;
existe el operador % que facilita las cosas.

        output_b(0b00010000|digito1);
        output_b(0b00100000|digito2);
aqui no entiendo que pretendes hacer...
basta con sumarlos.
y obvio tenes que considerar de hacer conversion de tipo (casting),
el compilador podria confundirse, mejor no dejar nada al azar.

Has pensado en emplear la referencia del pic digamos en 1,5v para aumentar la presicion de la lectura?


----------



## Saint_ (Ago 14, 2014)

Hola, respecto del codigo.


AleSergi dijo:


> En ese código que has subido, elimina los
> set_tris_b(0x00);
> set_tris_a(0x02);
> porque el compilador solo se ocupa de configurar esas cuestiones según se requiera.


Respecto del código. Es cierto lo que dice AleSergi, si no se usa la directiva #use fast_io no es necesario usar las instrucciones set_tris_x(); ya que el compilador internamente se ocupa de efectuar las convertir los puertos de entrada a salida o viceversa según la necesidad.


AleSergi dijo:


> Aquí
> temp=valor*0.488;
> mezclas zanahorias con papas, Todos los valores deben ser int, tenes uno decimal.


temp=valor*0.488, donde:
temp es tipo entero
valor es tipo entero. Tenemos que: valor*0.488 da como resultado un tipo flotante (la conversión es implícita)
al asignar ese resultado (flotante) a una variable tipo entro solo trasfiere la parte entera del valor y la parte decimal es desechada y también es una conversión implícita. También podría haberse escrito como:
temp=(int)(valor/0.488); o también como: temp=(int)((float)(valor)/0.488); pero el resultado sería el mismo.


AleSergi dijo:


> digito1=temp/10;
> digito2=temp-10*digito1;
> existe el operador % que facilita las cosas.


Es cierto sería más fácil hacer: digito2=temp%10; ya que con esta operación se obtiene el residuo de la división.


AleSergi dijo:


> output_b(0b00010000|digito1);
> output_b(0b00100000|digito2);
> aqui no entiendo que pretendes hacer...
> basta con sumarlos.


0b00010000|digito1 tiene por objeto enviar digito1 en el nible inferior y a su vez "encender" el display correspondiente a digito1, para digito2 es el mismo caso.
Para este caso da lo mismo hacer 0b00010000|digito1 (suma lógica) que 0b00010000+digito1(suma aritmética), el resultado es el mismo.

Respecto del esquema.

Veo que el pin MCLR del pic está al aire  y como en los  #fuses no está especificado si se puede usar como pin de entrada o salida entonces tienes que conectar ese pin a +5v.

Es obvio y en proteus no muestra los pìnes de alimentación de los circuitos digitales (porque se supone que están alimentados) pero te convienen revisar que existan los +5v en el pin de +vdd y los 0v en el pin de vss del pic "uno nunca sabe pero ese detalle suele causar problemas".

Un error que veo en el esquema es los resistores, estos están mal, los resistores deben ir en serie a la base del transistor, el modo en que tienes conectados los resistores podría causar que se dañen los pines de salida del pic.


----------



## ruse85 (Jun 24, 2019)

hola buenas noches

Estoy realizando un termómetro con SENSOR LM35-RANGO(-55 hasta 150°C) y que cuando este en el rango de -55 a -1 se prenda un led verde , cuando este en el rango de 0 a 1 se prenda un led rojo y que cuando este en un rango de 20 a 35 prenda un led amarillo. adjunto el código esta escrito en mplab y adjunto el circuito en proteus 8.17.
 Me podrian ayudar en que parte del programa y como puedo realizar que cada led realice la funcion.


----------



## DJ T3 (Jun 24, 2019)

ruse85 dijo:


> Me podrian ayudar en que parte del programa y como puedo realizar que cada led realice la funcion



En el *while* dentro del *main* debes comprobar y comparar, quizas con algun *if,* por el tema de rangos


----------



## ruse85 (Jun 25, 2019)

DJ T3 dijo:


> En el *while* dentro del *main* debes comprobar y comparar, quizas con algun *if,* por el tema de rangos


Hola buenas tardes  lo realice pero no logro avanzar. asi como tambien en algunas declaraciones me aparce error. no se si pudieras ayudarme. gracias


----------



## DJ T3 (Jun 26, 2019)

Pon el codigo completo envolviendo con la etiqueta de codigo para ver cual es la falla


----------



## ruse85 (Jun 27, 2019)

DJ T3 dijo:


> Pon el codigo completo envolviendo con la etiqueta de codigo para ver cual es la falla


hola buenas tardes te adjunto el codigo muchas gracias.


----------



## ruse85 (Jul 23, 2019)

*H*ola*,* buenas tardes*.* *¿M*e podr*í*an ayudar*?*
*C*uando lo simulo sí funciona pero cuando lo armo en el proto board no funciona*.*
*N*o s*é *qu*é* est*é* mal*.* *N*o s*é* si pudieran ayudarme*.
M*uchas gracias*,* saludos*.*


----------



## D@rkbytes (Jul 24, 2019)

Supongo que deben ser los fuses de la palabra de configuración.
Si eso que conectas son LED, ya deben haberse quemado.

Mira la modificación del programa adjunto.
PD: Si no puedes abrir la simulación es porque la modifiqué con una versión superior de Proteus.
De igual forma usé PBPX 3.0.8.1

Palabra de configuración recomendada:
Para PBP 2.X:

```
@ Device INTRC_OSC_NOCLKOUT,WDT_OFF,PWRT_ON,LVP_OFF
```
Para PBP 3.X:

```
#Config
    __CONFIG _FOSC_INTOSCIO & _WDT_OFF & _PWRTE_ON & _LVP_OFF
#EndConfig
```


----------



## ruse85 (Jul 24, 2019)

hola muchas gracias estaba como le puedo hacer para que tenga estos rangos de 0 °C a 2°C, 3°C a 5°C y de 20°C a 40 °C nada mas.
me ayudarias explicarme como le puedo realizar.

gracias  saludos


----------



## D@rkbytes (Jul 25, 2019)

En el archivo que subí se demuestra cómo seleccionar los rangos.


----------



## ruse85 (Jul 25, 2019)

Hola buen día como no podia compilar por eso pero ya vi cual era el error que me marcaba. Y ya pude seleccionar Rangos, en si el termómetro que trato de realizar es el completo entonces me imagino que has que estar restando la Temperatura 1 y la dos. Voy a intentarlo haber *a ver *que tal me va. Saludos y muchas gracias.


----------



## ruse85 (Ago 1, 2019)

D@rkbytes dijo:


> En el archivo que subí se demuestra cómo seleccionar los rangos.


Hola buenas tardes

Ya realice la pcb y arme el circuito pero aun sigue sin funcionar por un rato funciona bien pero despues deja de funcionar, ¿sera por que solde el sensor aun cable blindado que delargo de 1 metro? ya medi el voltaje del pin 2 del sensor para verificar que este funcionando bien y los voltajes son correctos ya revise el codigo y no encontre nada raro, me podrias ayudar haber que esta mal.

saludos


----------



## D@rkbytes (Ago 1, 2019)

ruse85 dijo:


> por un rato funciona bien pero después deja de funcionar.


Seguramente es el programa el que está fallando.


ruse85 dijo:


> ¿Será porque soldé el sensor a un cable blindado de 1 metro de largo?


No. Yo vi un sensor LM35 conectado con más de 6 metros de cable blindado y funcionaba bien.


ruse85 dijo:


> ¿Me podrías ayudar a ver qué está mal?


Sin ver el programa que estás usando no lo creo posible.


----------

