# Sensor de temperatura. Pasar de PIC16F877A a PIC16F887



## picnoob (Ago 29, 2012)

Buenas soy nuevo por aca, espero me resivan bien, he preguntado por todas partes y nadie me da respuesta, este es mi ultimo intento.

En fin estaba modificando un codigo de un sensor de temperatura con un ml35 y un pic16f877A pero como ustedes saben el 877A ya quedo en desuso por lo tanto ya no lo sacan a la venta, el pic16f887 es el nuevo sustituto entonces decidi pasarme a el pero no doy, el programa corre correntamente en mikroc pero cuando lo emulo en proteus la pantalla queda en blanco en cambio utilizando el 877A funciona perfecto.

Les agradeceria sus ayudas







codigo

```
unsigned char ch;
unsigned int adc_rd;
char *text,*text1;
long tlong;
int i,j;
// LCD module connections
sbit LCD_RS at RB4_bit;
//sbit LCD_RW at RB6_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
//sbit LCD_RW_Direction at TRISB6_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections



void main() {
 /* TRISB = 0;
  PORTB = 0xFF;
  TRISB = 0xff;
  ANSEL  = 0;                        // Configure AN pins as digital I/O
  ANSELH = 0;  */
 INTCON = 0;
 trisb=0;
  Lcd_init();//Lcd_Config(&PORTB, 4, 5, 6, 3, 2, 1, 0);
  LCD_Cmd(_LCD_CURSOR_OFF);     //antes    LCD_Cmd(LCD_CURSOR_OFF);
  LCD_Cmd(_LCD_CLEAR);   //antes  LCD_Cmd(LCD_CLEAR);
  for(i=0;i<5;i++){
  LCD_Cmd(_LCD_CLEAR);
  text = "HOLA";
  LCD_Out(1,i,text);
  Delay_ms(100);
  }
  text1 = "COMO ESTAS";
  LCD_Out(2,3,text1);
  ADCON1     = 0x82;
  TRISA      = 0xFF;
  Delay_ms(1000);
  LCD_Cmd(_LCD_CLEAR);

  text  = "Temperatura:";
   for(j=16;j>0;j--){
    LCD_Cmd(_LCD_CLEAR);
    LCD_Out(1,j,text);
    Delay_ms(100);
    }

  while (1) {
    adc_rd  = ADC_read(2);

    tlong = (long)adc_rd * 5000;
    tlong = tlong / 1023 - 40;
    ch    = tlong / 1000;

    if(ch==0)
    LCD_Chr(2,6,' ');
    else
    LCD_Chr(2,6,48+ch);

    ch    = (tlong / 100) % 10;

    LCD_Chr_CP(48+ch);
    ch    = (tlong / 10) % 10;
    LCD_Chr_CP(48+ch);
    LCD_Chr_CP('.');

    ch    = tlong % 10;
    LCD_Chr_CP(48+ch);
    LCD_Chr_CP('C');
    Delay_ms(200);
  }
}
```


----------



## D@rkbytes (Ago 30, 2012)

picnoob dijo:


> el programa corre correctamente en mikroc pero cuando lo emulo en proteus la pantalla queda en blanco en cambio utilizando el 877A funciona perfecto.


Tienes comentado el uso del registro ANSELH
Descomentalo para que el puerto B sea digital I/O, ya que ahí tienes conectada la pantalla.
El registro ANSEL déjalo comentado para que RA2 (AN2) sea análogo.
También puedes configurar los pines usando el registro ADCON0 y ADCON1

Si deseas usar el oscilador interno, declaralo en los fuses y configura el registro OSCCON
Por ejemplo para 8MHz sería así.
OSCCON = 0b1110100;

Suerte.


----------



## picnoob (Ago 31, 2012)

Gracias hermano, mil gracias, funciono correctamente.

Ahora he tratado de sacar el valor de la temperatura y no he podido tanto con tlong y con ch pero nada no he podido, lo que quiero es que al tomar la variable compararla con otra que tenga un numero ejemplo 40 entonces si la temperatura llega a 40 apague un bombillo y si baja lo vuelva a encender pero para eso necesito el valor que esta mandando el lm35



D@rkbytes dijo:


> Tienes comentado el uso del registro ANSELH
> Descomentalo para que el puerto B sea digital I/O, ya que ahí tienes conectada la pantalla.
> El registro ANSEL déjalo comentado para que RA2 (AN2) sea análogo.
> También puedes configurar los pines usando el registro ADCON0 y ADCON1
> ...


