TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: aripod en 17 de Noviembre de 2008, 16:35:53

Título: Problema Sensor de temp y 3 displays
Publicado por: aripod en 17 de Noviembre de 2008, 16:35:53
Estoy haciendo un sensor de temp con 3 displays y un 16f877a. El codigo es el siguiente:

Código: [Seleccionar]
#include <16f877a.h>            //pic a utilizar         
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP      //ordenes para el programador
#use delay (clock=4000000)         //Fosc=4Mhz


void mostrar(int temperatura);
float temperatura=0;
void main(void)
{
set_tris_b(0x00); 
set_tris_c(0x00);
output_low(pin_C0);
output_low(pin_C1);
output_low(pin_C2);

setup_adc_ports(NO_ANALOGS);
setup_adc_ports(RA0_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0); //Canal 0.
delay_ms(1);


while(1)
   {
mostrar(temperatura=read_adc()*(500/255));
   }
}


void mostrar(int temperatura)
{
int decenas=0, unidades=0, decimales=0;
int tab7seg[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67};
while(temperatura>100)
   {
   temperatura=temperatura-100;
   decenas++;
   }

while(temperatura>10)
   {
   temperatura=temperatura-10;
   unidades++;
   }

while(temperatura>0)
   {
   temperatura=temperatura-1;
   decimales++;
   }

output_high(pin_C0);
output_b(tab7seg[decenas]);
delay_ms(5);
output_low(pin_C0);
delay_ms(5);   //VER SI PUEDEN SER MENORES O CERO.
output_high(pin_C1);
output_b(tab7seg[unidades]);
delay_ms(5);
output_low(pin_C1);
delay_ms(5);   //VER SI PUEDEN SER MENORES O CERO.
output_high(pin_C2);
output_b(tab7seg[decimales]);
delay_ms(5);
output_low(pin_C2);
delay_ms(5);   //VER SI PUEDEN SER MENORES O CERO.
}

La idea es que muestre la temp por los tres displays, DECENAS UNIDADES. DECIMALES, por eso en la conversion multiplico el dato por (500/255), para poder tener los tres digitos en un solo numero entero. Definitivamente algo esta mal porque poniendo valor en la RA0 que seria la temp me muestra cualquier valor.
El sensor me tira 100mv/°c. Dejo el archivo del proteus tambien....

Gracias por la ayuda!
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 17 de Noviembre de 2008, 17:29:26
Hola.

Revisa lo siguiente:

http://www.todopic.com.ar/foros/index.php?topic=21738.0 (http://www.todopic.com.ar/foros/index.php?topic=21738.0)
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 23 de Noviembre de 2008, 20:25:37
Volvi al codigo, tenia un problema con los tipos de las variables....declare float y anda bien. AHora estoy con lo de los 7 segs y la interrupcion,,,,nunca lo hice asi...gracias por el link...
Donde puedo conseguir informacion para aprender a utilizar las interrupciones para cualquier fin, no solo para mnostrar algo en los displays? Gracias!
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 23 de Noviembre de 2008, 21:34:26
Hola.

Aqui en el foro hay muuuuuucha info sobre eso. Usa el buscador y listo.

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 24 de Noviembre de 2008, 11:06:51
Suponiendo que quiero que haga algo la interrupcion cada 1ms, que pasa con lo del main? Se hacen las dos cosas, paralelamente digamos??
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 24 de Noviembre de 2008, 20:59:41
Hola.

Las ISR son justamente para eso, el main se cumlple normalmente, al 1 milisegundo se interrumpe el codigo que se esta ejecutando y se atiende el servicio de interrupcion, hace lo que tiene que hacer y luego retorna a la parte del codigo donde se habia quedado antes de interrumpirse.

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 29 de Noviembre de 2008, 20:18:45
Bueno, retomo el tema.....SI quiero hacer la interrupcion cada 1ms, y seguin la formula: T = (256 - precarga) * Preescaler * 4 / Fosc ; con Preescaler 256 y Fosc 4Mhz, precarga=252. Esto significa que necesito que empiece a contar desde 252 para que llegue a 255 asi se desborda cada 1ms?
Suponiendo que asi sea, dentro de #int_RTCC que es lo que tengo que hacer? Ver si se desbordo el timer0 y si asi paso ponerlo en 252....?
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 30 de Noviembre de 2008, 14:07:45
Hola.

