TODOPIC

FORO TÉCNICO => Foro Técnico => Mensaje iniciado por: DarkVect en 08 de Octubre de 2008, 14:40:30

Título: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: DarkVect en 08 de Octubre de 2008, 14:40:30
Hola,

He bajado esta herramienta, muy útil por lo que parece, para calcular Timers y demás cosas pero tengo un problema: ¿Cómo demonios calcula los tiempos?

Me explico: para un reloj de 4MHz, un timer de 8 bits, un escaler de 2 y sin precarga me da un valor de 516,0us y aplicando la formulita típica eso debería ser:

4/4MHz * 2 * 256 = 512us ¿De dónde sale la diferencia? Tiene que ver con el reload (lo tengo a 4 ciclos para u PIC16F)?

Lo mismo pasa para el resto de temporizaciones, siempre hay diferencia entre lo teórico y lo que da el programa, que se supone debería ser lo teórico también.

Gracias por la ayuda.

Título: Re: PIC Multi Calc
Publicado por: PalitroqueZ en 08 de Octubre de 2008, 15:40:26
Es por el reload, ponlo al mínimo.

En realidad "asumo" que el reload incluye el tiempo en el que entra y sale de la interrupción (y también el momento a partir del cual se carga el timer de nuevo)


Título: Re: PIC Multi Calc
Publicado por: DarkVect en 09 de Octubre de 2008, 04:02:49
Sí, yo también creo que es el reload. Lo tengo puesto a 4 porque al lado pone Cycle Inst. y es lo que dura en el PIC. No tengo el programa a mano ahora, pero si lo cambio diría que me cambiará también el 4 de la fórmula teórica para los ciclos de instrucción, no?

De todos modos, si debido a la entrada y salida los tiempos no son exactos, para que usar un rleoj de 3,2768MHz para lograr un segundo si al fin y al cabo con el reload no será un tiempo exato. Mientras tanto con un 4MHz que en principio no da el segundo exacto, con este retardo se consigue una aproximación muy muy cercana ¿?
Título: Re: PIC Multi Calc
Publicado por: PalitroqueZ en 09 de Octubre de 2008, 14:04:39
la mejor prueba es simular el código (mplab ó proteus) y ajustar los tiempos si se da el caso.

Título: Re: PIC Multi Calc
Publicado por: DarkVect en 10 de Octubre de 2008, 04:08:56
SOLUCIONADO:

Del Datasheet: Cuando se escribe, es decir cuando se utiliza el preload, del Timer0 la cuenta se retrasa siempre 2 ciclos de rleoj por la lógica interna del PIC. De ahí que SIEMPRE que se utilice un set_timer0 hay que tener en cuenta esos dos ciclos adicionales.

Por ejemplo:

A 4MHz el ciclo de instrucción es de 1MHz, utilizando un divisor de 8 tenemos un periodo de 8us. Imagines que sólo queremos contar 100 veces dicho periodo, esto impleicaría realizar una precarga en el timer de 156. Sin embargo y debido al "problema" del retraso, el valor real que se debe cargar es de 158, para que realmente cuente sólo 98 en lugar de 100.

Aquí hay un muy buen link (ver imagen del programa):

http://www.best-microcontroller-projects.com/pic-timer-0.html

Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: RedPic en 10 de Octubre de 2008, 06:47:57
Hummmmm .... very insteresting.  :shock:

Muchas gracias por la nota. :mrgreen:
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: DarkVect en 10 de Octubre de 2008, 07:22:50
La verdad es que sí...  :shock:

Aquí está el Datasheet de un 16F818 donde se explica claramente en la sección 6.1 Timer0 Operation:

http://ww1.microchip.com/downloads/en/DeviceDoc/39598e.pdf

Se puede leer que "si el registro del timer es escrito la interrupción se dehabilita durante los 2 ciclos de reloj siguientes" cosa que genera el comentado problema de precisión. La solución es o no escribir xDDDDD o cargar el timer con +2 ciclos.
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: Nocturno en 10 de Octubre de 2008, 08:38:39
Yo hasta ahora siempre ajustaba de manera empírica, pero gracias a esta investigación  ya sé porqué nunca me cuadraba a la peseta.
Gracias.
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: DarkVect en 10 de Octubre de 2008, 12:40:10
Me alegro de que solucionaras el "misterio"