----------



## picnoob (Ago 31, 2012)

Bueno ya logre obtener la temeratura, cambie el while por otro pero lo que ahora me tiene cabezon es que colocar entre la salida del puerto B y El bombillo de 110V que se apaga y enciende



```
do {
    temp_res = ADC_Read(2)/2;     // Get 10-bit results of AD conversion
    //temp_res = ADC_Read(2);
    temp = (temp_res * VREF)/10.240;  // Calculate temperature in Celsuis
                                      //  change Vref constant according
     //FloatToStr(temp, txt);                                 //  to the power supply voltage
    FloatToStr(temp_res, txt);            // Convert temperature to string
    //txt[4] = 0;
    Lcd_Out(2,3,txt);                 // Write string in second row
    Delay_ms(300);

    if(temp_res>40)
    {
    PORTB.F7 = 0;
    }
    if(temp_res<40)
    {
    PORTB.F7 = 1;
    }
   } while(1);
```


----------



## picnoob (Ago 31, 2012)

ya lo logre en proteus todo va de pelos pero en la vida real no se si tendra problemas


----------



## D@rkbytes (Ago 31, 2012)

picnoob dijo:


> Bueno ya logre obtener la temperatura, cambie el  while por otro pero lo que ahora me tiene cabezón es que colocar entre  la salida del puerto B y El bombillo de 110V que se apaga y  enciende


Utiliza un optotriac y un triac. Usa el buscador del foro y encontraras la forma de hacerlo.


picnoob dijo:


> ya lo logre en proteus todo va de pelos pero en la vida real no se si tendrá problemas


Si tendrás problemas. Las fuentes de tensión deben estar separadas.
Para eso utiliza el optotriac.
También puedes usar un relevador controlado por un transistor.

Saludos.


----------



## CISR (Sep 1, 2012)

tambien puedes usar un relevador de estado solido como el 120D45 que tiene un voltaje de control que va desde los 3 volts hasta los 32.


----------



## X1un1Mundo1Mejor1wii (Sep 1, 2012)

Amigo el va a encender un Bombillo el debería usar un optotriac 3041 que tiene detector de cruce por cero, ese MOC de la foto yo lo uso cuando deseo hacer control de angulo de disparo en cambio el 3041 por ejemplo tiene un detector de cruce por cero que esperaría que la señal alterna cruce por "0 " voltios, otra cosa el  bombillo tiene una resistencia que varia y  aumenta con el calor por lo tanto en estado frío (apagado) y si se usase ese MOC de la figura malograría el triac de a pocos o quizás antes de lo que te imagines, bueno en todo caso lo mejor para arranques sólidos sin control angular de la señal es usar MOC con detector de cruce por cero


Otra opción es usar un transformador de pulsos, pero ya veo que casi nadie los usa, y para tu caso no serviría ya que tu señal es constante por lo tanto no habría variación en la salida del transformador y este se comportaría como una resistencia.


----------



## CISR (Sep 1, 2012)

Pero si solo haría un "todo o nada" o prende o apaga , ese diagrama es el que yo tengo para activar un electroiman desde el pic usando el triac mac15a8 aquí su hoja de datos:

MAC15A-8 pdf, MAC15A-8 description, MAC15A-8 datasheets, MAC15A-8 view ::: ALLDATASHEET  :::

lo uso con este optoacoplador:

QT Optoelectronics - datasheet pdf

lo que si es que se me paso que es una carga resistiva y a la salida solo tienes que conectar la resistencia de 180 ohms directa a tu ZR quitando el capacitor y la otra resistencia ,ahí en la hoja de datos del moc viene como conectarlo para tu foco.

cuando necesito activar algo que necesita mas carga como ya dije uso relevadores de estado solido como el 120D45 que seria lo mas fácil :
120D45 datasheet & application note - Datasheet Archive

saludos !!!


----------



## picnoob (Sep 1, 2012)

Pues le pregunte al tecnico que me esta vendiendo el quemador de pics y me recomendo utilizar un transistor que esta conectado al pic y que activa un rele de 5v el cual enciende el bombillo en el caso de estar en HIGH, ¿Q les parece esa solucion? que tambien la dijo d@rkbytes y CISR pero con uno de estado solido.

En proteus funciona correctamente.


----------



## picnoob (Sep 9, 2012)

Ya llegue aqui ahora voy por los bombillos.


----------



## Meta (Sep 9, 2012)

Hola:

Puede que esto te ayude con el 16F886, se adapta rápido al 16F887 con el LM35.