Cuando entra a la parte de #int_RTCC, es porque el timer ya se desbordo y por ende ya entro a la interrupcion. Si quieres que sea 1mS exacto deberias colocar dentro de la interrupcion set_timer(precarga), de esta manera vuelve a contar pero teniendo en cuenta el valor de la precarga, yo no lo hice asi ... no afectan mucho los 24uS que estan de extra en la visualizacion, pero si quieres bases de tiempo mas precisas entonces usa el set_timer(precarga) dentro de la int.

Código: CSS
  1. #int_TIMER0
  2. void display_isr(void)
  3. {
  4.  set_timer0(value);//value: valor calculado para el desborde
  5.  ....
  6. }

Saludos

Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 03 de Diciembre de 2008, 09:57:50
Segun lo que entendi, el codigo deberia ser asi:

Código: [Seleccionar]
#include <16f877a.h>            //pic a utilizar         
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP      //ordenes para el programador
#use delay (clock=4000000)         //Fosc=4Mhz


void mostrar(long temperatura);
long temperatura=0;
void main(void)

set_tris_a(0x00); 
set_tris_b(0x00); 
set_tris_c(0x00);
set_tris_d(0x00);
output_low(pin_C0);
output_low(pin_C1);
output_low(pin_C2);

output_a(0x00);
output_b(0x00);
output_c(0x00);
output_d(0x00);

enable_interrupts(INT_RTCC);               // Habilito Interrupción RTCC.
setup_counters(RTCC_INTERNAL,RTCC_DIV_256);// TIMER0: Clock Interno, Presescaler 256.
set_timer0(252);

setup_adc_ports(NO_ANALOGS);
setup_adc_ports(RA0_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0); //Canal 0.



while(1)
   {
    temperatura=read_adc()*(100/51);
   }
}

#int_TIMER0
void Timer0_isr(void)
{
mostrar(temperatura);
set_timer0(252);
}

void mostrar(long temperatura)
{
int decenas=0, unidades=0, decimales=0;
int tab7seg[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67};
while(temperatura>100)
   {
   temperatura=temperatura-100;
   decenas++;
   }

while(temperatura>10)
   {
   temperatura=temperatura-10;
   unidades++;
   }

while(temperatura>0)
   {
   temperatura=temperatura-1;
   decimales++;
   }

output_high(pin_C0);
output_b(tab7seg[decenas]);
delay_ms(5);
output_low(pin_C0);
delay_ms(5);   //VER SI PUEDEN SER MENORES O CERO.
output_high(pin_C1);
output_b(tab7seg[unidades]);
delay_ms(5);
output_low(pin_C1);
delay_ms(5);   //VER SI PUEDEN SER MENORES O CERO.
output_high(pin_C2);
output_b(tab7seg[decimales]);
delay_ms(5);
output_low(pin_C2);
delay_ms(5);   //VER SI PUEDEN SER MENORES O CERO.
}

Pero definitivamente entendi mal ya que no se prenden nunca los displays......esta claro que no entiendo bien que es lo ke hay que hacer cuando entra a la interrupcion. NO tengo que hacer ahi lo que quiero hacer y al salir poner el valor del TIMER0 en el valor de precarga??

Vi tu ejemplo MLO_ y por lo que entendi, todo lo que haces dentro de la interrupcion es lo que cada uno necesita para su necesidad?
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 03 de Diciembre de 2008, 12:39:44
Hola.

No es bueno colocar delays tan largos en las interrupciones, mira que tu estas despelgando los datos cada 5mS dentro de la misma interrupcion que se desborda cada milisegundo.

Otra cosa: Las interrupciones debes definirlas antes del programa principal, no despues como tu las tienes definidas.

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 03 de Diciembre de 2008, 14:00:17
Entonces kizas estoy yendo por mal camino. Mi idea es que se ejecute el main, pero cada 1ms salte a la interrupcion, haga el barrido de los displays y vuelva al main y siga haciendo sus cosas, y al 1ms vuelva a la interrupcion, todo esto dure lo ke dure la misma....
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 03 de Diciembre de 2008, 14:31:45
Hola.

Lo que yo hago con la interrupcion es multiplexar los datos. Es decir: tengo 4 variables, unidades_var1, decenas_var1, unidades_var2 y decenas_var2, cada vez que entra a la interrupcion (cada 1.024 mS) despliego las variables.