Dichosos Datasheet!! Mira que viene todo, todito, todo!!!
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: flacoclau en 10 de Octubre de 2008, 12:48:25
Eso ya lo tenía visto en el datasheet cuando hice el tema del sincronismo de tv, todo esto viene a que no hay mejor cosa que imprimir y encuadernarlo para tenerlo a mano, sobre todo cuando voy al baño!!!  :D
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: DarkVect en 10 de Octubre de 2008, 12:52:57
Ya que el tema empezaba con el PIC Multi Calc voy a decir que es la re-ostia, con perdón!!

Cuando nos hace las cuentas YA tiene en cuenta todo esto!! Por ejemplo:

Reloj de 4MHz y queremos 1ms en la interrupción:

Solución:

Pre-escaler=4
Pre-load=7
Error=0,00%

El cálculo: 4/4MHz * 4 * (256-7)= 0,996ms -> con los dos ciclos de retraso del timer por usar pre-load (2 * 4/4MHz * 4) = 1ms EXACTO!!

Fascinante!!!  :-/ :-/
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: PalitroqueZ en 10 de Octubre de 2008, 14:01:11
Que bueno que lo solucionaras, yo uso mucho ese programa, por la flojera de estar sacando cuentas y como siempre le hago pruebas de tiempo al programa principal, entonces siempre tengo mi tiempo requerido.  :)

