TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: micro_pepe en 16 de Septiembre de 2018, 18:19:54

Título: Interrupción en asm dentro de XC8
Publicado por: micro_pepe en 16 de Septiembre de 2018, 18:19:54
Estoy haciendo una interrupción del TIMER1 en XC8 en asm de la siguiente forma:

Código: C
  1. void interrupt INTERRUPT_InterruptManager() {
  2.   #asm
  3.   _asm
  4.  
  5.   nop
  6.   nop
  7.   nop
  8.   nop
  9.   nop
  10.   nop
  11.   nop
  12.   bcf   PIR1,0      ;borra flag timer1
  13.   _endasm
  14.   #endasm
  15. }

Si pongo un punto de ruptura en el primer nop, desde que se produce la interrupción hasta que llega a ese punto, pasan 11 o 16 ciclos de instrucción, dependiendo de si uso la compilación profesional o la estándar; no quiero que dependa de eso, puede que incluso de una versión a otra de xc8 cambie ¿Hay alguna manera de incluir el vector de interrupción en asm? si no creo que no queda más remedio que hacer todo el programa en asm.

Gracias!!! un saludo.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: KILLERJC en 16 de Septiembre de 2018, 18:45:57
No entiendo cual es tu propósito de realizar eso...
Obviamente que depende de la frecuencia a que te manejes, pero 11 a 16 ciclos para salvar el contexto e ir a la interupcion no veo cual es el problema.

Si estas tan jugado por esos ciclos en el tiempo, considero que deberias estar buscando mas frecuencia.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: micro_pepe en 16 de Septiembre de 2018, 18:53:16
No entiendo cual es tu propósito de realizar eso...
Obviamente que depende de la frecuencia a que te manejes, pero 11 a 16 ciclos para salvar el contexto e ir a la interupcion no veo cual es el problema.

Si estas tan jugado por esos ciclos en el tiempo, considero que deberias estar buscando mas frecuencia.

El PIC funciona a 20MHz y pretendo hacer un frecuencimetro de hasta 50MHz, lo más preciso posible, entonces hay un error de 10Hz por cada ciclo de instrucción, puedo medir la base de tiempo en simulación, y calcular la frecuencia con ese dato, pero no quiero que dependa del compilador.

Saludos!!!
Título: Re:Interrupción en asm dentro de XC8
Publicado por: KILLERJC en 16 de Septiembre de 2018, 23:48:39
Tal ves te sirva:

http://www.electronics-lab.com/project/100mhz-frequency-counter-with-pic16f628a/
Título: Re:Interrupción en asm dentro de XC8
Publicado por: micro_pepe en 17 de Septiembre de 2018, 17:48:09
Está bien la idea, lo que no sé es como de estable y preciso es el TIMER1 con un cristal de 32765Hz, frente a un TCXO de 20MHz.

En el foro vi un frecuencimetro diseñado por Picuino con un PIC18F2550, pero los archivos ya no funcionan. Por lo que vi, toma una diferencia de tiempo y otra de pulsos contados, y de ahí calcula la frecuencia.

Saludos!!!
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 18 de Septiembre de 2018, 11:10:54
Si es para un frecuencimetro, puedo ayudar.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 18 de Septiembre de 2018, 17:34:17
¿Qué precisión quieres conseguir?
Título: Re:Interrupción en asm dentro de XC8
Publicado por: micro_pepe en 19 de Septiembre de 2018, 13:11:50
¿Qué precisión quieres conseguir?

Quisiera que a fondo de escala (50MHz) tenga un error de +/-10Hz, y me gustaría hacerlo con un pic pequeño, de 8 patas, para visualizar el resultado en un PC via RS232, o en un LCD que funcione via puerto serie, no sé si es posible, por las cuentas que he hecho, si uso un timer para contar y otro para la base de tiempo, por interrupción, cuando se dé el caso de que se produzcan a la vez, la base de tiempo o el contador se verán afectadas.

Gracias, un saludo!!!
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Yoshua en 19 de Septiembre de 2018, 13:51:48
Para la frecuencia, los incrementos de desborde del timer contador se hacen en un bucle que espera a que el tiempo de base termine. Se me ocurre que la manera de hacerlo seria que en la interrupción manejada en asm habilite y deshabilite el timer en la misma cantidad de ciclos de instrucción.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 19 de Septiembre de 2018, 15:11:31
Se puede hacer, pero vas a tener varios problemas.

Esa precisión es imposible con un xtal normal, que puede variar eso al aumentar un poco la temperatura. Necesitas un tcxo y te costará encontrar uno con esa precisión. Con 1ppm (+-50) ya puedes darte por satisfecho. En ebay hay ocxo de segunda mano por 20€, con los que puedes conseguir esa precisión.

Esa resolución se puede conseguir sin problema. Está justo en el límite de los números en coma flotante.