Para la primera interrupcion del timer0, visualizo las unidades de la primera variable:
(http://img505.imageshack.us/img505/4569/unidadestimer0tp7.png)

Para la siguiente interrupcion del timer0, visualizo las decenas de la primera variable:
(http://img505.imageshack.us/img505/2950/decenastimer0op5.png)

Para la 3 interrupcion del timer0, visualizo las unidades de la segunda variable:
(http://img505.imageshack.us/img505/2574/unidades1timer0dx4.png)

Para la 4 interrupcion del timer0, visualizo las decenas de la segunda variable y reinicio el contador de las interrupciones para que el proceso reinicie:
(http://img505.imageshack.us/img505/7425/decenas1timer0hv7.png)

Dentro de la misma interrupcion lo que hago primero es pasar el valor de las variables a BCD, es decir si tengo el valor d56 en value_1 lo convierto en 0x56, para pasar primero el valor 6 (unidades) y luego el valor 5 (decenas)
Código: C#
  1. dato_1 = int2bcd(value_1);
  2.         dato_2 = int2bcd(value_2);

Y el valor de las variables las cargo en el programa principal:
Código: C#
  1. while(true)
  2.  {
  3.         set_adc_channel(0);
  4.         delay_us(10);
  5.         value_1 = pc * read_adc();
  6.         set_adc_channel(1);
  7.         delay_us(10);
  8.         value_2 = resolucion * read_adc();
  9.         //delay_ms(1000);
  10.  }

Espero te ayude la aclaracion -y no haberte enrredado mas-

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 03 de Diciembre de 2008, 21:31:53
Entendi bien la idea, programe lo siguiente; pero no se prenden los displays......dejo el codigo y la simulacion:

Código: [Seleccionar]
#include <16f877a.h>            //pic a utilizar         
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP      //ordenes para el programador
#use delay (clock=4000000)         //Fosc=4Mhz

int decenas=0, unidades=0, decimales=0, interrupciones=1;
int tab7seg[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67};
#int_TIMER0
void Timer0_isr(void)
{
switch(interrupciones)
{
case 1:
output_high(pin_C0);
output_b(tab7seg[decenas]);
delay_ms(5);
output_low(pin_C0);
delay_ms(5);   //VER SI PUEDEN SER MENORES O CERO.
interrupciones++;
break;

case 2:
output_high(pin_C1);
output_b(tab7seg[unidades]);
delay_ms(5);
output_low(pin_C1);
delay_ms(5);   //VER SI PUEDEN SER MENORES O CERO.
interrupciones++;
break;

default:
output_high(pin_C2);
output_b(tab7seg[decimales]);
delay_ms(5);
output_low(pin_C2);
delay_ms(5);   //VER SI PUEDEN SER MENORES O CERO.
interrupciones=1;
break;
}
set_timer0(252);
}

void conversion_bcd(long temperatura);
long temperatura=0;
void main(void)

set_tris_a(0x00); 
set_tris_b(0x00); 
set_tris_c(0x00);
set_tris_d(0x00);
output_low(pin_C0);
output_low(pin_C1);
output_low(pin_C2);

output_a(0x00);
output_b(0x00);
output_c(0x00);
output_d(0x00);

enable_interrupts(INT_RTCC);               // Habilito Interrupción RTCC.
setup_counters(RTCC_INTERNAL,RTCC_DIV_256);// TIMER0: Clock Interno, Presescaler 256.

setup_adc_ports(NO_ANALOGS);
setup_adc_ports(RA0_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0); //Canal 0.
set_timer0(252); //T = (256 - precarga) * Preescaler * 4 / Fosc --->>> precarga=252

while(1)
   {
    temperatura=read_adc()*(100/51);
conversion_bcd(temperatura);

   }
}


void conversion_bcd(long temperatura)
{
while(temperatura>100)
   {
   temperatura=temperatura-100;
   decenas++;
   }

while(temperatura>10)
   {
   temperatura=temperatura-10;
   unidades++;
   }

while(temperatura>0)
   {
   temperatura=temperatura-1;
   decimales++;
   }
}
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 03 de Diciembre de 2008, 22:20:39
Hola.

Debes organizar un poco el codigo.
Código: C#
  1. setup_adc_ports(NO_ANALOGS);
  2. setup_adc_ports(RA0_ANALOG);
  3. setup_adc(ADC_CLOCK_INTERNAL);
  4. setup_counters(RTCC_INTERNAL,RTCC_DIV_256);// TIMER0: Clock Interno, Presescaler 256.
  5. set_adc_channel(0);     //Canal 0.
  6. set_timer0(252);        //T = (256 - precarga) * Preescaler * 4 / Fosc --->>> precarga=252
  7. enable_interrupts(INT_RTCC);               // Habilito Interrupción RTCC.
  8. enable_interrupts(GLOBAL);

Mira que te faltaba habilitar las interrupciones con enable_interrupts(GLOBAL).

De todas formas, revisa bien el codigo de tu interrupcion, no es la manera adecuada de multiplexar.

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 03 de Diciembre de 2008, 22:54:12
Seria mas o menos asi con un switch{ case : }:

Código: C#
  1. #include <16f877a.h>            //pic a utilizar          
  2. #fuses XT,NOWDT,NOPROTECT,PUT,NOLVP      //ordenes para el programador
  3. #use delay (clock=4000000)         //Fosc=4Mhz
  4.  
  5. int decenas=0, unidades=0, decimales=0, interrupciones=0;
  6. int tab7seg[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67};
  7. long temperatura=0;
  8.  
  9. void decimal2bcd(long temp);
  10.  
  11. #int_TIMER0
  12. void Timer0_isr(void)
  13. {
  14.         decimales=0; unidades=0; decenas=0;
  15.         decimal2bcd(temperatura);//Paso el valor a BCD
  16.         switch(interrupciones)
  17.         {
  18.                 case 0: output_high(pin_c0);//Apago el habilitador de las decenas
  19.                                 output_b(tab7seg[decimales]);//Pongo el numero de los decimales
  20.                                 output_low(pin_c2);//Enciendo el habilitador de los decimales
  21.                                 break;
  22.  
  23.                 case 1: output_high(pin_c2);//Apago el habilitador de los decimales
  24.                                 output_b(tab7seg[unidades]);//Pongo el numero de las unidades
  25.                                 output_low(pin_c1);//Enciendo el habilitador de las unidades
  26.                                 break;
  27.  
  28.                 case 2: output_high(pin_c1);//Apago el habilitador de las unidades
  29.                                 output_b(tab7seg[decenas]);//Pongo el numero de las decenas
  30.                                 output_low(pin_c0);//Enciendo el habilitador de las decenas
  31.                                 interrupciones=0;//Inicializo la variable para el multiplexaje
  32.                                 break;                         
  33.         }
  34.         interrupciones++;//Aumento la variable para el multiplexaje
  35. }
  36.  
  37. void main(void)
  38. {  
  39.         setup_adc_ports(RA0_ANALOG);
  40.         setup_adc(ADC_CLOCK_INTERNAL);
  41.         setup_counters(RTCC_INTERNAL,RTCC_DIV_256);// TIMER0: Clock Interno, Presescaler 256.
  42.         set_adc_channel(0);     //Canal 0.
  43.         set_timer0(252);        //T = (256 - precarga) * Preescaler * 4 / Fosc --->>> precarga=252
  44.         output_high(pin_c0);
  45.         output_high(pin_c1);
  46.         output_high(pin_c2);
  47.         enable_interrupts(INT_RTCC);               // Habilito Interrupción RTCC.
  48.         enable_interrupts(GLOBAL);
  49.        
  50.         while(true)
  51.         {
  52.                 temperatura=read_adc()*(100/51);
  53.         }
  54. }
  55.  
  56. void decimal2bcd(long temp)
  57. {
  58.         while(temperatura>100)
  59.         {
  60.                 temperatura=temperatura-100;
  61.                 decenas++;
  62.         }
  63.  
  64.         while(temperatura>10)
  65.         {
  66.                 temperatura=temperatura-10;
  67.                 unidades++;
  68.         }
  69.  
  70.         while(temperatura>0)
  71.         {
  72.                 temperatura=temperatura-1;
  73.                 decimales++;
  74.         }
  75. }

De todas maneras compilalo por si acaso.

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 04 de Diciembre de 2008, 10:09:30
AHi puse el switch como dijiste.....pero en vez de incrementar la variable interrupciones a la salida del switch, lo hago en cada case....y a la salida del switch puse set_timer0(252);. Con el valor de precarga calculado es MUY lenta la muestra de los valores en los displays,,,mas o menos a ojo fui probando y quedo en 220...pero sigue viendose como se prenden y se apagan los displays, no quedan siempre prendidos como en tu ejemplo.....
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 04 de Diciembre de 2008, 13:52:59
Hola.

Hay que hacer unas correcciones en el codigo que te puse:

quitar la linea interrupciones++; y colocar mejor
Código: [Seleccionar]
...
switch(interrupciones++)
{
 ...
}
...

Ya que de no hacerlo, no se deplegaria nunca el valor de los decimales.

Otra correccion que hay que hacer es en tu codigo de pasar a bcd decimal2bcd(), pon en lugar de while(temperatura>10):
Código: [Seleccionar]
while(temperatura>=10)

Con respecto a la multiplexacion, se puede ver lento por los displays que usas en la simulacion, busca unos que vienen todos juntos ya, creo que se llaman 7SEG-MPX4.., con esos da mejor resultado.

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 04 de Diciembre de 2008, 14:46:37
Ahora anda PERFECTO el tema de los displays. Cuando use los displays de 7 segs comunes no voy a tener el mismo problema que en la simulacion, no?

Ahora, no se que paso, no anda la conversion....sera algo de la simulacion? es raro porque no toque nada de eso...Si tengo saltos de 0,1v/°C, tendria que hacer (1024/5)*0.1?
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 04 de Diciembre de 2008, 19:23:37
Hola.

Debes tener en cuenta el manejo de la corriente, lo ideal es activar los displays por medio de transistores.

Pon un delay de 1 milisegundo despues de temperatura=read_adc()*(100/51);. Si vas a hacer conversiones a 10 bits debes avisarle al compilador con la directiva de compilacion:
Código: [Seleccionar]
#device adc=10
Me imagino que la temperatura no pasa de los 99.9 grados no?  :mrgreen:

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 04 de Diciembre de 2008, 20:25:02
En la simulacion esta sin transistores, pero en el circuito estan los transistores :D
AHi puse el delay de 1ms despuies de temperatura=read_adc(), pero ahora como puse que sea el conversor de 10 bits, multiplico read_adc()*((1024/5)*0.1). Una duda de sintaxis,,,es 0.1 o 0,1? Punto o coma?
Bueno, como sea, ninguno de las dos opciones me esta entregando el valor que quiero. EN la entrada del RA0 tengo una fuente de tension, en 1,23v; por lo que deberia ver 12.3 en los displays, pero veo 252 con la coma y -40 con el punto (En el -, esta apagado el display).

La temperatura es de ambiente, asi que como maximo seria de 50° C que NO creo que llegue nunca ni a un valor cercano...asi que no hay problema por eso :)
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 04 de Diciembre de 2008, 20:42:11
Hola.

Es con punto (0.1).

Si vas a pasar a voltaje analogico deberia ser read_adc() * (5/1024) * 10, o lo que seria igual:

Código: [Seleccionar]
temperatura = (float) (read_adc() * 0.04883);

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 04 de Diciembre de 2008, 21:19:02
AHi anda, pero cuando pongo en la misma linea (5/1024)*10 no lo hace me muestra 000, pero si pongo el resultado de la operacion directamente me muestra bien el numero.
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 05 de Diciembre de 2008, 12:04:17
Hola.

Es por el tipo de variable. Tu al hacer la operacion vas a obtener un float, si tu no le avisas al compilador mediante el casting, o sea el: (float), el te retornara el valor decimal de la operacion, es decir 0.

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 05 de Diciembre de 2008, 14:21:45
la variable es float, pero igual sigue dando cero con
Código: [Seleccionar]
temperatura=(float) read_adc()*(500/1024);
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: MLO__ en 05 de Diciembre de 2008, 14:48:22
Hola.

 :-)

El resultado de la division es 0.04883 ... aunque el compilador haga bien la operacion, es decir, con la precision de un float, nosotros estamos guardando la variable en un long, por lo tanto guarda la parte entera de la division, es decir cero.

Podrias usar una variable auxiliar tipo float para guardar el resultado de la division y luego multiplicarla por el valor retornado por read_adc() ... pero seria mas memoria ...

Yo acostumbro ha dejar solo las operaciones necesarias ... en este caso el valor 50/1024 va a ser siempre constante por lo que lo pre-calculo y lo uso en el programa como una constante.

Saludos
Título: Re: Problema Sensor de temp y 3 displays
Publicado por: aripod en 05 de Diciembre de 2008, 15:03:13
Cambie el tipo de la variable temperatura a float ahora tambien....Yo decia ponerlo en el calculo para no perder presicion en el calculo, aunque puse varios decimales....Aunke es cierto que poner la constante seria menos memoria en el programa.....