por cierto la página principal del PIC Multi Calc está caida  :(

Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: Nocturno en 11 de Octubre de 2008, 01:58:54
¿Cuál es la página?
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: doppel en 11 de Octubre de 2008, 02:05:45
Hola manolo

es esta: http://www.mister-e.org/

saludos

Hernán
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: pocher en 15 de Octubre de 2008, 04:50:29
No tengo muy claro que la reducción de 2 ciclos en la precarga del TMR0 consiga hacer ir bien a un reloj. Habría que probarlo, personalmente creo que lo mejor para conseguir una base de tiempos exacta es no hacer precargas con el set_timer0.
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: Nocturno en 15 de Octubre de 2008, 05:54:48
¿Porqué Pocher?, si siempre tarda lo mismo y podemos descontar su efecto no veo la razón por la que no debería ser preciso.
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: DarkVect en 15 de Octubre de 2008, 08:05:56
En los data de los PIC e incluso en el data general donde se recogen los aspectos comunes de éstos NO dice nada en contra de escribir sobre el registro del timer. De hecho lo único que remarcan es esa inhabilitación del conteo durante dos ciclos de reloj. Eso es exacto y preciso.

Lo que ya no tengo claro es lo de escribir sobre el Timer1. Si miráis el data genérico pone que no es recomendable hacer escrituras sobre el registro bajo del timer, por lo que según entiendo sólo se podrían cargar valores múltiplos de 256 que son los que van en el registro alto. Alguna idea sobre esto?
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: PalitroqueZ en 15 de Octubre de 2008, 13:07:51
No tengo muy claro que la reducción de 2 ciclos en la precarga del TMR0 consiga hacer ir bien a un reloj. Habría que probarlo, personalmente creo que lo mejor para conseguir una base de tiempos exacta es no hacer precargas con el set_timer0.

conseguir la presición de un timer, es poco probable, porque caeriamos en el tema de factores externos, sobreencabezamientos (overhead) en lenguajes de alto nivel, etc. Lo mejor en estos casos:

Citar
la mejor prueba es simular el código (mplab ó proteus) y ajustar los tiempos si se da el caso.

Título: Siguen sin darme los calculos :?
Publicado por: Marttyn en 03 de Noviembre de 2008, 00:35:40
No me dan los calculos  :?
Estuve leyendo el post, y por lo visto el Timer0 pierde 2 ciclos con la pregarga... por lo visto esto no afecta al timer1 segun lei en algun lado...
Pero aun asi no me dan los calculos... quiero contar 20mS (20.000uS) y para ello uso el timer1 con precarga de 45535 (65535 - 45535 = 20000)
Los resultados son estos:

(http://i299.photobucket.com/albums/mm317/Marttyn/Electronica/Dibujo2-2.jpg)

Como se ve en el stop watch, me paso por 39 (TREINTAYNUEVE  :shock:) instrucciones. Seria comprensible que me pasara por 7 instrucciones (4 para la precarga y 3 pasa retomar el programa), ya que es lo que se demora dentro de la interrupcion.... pero donde esta todo el tiempo que me sobra?

el codigo lo reduje a lo mas simple... osea, solo la interrupcion:

Código: C
  1. #include <12F683.h>
  2. #device adc=8
  3.  
  4. #FUSES NOWDT,NOMCLR,PUT,INTRC_IO
  5. #use delay(clock=4000000)
  6.  
  7. #int_TIMER1
  8. void TIMER1_isr(void) {
  9.         set_timer1(45535);
  10. }
  11. void main() {
  12.        
  13.         setup_adc_ports(NO_ANALOGS|VSS_VDD);
  14.         setup_adc(ADC_CLOCK_INTERNAL);
  15.         setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  16.         setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  17.         setup_timer_2(T2_DISABLED,0,1);
  18.         setup_comparator(NC_NC);
  19.         setup_vref(FALSE);
  20.         disable_interrupts(INT_TIMER0);
  21.         enable_interrupts(INT_TIMER1);
  22.         enable_interrupts(GLOBAL);
  23.         setup_oscillator(OSC_4MHZ);
  24.        
  25.         set_timer1(45535);
  26.  
  27.         do{                    
  28.  
  29.         }while(TRUE);  
  30. }

haciendo un par de pruebas veo que desde el momento que se produce INT_TIMER1 tarda 35 instrucciones en llegar a la primer instruccion dentro de la interrupcion (ahi estan los 39 ciclos perdidos, 35 + 4 ciclos de precarga). Pero no solo eso! una vez acabada la ISR del timer, le lleva 26 instrucciones mas retomar el programa donde estaba  :shock: :shock:
Como es eso posible? Es por la traduccion de C a ASM? o en ASM pasa lo mismo?
Ahora entiendo porque nunca pude hacer andar un servo a la perfeccion! es imposible generar los 20mS exactos sin estar al tanto de todas estas cosas  :mrgreen:
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: Marttyn en 03 de Noviembre de 2008, 02:01:26
Haciendo mas pruebas veo que para entrar en las ISR lleva unas cuantas instrucciones desde que se produce la interrupcion:
TMR0: 39 instrucciones
TMR1: 36 instrucciones
TMR2: 41 instrucciones
CCP1: 41 instrucciones

Salir de estas interrupciones y retomar el programa consume 26 instrucciones para cualquiera de ellas.
Estas pruebas las hice con un 12F683, en modo debug con el stop watch de mplab, y usando lenguaje C.
Alguna conclusion?  :z)

Si alguien quiere comprobar o continuar con estas pruebas dejo el codigo fuente que use. Solo hay que comentar y descomentar las lineas necesarias para probar cada interrupcion
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: Nocturno en 03 de Noviembre de 2008, 03:41:52
Sí, Marttyn, eso pasa siempre con las interrupciones: hay que salvar el contexto y determinar qué tipo de interrupción es antes de devolver el control al programa.
Cuando sales de la interrupción hay que dejar el contexto como estaba.
Todo eso consume los ciclos que tú dices.
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: BrunoF en 03 de Noviembre de 2008, 04:25:47
Buenas.

Lo que comentás es completamente cierto y existe, tanto en C como en ASM.
Esas 35 instrucciones que comentas son seguramente las que guardan los registros clave(como el W,STATUS,FSR...) y hacen la selección de cuál interrupción se produjo. Voy a destacar que en ASM bajo ciertas condiciones y truquillos es posible achicar bastante ese número de instrucciones. En el caso de un compilador ya no es tan sencillo ya que deberías modificar el ASM de salida a mano para lograrlo.

Las importantes son las instrucciones antes de ser atendida una interr. y no las que tarda en salir de la ISR(al menos para los Timers con tiempos medianos o grandes). A esto lo digo porque no interesa si tarda 10 o 100 instrucciones antes de salir de la ISR, ya que el Timer estará contando igualmente aunque se encuentre dentro de la ISR. Obviamente supongo que estará más que sobreentendido que no es necesario que el uC se encuentre fuera de la ISR para que un timer cuente ;).