```
/*El módulo convertidor ADC. Termómetro digital

Este ejemplo visualiza sobre la pantalla LCD la temperatura ambiente captada por el sensor LM35DZ
conectado con la entrada RA0/AN0 y cuya precisión es de 10mV/ºC. La resolución del convertidor
ADC, con una tensión de referencia de 5V, es de 0.00488. En estas condiciones cada ºC supone 
dos incrementos en la salida del convertidor (0.00976V=10mV) aproximadamente. Es por ello que
al resultado de la conversión se le divide entre 2.

Se emplea el Timer 1 que provoca una interrupción cada 0.1 seg. Cunado se produzcan n interrupciones
se procede a tomar una muestra de la tempreatura. En este ejemplo se toman cada 1 segundo. 

En este caso visualizamos en centígrados (ºC) y en Fahrenheit (ºF), donde (ºF = ºC*1.8+32)*/

#include <16f886.h>

/* Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades */

#fuses     NOLVP,PUT,NOWDT,EC_IO,NOFCMEN,NOBROWNOUT    //Palabra 1 de configuración
#fuses    NOWRT,BORV40                                //Palabra 2 de configuración

/* Con estas directivas las funciones "input" y "output_bit" no reprograman
el pin de la puerta cada vez que son utilizadas. Si no se indica el
modo fast_io se asume por defecto standard_io el cual reprograma el pin
siempre antes de ser utilizadas estas funciones. */

#device ADC=10                                    //Conversor ADC/ de 10 bits de resolución
#use fast_io (A)
#use fast_io (B)
#use delay(clock=4000000)                        //Frecuencia de trabajo

#include <lcd4bitsPIC16.h>                        //Incluye funciones de manejo del LCD

#define Tiempo    10                                //Nº de interrupciones de 0.1 seg. para tomar una muestra (p.e. 1 segundo)
int Int_Cont;                                    //Contador de interrupciones
int16 Temperatura;                                //Variable con la temperatura medida    
int Centigrados;                                //Variable con la medida en ºC
float Fahrenheit;                                //Variable con la medida en ºFahrenheit

/****************************************************************************************
Tratamiento de la interrupción que provoca el Timer 1 cada 0.1 seg. Espera a que se produzcan
tantas interrupciones como se indique en "Tiempo" para conseguir una temporización total determinada.
Inicia una conversión del canal seleccionado, realiza los cálculos apropiados y visualiza sobre el LCD*/
#int_timer1                
tratamiento()
{    
    Int_Cont--;    
    if(Int_Cont==0)                                //Han pasado n interrupciones
    {
        lcd_gotoxy(10,1);                        //Coloca el cursor        
        Temperatura=read_adc();                    //Inicia la conversión y lee el resultado (temperatura)
        Centigrados=Temperatura/2;                //Calcula los grados centígrados
        Fahrenheit=Centigrados*1.8+32;            //Calcula los grados Fahrenheit
        printf(lcd_putc,"%2u",Centigrados);        //Visualiza en grados centígrados
        lcd_gotoxy(8,2);                        //Coloca el cursor
        printf(lcd_putc,"%3.1f",Fahrenheit);    //Visualiza en grados Fahrenheit
        Int_Cont=Tiempo+1;                        //Repone el contador para otras 10 interrupciones (1 seg)
    }
    set_timer1(~12500);                            //Repone TMR1 con 12500
}
                    
main()
{  
    delay_ms(50);    
    lcd_init();                                    //Inicia la pantalla LCD
    printf(lcd_putc,"Temp.=      %cC",0xdf);    //Visualiza "Temp.      ºC"                        
    lcd_gotoxy(13,2);
    printf(lcd_putc,"%cF",0xdf);                //Visualiza "ºF"        
    Int_Cont=Tiempo+1;                            //Nº de interrupciones (10) para que transcurra 1 seg.

//Se activa el ADC y se selecciona el canal RA0/AN0. Frecuencia de trabajo Fosc/32
    setup_adc(adc_clock_div_32);                //Ajusta frecuencia de muestreo del ADC
    setup_adc_ports(sAN0);                        //RA0 entrada analógica
    set_adc_channel(0);                            //Selección del canal RA0/AN0

/*El TMR1 trabaja con oscilador interno y un preescaler de 1:8. Si se trabaja a una frecuencia
de 4 MHz, el TMR1 deberá ser cargado con 12500 para que provoque interrupción al de 0.1s
(12500 * 8 * 1 =100000uS=0.1")*/
    set_timer1(~12500);                            //Carga TMR1 con 12500
    setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);    //TMR1 ON y 1:8    
    enable_interrupts(int_timer1);                //Activa interrupción del Timer1    
    enable_interrupts(global);                    //Habilita interrupciones

    while(1)
    {
    }
}
```