Yo he hecho experimentos con el pic16f628 y funciona para lo que tu quieres. Otros micros más modernos tienen muchos periféricos que ayudan, pero la señal de entrada está limitada al sincronizarla siempre con el oscilador interno. No te los recomiendo.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 19 de Septiembre de 2018, 15:17:07
http://ww1.microchip.com/downloads/en/DeviceDoc/40044G.pdf
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 19 de Septiembre de 2018, 15:21:13
http://www.electronics-lab.com/project/100mhz-frequency-counter-with-pic16f628a-2/
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 19 de Septiembre de 2018, 15:25:49
Te recomiendo que compres un receptor gps, para afinar la base de tiempos. Puedes encontrar uno en ebay por unos 10Euros. Te dará un pulso por segundo con una precisión de 100ns (0,1ppm) y aún más precisión si cuentas varios pulsos durante un minuto.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 19 de Septiembre de 2018, 15:35:11
Si quieres experimentar, esto tiene la precisión que necesitas:

Homebrew ocxo
Título: Re:Interrupción en asm dentro de XC8
Publicado por: micro_pepe en 20 de Septiembre de 2018, 13:13:48
Que tal uno de estos con un divisor de frecuencia?

https://www.tme.eu/es/details/i547-2p3-40.0000m/generadores-de-cuarzo-smd/ilsi/i547-2p3-400000-mhz/

Tengo entendido que si divido entre 2 la frecuencia, mejora en igual cantidad la precisión y la estabilidad.

Para hacer pruebas ¿Que tal es de fiable simular en Proteus? para obtener una base de tiempos teórica que funcione, luego habría que afinar en la práctica.

Saludos!!!
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 20 de Septiembre de 2018, 14:28:32
El que yo probé era bastante malo, porque se mantenía en su rango de error, pero con mucho jitter. La frecuencia oscilaba contínuamente en torno al rango de error, pero sin salirse de este.
Si divides la frecuencia, la precisión sigue siendo la misma, 2ppm. Pero al tener jitter, la resolución también será esa.

Te pongo un ejemplo. Al medir con ese tcxo, la medida de 50Mhz va a saltar continuamente entre 50.000.000 Hz y 50.000.100 Hz sin estabilizarse.
Eso a mí no me gusta nada. Con un Xtal normal, una vez afinado, puede que tengas una lectura de 50.000.200 Hz, pero esa lectura será estable.
Aumentará en unos 50Hz por cada grado de temperatura, de manera que un simple soplo la modificará. Pero dentro de una caja no tendrás ese problema.
Incluso puedes compensar tú mismo la temperatura con un sensor y el micro y dentro de un rango pequeño de temperaturas (20-30º) no te costará llegar a tener los 2ppm de ese oscilador.


Si quieres mucha precisión (0.01ppm o menos) te recomiendo esto:

https://www.ebay.es/itm/10MHz-FOQ-Piezo-Technik-PTOC32227-High-Precision-OCXO-Square-wave-5V-VFC/271617146639?hash=item3f3da4bf0f:g:bfsAAMXQDK1Rvqrs
https://www.ebay.es/itm/Ublox-NEO-6M-GPS-Modulo-Aircraft-Flight-Controller-For-Arduino-MWC-IMU-APM2-New/112478472619?hash=item1a303d49ab:g:wqEAAOSwbQZbf8rO

O esto:

https://www.ebay.es/itm/GPS-DISCiPLINED-CLOCK-GPSDO-10MHz-10M-OUTPUT-SQUARE-WAVE-RS232-OUTPUT-GPS-NMEA/281649576001?hash=item41939f7841:g:RScAAOSwBLlVHCwv


Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 20 de Septiembre de 2018, 14:35:16
Para empezar lo mejor es probar con un simple cristal que sea bastante estable y luego seguir mejorando.
Pero el GPS deberías comprarlo si o si. Este que te dejo o uno semejante:

https://www.ebay.es/itm/Ublox-NEO-6M-GPS-Modulo-Aircraft-Flight-Controller-For-Arduino-MWC-IMU-APM2-New/112478472619?hash=item1a303d49ab:g:wqEAAOSwbQZbf8rO

A mí, el de antena separada me han funcionado mejor. La antena era más sensible que cuando está montada sobre el PCB.

Saludos.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 20 de Septiembre de 2018, 14:40:47
Que tal uno de estos con un divisor de frecuencia?

https://www.tme.eu/es/details/i547-2p3-40.0000m/generadores-de-cuarzo-smd/ilsi/i547-2p3-400000-mhz/

Tengo entendido que si divido entre 2 la frecuencia, mejora en igual cantidad la precisión y la estabilidad.


Me corrijo. Este Tcxo tiene compensación analógica. Con ese tipo de compensación el jitter debería ser pequeño, pero no dice nada en la hoja de características.
Si realmente tiene 2ppm en todo el rango de temperaturas, a 25ºC puede que tenga 0.2ppm que es lo que buscas. Por probar no pasa nada.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 20 de Septiembre de 2018, 14:46:52
Para esta aplicación yo no me fiaría mucho del Proteus. Para empezar no está mal, pero los errores los verás de verdad en el pic de verdad.


Luego hay trucos de programa para conseguir buena precisión:

* Mide el tiempo que pasa (ciclos de reloj) entre varios pulsos de señal. Eso se llama Reciprocal counting y te dará mucha precisión para bajas frecuencias.