Ahora, si nos vamos a poner en exquisitos hay muchísimos factores a considerar. Ya han mencionado varios: los 2 ciclos de ejecución durante los cuales el timer no se incrementa cuando se carga un valor en su registro, las instrucciones antes de llegar a realmente precargar el timer y otras que no se han comentado como, por ejemplo,  cuando se produce una interrupción, el uC automáticamente carga el vector 0x004(en el pic que exponés, 12F683) y eso lleva 2 ciclos de instrucción(es una especie de "call 0x004"). Además, puede que la interrupción tarde en producirse un poco más entre que el Timer se desborda y el uC realmente se percata de esto(CREO que son 2 ciclos más en el caso del TMR0). Dependiendo del tipo de interrupción, el uC puede tardar más en detectarla. Por ejemplo, una interrupción por cambio de estado del puerto b(RB4-RB7) lleva entre 3 y 4 ciclos de ejecución antes de que el uC se percate de que realmente se produjo y efectivice la interrupción.

En definitiva: lo que necesitás sencillamente es agregar a la formulita un numerito más que represente todos esos ciclos adicionales que hay que contemplar según la interrupción(y según lo que al compilador le de la gana (que es un verdadero trastorno, ya que también depende de su versión)).

Tiempo de desbordamiento =  [(256-TMR0) * PREESCALER + A+ 4 + B] * (4/FOSC)

A= 2 si  es que hay precarga del TMR0
B= número de instrucciones antes de que se se precargue el TMR0

Los cuatro ciclos adicionales correspondes 2 al tiempo de sincronísmo entre los relojes del uC, y dos más del call 0x004. Tal vez eso demuestre la incongruencia entre tus cálculos teóricos iniciales y los del programita que usabas para calcularlos.

Si no se precarga el registro TMR0, A no exíste y B no tiene importancia(se ignora).

Saludos.



Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: DarkVect en 03 de Noviembre de 2008, 08:53:27
Marttyn el problema que creo que tienes con el timer1, al cual NO aplica lo de la deshabilitación durante 2 ciclos después de escribirlo, es que según entiendo yo del Datahseet NO se debe escribir en su registro bajo. Es decir, en los set_timer1 diría que hay que cargar valores múltiplos de 256 para no modificar ese registro bajo.

Alguien puede confirmar esto?
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: BrunoF en 03 de Noviembre de 2008, 15:43:22
Hola DarkVect.

No puedo confirmarlo, tampoco refutarlo completamente pero desde mis humildes conocimientos diría que lo que comentás no es posible. El Timer1 consta de dos registros: TMRH y TMRL y ambos son leibles/escribibles. Si querés podés no escribir el registro bajo, pero no vas a lograrlo con la instrucción set_timer1 ya que seguramente siempre te escriba ambos indiferentemente del valor que le cargues.

Saludos.
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: Marttyn en 03 de Noviembre de 2008, 18:34:32
Gracias Bruno!
Muy buena tu explicacion! Seguire con las pruebas y estudiare algo de ASM para poder optimizar el codigo  lo mas posible cuando sea necesario :mrgreen:

Por cierto, DarkVect lo de la precarga solo con multiplos de 255, no lo se, pero como dice bruno, cuando haces un set_timer1() se generan las respectivas instrucciones en ASM para escribir tanto en la parte alta como en la parte baja del registro del timer, por lo que si el compilador lo hace asi, no deberia haber problemas por ello...
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: DarkVect en 03 de Noviembre de 2008, 21:53:05
Bueno, que el compilador lo haga así no asegura que sea lo correcto ya que en los ejemplos que da en el manual no tienen enuenta los dos ciclos de deshabilitación del Timer0, por ejemplo.

Aquí un datasheet como ejemplo. En la pág. 59 columna derecha lo explica, pero ahora que lo miro bien es para cuando se usa como Contador Asíncrono. También podría ser que CCS parase el timer, escribiese y lo volviese a poner en marcha, cosa que también significaría algunos ciclos de retraso.

http://ww1.microchip.com/downloads/en/DeviceDoc/39598e.pdf
Título: Re: Problema Precisión Timer0 - SOLUCIONADO (INTERESANTE)
Publicado por: Marttyn en 04 de Noviembre de 2008, 01:12:27
Gracias a todos por salpicarme con su sabiduria!  :-/
Mientas mas me explicais, mas aprendo y mas ganas de saber tengo! Pero mis preguntas se estan desviando del tema principal de este POST, asi que retomare mis dudas aqui:
http://www.todopic.com.ar/foros/index.php?topic=23662.0
Si alguien quiere pasarse por ahi se lo agradezco!
Salu2