Autor Tema: Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.  (Leído 2656 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Carlos2302

  • PIC16
  • ***
  • Mensajes: 110
Hola muchachos quiero saber si alguien puede ayudarme sobre esto que me esta pasando con esta practica con un atmega8-pu, lo que pasa es lo siguiente diseñe un programa en codigo C para el micro, cuando uso el tmr0 para generar un retardo el programa me ejecuta a la perfeccion, cuando quito la señal de cualquier sensor el lcd me marca cero temperatura como debe ser correcto.
Diseñe otro programa para generar interrupciones largas de 5 seg, con el tmr1 y usando la interrupcion ISR(TIMER1_OVF_vect) pero cuando ejecuto dicho codigo en el micro no me lee bien las entradas de los sensores me produce 10 de mas en las lecturas y cuando quito las señales de los sensores me dan una lectura de 10mV de ahi deduzco que por eso me genera los 10 de mas en la lecturas. pero como una imagen vale mas de mil palabras les adjunto imagenes y los programas la simulacion esta dentro de la carpeta debug.
Gracias a Dios por aquellas personas que ayudan sin esperar nada a cambio. Dios los bendiga hoy mañana y siempre.

Desconectado Carlos2302

  • PIC16
  • ***
  • Mensajes: 110
Re:Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.
« Respuesta #1 en: 24 de Marzo de 2016, 22:27:12 »
Unas imagenes
Gracias a Dios por aquellas personas que ayudan sin esperar nada a cambio. Dios los bendiga hoy mañana y siempre.

Desconectado Carlos2302

  • PIC16
  • ***
  • Mensajes: 110
Re:Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.
« Respuesta #2 en: 24 de Marzo de 2016, 22:27:51 »
Otra mas
« Última modificación: 24 de Marzo de 2016, 22:30:46 por Carlos2302 »
Gracias a Dios por aquellas personas que ayudan sin esperar nada a cambio. Dios los bendiga hoy mañana y siempre.

Desconectado Carlos2302

  • PIC16
  • ***
  • Mensajes: 110
Re:Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.
« Respuesta #3 en: 24 de Marzo de 2016, 22:31:56 »
La ultima
Gracias a Dios por aquellas personas que ayudan sin esperar nada a cambio. Dios los bendiga hoy mañana y siempre.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.
« Respuesta #4 en: 24 de Marzo de 2016, 22:57:08 »
Tenes un problema ... y es que crees que la interrupcion podes hacer cualquier cosa, y meter delays etc. Antes de tratar eso voy a intentar omitir esta linea de programa:

Código: C
  1. lcd_puts("Danielito te amo");

La cual asume un gran amor por vos mismo :D , y que me parecio raro encontrar algo asi cuando compartis el proyecto. Ahora si que lo evitamos, vamos al tema de las interrupciones:

Tenes que entender que es una interrupcion, la idea de una interrupcion es que al ocurrir se ejecute rapidamente y luego continue el programa principal, sin afectarlo en "tiempos", es decir deberia ser lo mas rapido posible, y ademas cuando hay en proceso una interrupcion deshabilita las demas globalmente, esto es de vital importancia si queres hacer funcionar algo. NUNCA pero NUNCA tardes en una interrupcion, por que mientras mas tardas, mas tardas cualquier otra interrupcion. Veamos tu codigo y voy a remarcar en negrita lo que tarda y que no deberia estar en una interrupcion:

(Lo puse en un quote para poder marcarlo en negrita)
Citar
ISR(TIMER1_OVF_vect){
   PORTB |=(1<<PB1);
   cli();
   ADCSRA |=((1<<ADEN)|(1<<ADSC));//enciendo y inicio la conversion
   while(ADCSRA&(1<<ADSC));  //me quedo esperando a que termine la conversion
   ADCSRA&=~(1<<ADEN); //Apago el conversor despues de terminada la conversion
   Valor_adc=ADC; //ADC es un registro de 16 Bits formados por ADCL y ADCH
   temp1=(float)Valor_adc*(240)/1024;
   //temp1=temp1-9.5;
   sprintf(mensaje_temp_1,"Temp1 %.1f C",temp1);
   _delay_ms(100);

   PORTB &=~(1<<PB1);
   _delay_ms(100);
   
   PORTB |=(1<<PB1);
   ADMUX  |= ((1<<MUX0)|(1<<MUX2)); // canal de entrada 5 pin28 del micro
   ADCSRA |=((1<<ADEN)|(1<<ADSC));//enciendo y inicio la conversion
   while(ADCSRA&(1<<ADSC));  //me quedo esperando a que termine la conversion
   ADCSRA&=~(1<<ADEN); //Apago el conversor despues de terminada la conversion
   Valor_adc_1=ADC; //ADC es un registro de 16 Bits formados por ADCL y ADCH
   temp2=(float)Valor_adc_1*(240)/1024;
   //temp2=temp2-9.5;
   sprintf(mensaje_temp_2,"Temp2 %.1f C",temp2);
   ADMUX&=~((1<<MUX0)|(1<<MUX2));//selecciono nuevamente canal 0
   _delay_ms(100);
   PORTB &=~(1<<PB1);
   
   lcd_clrscr();
   lcd_puts(mensaje_temp_1);

   if (Valor_adc > 143)
   {
      PORTB |=(1<<PB0);
   }
   else{
      PORTB &=~(1<<PB0);
   }
   lcd_gotoxy(0,1);
   lcd_puts(mensaje_temp_2);
   _delay_ms(1000);
   
   TCNT1= 57722; //1 seg
   //TCNT1= 26472; //5 seg
   sei();
}

Resumen, lo que vos deberias estar haciendo en la rutina principal lo estas haciendo en la interrupcion, y ese es tu problema.
Tratas de crear una interrupcion de 1 segundo y aun asi tenes puesto en delays 1.4s sin contar las operaciones con flotantes que son "intensivos" en un Microcontrolador que no poseen modulo para esto, divisiones, multiplicaciones, y tambien LCD que suelen tenes bastantes delays entre medio solo para enviar datos al LCD, ni contar lo que se tarda en convertir de un flotante a un string. Y si fuera el colmo, 2 while dentro.
Es decir solo tenes que realizar operaciones simples. Nada mas. tal ves activar un flag ( un bit ) para avisarle al programa principal que hago lo que debe hacer.

Otra de las cosas es que no tenes que desactivar y activar las interrupciones con cli() y sei(), el mismo micro cuando entra a una interrupcion se desactiva la interrupcion global, es decir pone a 0 el bit de las interupciones globales haciendo que dentro de la interrupcion no pueda existir OTRA interrupcion que lo saque de alli. Cuando se termina la interrupcion hay una instruccion especial que ademas de volver a donde estaba activa las interrupciones globales, asi que nunca nunca pongas un cli() o sei() dentro de la interrupcion. El mismo micro y el compilador se encargan de esto.

Intenta mover eso a tu rutina principal ( el while(1) ) e intentar depender menos de los delays, esos 2 consejos van a llevar que tu prorgama y cualquier programa funcione mucho mejor.
« Última modificación: 24 de Marzo de 2016, 23:26:03 por KILLERJC »

Desconectado Carlos2302

  • PIC16
  • ***
  • Mensajes: 110
Re:Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.
« Respuesta #5 en: 24 de Marzo de 2016, 23:46:20 »
Gracias por tu ayuda mi hermanazo, y lo de danielito te amo es por mi hijo de 8 años jajaja se me olvido quitar eso. Bueno como puedes ver en el otro programa con utilizando en tmr0 y sin usar interrupciones funciona de maravillas como deberia por eso coloque las fotos.
Gracias a Dios por aquellas personas que ayudan sin esperar nada a cambio. Dios los bendiga hoy mañana y siempre.

Desconectado Carlos2302

  • PIC16
  • ***
  • Mensajes: 110
Re:Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.
« Respuesta #6 en: 25 de Marzo de 2016, 00:01:31 »
Y sera por eso que cuando quito las señales de los sensores el lcd me sigue dando lectura de temperatura 10. Y cuando conecto el sensor me suma esa diferencia :-(.
Gracias a Dios por aquellas personas que ayudan sin esperar nada a cambio. Dios los bendiga hoy mañana y siempre.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.
« Respuesta #7 en: 25 de Marzo de 2016, 00:14:35 »
Bueno como puedes ver en el otro programa con utilizando en tmr0 y sin usar interrupciones funciona de maravillas como deberia por eso coloque las fotos.

Si, esa es una forma de hacerlo. La otra forma de hacerlo que tenias era que si duraba 128us , significaba que debias esperar 30.51 overflows del Timer0 ( 1/128us / 256 )

Esperas 30 de esos mirando el flag de interrupcion, pero sin activarlas obviamente, y cuando estas en la 30, esperas hasta que llegue a 132 (0.51 * 256). Y alli tenes tu segundo de nuevo.

Y sera por eso que cuando quito las señales de los sensores el lcd me sigue dando lectura de temperatura 10. Y cuando conecto el sensor me suma esa diferencia :-(.

Ojo que si quitas el sensor segun como tengas el circuito podes dejar el pin al aire y captar cualquier cosa menos 0V, quedaria en 0V si es que existe algo que lo lleve a ese valor como un pull-down.
Por ahora vamos por parte, primero es tratar de arreglar la interrupcion para que funcione como corresponde. es decir si queres una interrupciones de 1s deberia ser asi:

Código: C
  1. ISR(TIMER1_OVF_vect)
  2. {
  3.         ++contadorinterrupciones
  4.         if(contadorinterrupciones == 30 )
  5.         {
  6.                 TCNT0 = 256-132;                // El complemento a 2, la proxima interrupcion es la que vale
  7.         }
  8.         else if(contadorinterrupciones == 31 )
  9.         {
  10.                 PORTB ^= _BV(PB0);
  11.                 contadorinterrupciones = 0;
  12.         }
  13. }
(Creo que el compilador limpia el flag automaticamente)

Configurado el timer con preescaler 1024, y con un valor inicial de 0.
Luego vamos a ver el tema de los sensores. Aunque todavia no entendi para que necesitas esta interrupcion.

Desconectado Carlos2302

  • PIC16
  • ***
  • Mensajes: 110
Re:Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.
« Respuesta #8 en: 25 de Marzo de 2016, 00:48:55 »
Bueno estoy usando las interrupciones solo como parte de mi aprendizaje nada mas por eso y pues mi intencion era que el micro se quedara sin hacer nada osea en el bucle while(1) durante 1 seg o mas, mientras pensaba que hacer en dicho bucle. pero ya voy a reescribir el codigo para no usar interrupciones ni temporizaciones con los modulos TMRx, solo voy a usar las rutinas de espera de la funcion de retardos. Me has ayudado mucho y me has abierto los ojos en cuanto al tema de las interrupciones. Yo pence que podia demorarme todo lo que quisiera dentro de ellas. Referente a cuando desconecto las señales de los sensores efectivamente tengo unas resistencias de 1k pull down y sin embargo no me marca los cero voltios cuando uso la rutina de interrupcion del tmr1, pero cuando uso el otro programa si me crea los cero voltios. a veces pienso que cuando trabaja el tmr1 me induce un ruido electrico y por eso es que no me llega a cero voltios.
Gracias a Dios por aquellas personas que ayudan sin esperar nada a cambio. Dios los bendiga hoy mañana y siempre.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conversor A/D LM35 y LCD con interrupciones de los temporizadores Ayuda.
« Respuesta #9 en: 25 de Marzo de 2016, 01:32:45 »
Intenta algo mas simple.. En ves de estar leyendo sobre el LCD el valor de una operacion que es con coma y puede causar problemas (por la precision), trata de mostrar el valor directo del ADC.

El ADC deberia tener una salida de 0 a 1023 ( Suponiendo que no lo hiciste justificado a la izquierda )
No mostrar la "temperatura" calculada , si no el valor del ADC:

sprintf(mensaje_temp_1,"Temp1 %i",Valor_adc);

Y de esa forma podes dividir en parte para ver donde esta el error

RESUMEN!!!

Posibles errores:

- Tiempo de adquisicion:

Código: C
  1. ADMUX  |= ((1<<MUX0)|(1<<MUX2)); // canal de entrada 5 pin28 del micro
  2.    //Aca pequeño delay
  3.    ADCSRA |=((1<<ADEN)|(1<<ADSC));//enciendo y inicio la conversion

Luego de cambiar de canal segun la impedancia que tengas conectado, el micro necesita un tiempo hasta que el capacitor del ADC se descargue y carge con la nuevo valor de tension. Asi que deberias poner un pequeño delay, que tal ves con 1 ms es suficiente. O trata de leer solo 1 entrada por ahora, de esa forma no cambias de canales. El tiempo de adquisicion va a depender de la resistencias que tengas puestas y capacidades externas.

- Verificar con el multimetro y LCD:

Si mostrando el valor del ADC en el LCD (antes resolver el posible problema de arriba) ves que no llega a 0 cuando quitas el sensor, es por que existe una tension que esta entrando en el PIN y que deberias verificarlo con el multimetro. Si aun asi el multimetro marca 0V. Y seguis teniendo valores mayores a 0 del ADC Probaria poniendo el canal 1111 que es 0V ( GND ) lo podes ver a esto en el datasheet. Y ahi deberia darte 0V si o si. Sino pienso que podria ser un problema del ADC. Ya que no hay forma de cambiar a otro valor.

Si es 0 el resultado de Valor_adc y es 0V la entrada medida con el multimetro, entonces hay algo mal en el proceso de convertir el valor del ADC a la temperatura.

Asi dividiendo las causas, podes ir acortando los posibles problemas.