* Mide tiempo y pulsos de forma continua (sin resetear a cero entre mediciones) y luego resta una medición de la anterior. Así no tendrás errores sistemáticos y compensas los errores entre mediciones. Eso se llama Continuous Counting.


Saludos.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 20 de Septiembre de 2018, 14:53:28
Un par de documentos que ayudan:

https://www.radiokot.ru/konkursCatDay2014/30/02.pdf

http://leapsecond.com/hpan/an200.pdf

Título: Re:Interrupción en asm dentro de XC8
Publicado por: micro_pepe en 22 de Septiembre de 2018, 16:10:17
Para esta aplicación yo no me fiaría mucho del Proteus. Para empezar no está mal, pero los errores los verás de verdad en el pic de verdad.


Luego hay trucos de programa para conseguir buena precisión:

* Mide el tiempo que pasa (ciclos de reloj) entre varios pulsos de señal. Eso se llama Reciprocal counting y te dará mucha precisión para bajas frecuencias.

* Mide tiempo y pulsos de forma continua (sin resetear a cero entre mediciones) y luego resta una medición de la anterior. Así no tendrás errores sistemáticos y compensas los errores entre mediciones. Eso se llama Continuous Counting.

Saludos.

Según esto, no debo usar el mismo método para frecuencias bajas que para altas.

El GPS, ¿que tengo que hacer con el? usarlo como referencia de frecuencia, para hacer pruebas de medición. Que tiene, una salida senoidal o cuadrada por algún sitio?

Me pondré a recopilar materiales para empezar a funcionar.

Gracias, un aludo!!!
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 22 de Septiembre de 2018, 19:14:51
Siempre es el mismo método. Pero en frecuencias bajas da la misma precisión que en altas. Lee datasheet.

El gps da 1 pulso por segundo con mucha precisión. Te sirve para calibrar el cristal de cuarzo. Luego lo compensas multiplicando la frecuencia por una constante.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 23 de Septiembre de 2018, 07:47:08
Te explico un poco.

Los frecuencímetros más básicos cuentan los pulsos que llegan en 1 segundo.
Si la señal tiene 10.5 Hz, a veces contará 10 pulsos y a veces 11, con un error del 10%

Los frecuencímetros con método recíproco cuentan el tiempo entre dos pulsos de entrada distanciados más o menos 1 segundo.
En este caso, con un reloj interno de 20Mz, el frecuencímetro esperará un segundo y luego esperará hasta que llegue el siguiente pulso (unos 50ms después). En total contará 209523810 ciclos de reloj y 11 pulsos de entrada. Ahora ese tiempo hay que convertirlo en frecuencia:
   11 pulsos * 20000000 / 209523810 ciclos = 10,500001 Hz

Con un error de 0.1 ppm (7 dígitos correctos)
 
Hay técnicas para aumentar más la precisión, pero necesitarás cambiar a números en coma flotante de doble precisión (microcontrolador de 16 o 32 bit) y base de tiempo con precisión de 9 dígitos (OCXO). El problema del OCXO es que consume unos 300mA y necesita una referencia de tensión precisa para ajustarle, pero los 9 dígitos correctos que te da equivalen a un error de 3 segundos por siglo.

Un saludo.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: micro_pepe en 23 de Septiembre de 2018, 18:46:19
Entonces en la práctica, cual es la idea, usar un timer para contar pulsos de la señal a medir, y otro para contar ciclos de reloj del PIC, los pongo a cero, y detecto cuando se desbordan para incrementar una variable asociada a cada timer, cuando ha pasado un poco más de 1 segundo, tomo nota de los dos contadores y calculo la frecuencia.

Saludos!!!
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 23 de Septiembre de 2018, 19:28:42
Si, pero tienes que esperar al flanco del pulso de entrada para leer los contadores.
Título: Re:Interrupción en asm dentro de XC8
Publicado por: micro_pepe en 26 de Septiembre de 2018, 08:56:50
Si, pero tienes que esperar al flanco del pulso de entrada para leer los contadores.

Entonces ¿ tengo que hacer uso de la interrupción externa ?

Saludos!!!
Título: Re:Interrupción en asm dentro de XC8
Publicado por: Picuino en 26 de Septiembre de 2018, 12:02:53
Hay varios modos. Interrupción externa, módulo capture input, pooling, etc.

El método de interrupción puede funcionar. Recuerda medir siempre primero los pulsos de entrada y a continuación los ciclos de reloj.
Como no se hará a la vez habrá un desfase de pocos ciclos entre lecturas. Por eso es importante que el desfase sea en los ciclos de reloj que siempre tienen la misma frecuencia.

Otra cosa importante es que midas tiempo continuo y luego restes la medición anterior. Eso elimina los errores sistemáticos como el retraso de la interrupción.

Lo ideal sería un módulo que capture impulsos y otro que capture ciclos de reloj, pero creo que dan problemas prácticos con la sincronización.

Una solución buena, que complica más el circuito, es hacer un divisor de frecuencia externo. Con el método recíproco no importa que la frecuencia de entrada sea baja, porque no pierde precisión. Pero a frecuencias altas el microcontrolador tiene problemas sincronizando con la señal.

Saludos.