Un saludo.


----------



## picnoob (Sep 24, 2012)

Buenas, pues ya puede encender el bombillo dependiento de la temperatura utilizando un rele de 5v,  pero una cosa que no me cuadra es que la temperatura varia muy rapido en algunos momentos. Me explico mejor:

En  algunos momentos la temperatura llega, supongamos a 26°C y de repente salta a 28 baja de nuevo a 26 baja a 24 sube a 27 baja a 26 sube a 28 y asi sucesivamente, si es temperatura ambiente esta deberia variar muy poco y no de esa manera, entonces yo me imagino que es un problema en el circuito ya sea por que varia el voltaje o algo pasa pero no se que es por eso hago la pregunta ¿Porque pasa esto? a caso puede ser por que el lm35 lo tengo alejado del circuito, lo que pasa es que no deseo meter el circuito completo donde esta el bombillo sino solo el lm35 de manera que el circuito no se vaya a dañar o deteriorar por el calor.

uso 4mhz con el oscilador interno afecta esto en algo.


----------



## Meta (Sep 25, 2012)

Si usas el LM35 tal vez, si usas el DS1820 estará mejor.


----------



## ricbevi (Sep 25, 2012)

picnoob dijo:


> Buenas, pues ya puede encender el bombillo dependiento de la temperatura utilizando un rele de 5v,  pero una cosa que no me cuadra es que la temperatura varia muy rapido en algunos momentos. Me explico mejor:
> 
> En  algunos momentos la temperatura llega, supongamos a 26°C y de repente salta a 28 baja de nuevo a 26 baja a 24 sube a 27 baja a 26 sube a 28 y asi sucesivamente, si es temperatura ambiente esta deberia variar muy poco y no de esa manera, entonces yo me imagino que es un problema en el circuito ya sea por que varia el voltaje o algo pasa pero no se que es por eso hago la pregunta ¿Porque pasa esto? a caso puede ser por que el lm35 lo tengo alejado del circuito, lo que pasa es que no deseo meter el circuito completo donde esta el bombillo sino solo el lm35 de manera que el circuito no se vaya a dañar o deteriorar por el calor.
> 
> uso 4mhz con el oscilador interno afecta esto en algo.



Hola...en mi opinión usando un sensor como el LM35 donde las variaciones se miden en el entorno a los ºC/milivolts y encima a distancia es lo mínimo que te puede pasar...por eso te han recomendado el DS que el ser digital no importa(dentro de ciertos limites de diseño) la distancia.
Esos efectos se pueden minimizar(dentro de cierta medida) si el programador incluye en su programa por ejemplo el promedio de algunas mediciones en el tiempo antes de tomar una decisión al respecto.
Saludos.

Ric.


----------



## picnoob (Sep 26, 2012)

ricbevi dijo:


> Esos efectos se pueden minimizar(dentro de cierta medida) si el programador incluye en su programa por ejemplo el promedio de algunas mediciones en el tiempo antes de tomar una decisión al respecto.
> Saludos.
> Ric.



Y como se hace 

Lo unico que trate de hacer y que mas o menos disminuyo(disimulo) las variaciones fue que cada 1 segundo mostrara la lectura en ves de cada 200ms

Les dejo el video


----------



## ricbevi (Sep 27, 2012)

picnoob dijo:


> Y como se hace
> 
> Lo unico que trate de hacer y que mas o menos disminuyo(disimulo) las variaciones fue que cada 1 segundo mostrara la lectura en ves de cada 200ms
> 
> ...



Te lo tratare decir de otra manera. Si vas a usar el LM35...acorta todo lo posible y blinda la conexión entre este y el micro controlador,  en el software antes de mostrar o realizar alguna acción mide en repetidas oportunidades lo que te marca el sensor y luego saca un promedio y recién después muestras/actuás. Tú conoces tú programa así que tú debes implementar la solución yo solo te puedo orientar de como lo aria yo con la información que brindas.
Reitero el DS que te sugirieron anteriormente al comunicarse con el micro controlador mediante un bus digital(unos y ceros) es mejor en cuanto a la estabilidad de la medición sobre todo a distancia que una comunicación ANALOGICA como la del LM35.
Suerte.

Ric.


----------

