Autor Tema: Muestreo con adc?  (Leído 9971 veces)

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

Desconectado RALF2

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2062
Muestreo con adc?
« en: 16 de Marzo de 2008, 21:01:55 »
Que tal amigos!
Necesito realizar una rutina para muestrear una señal DC utilizando el adc del pic16f877 a 20Mhz el problema es que ese muestreo debe ser hecho en tiempos lo mas exactos posibles.  :(

Que recurso del micro me podria servir para esto?

SAludos




Desconectado Menta

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 611
Re: Muestreo con adc?
« Respuesta #1 en: 16 de Marzo de 2008, 22:13:58 »
Hola! pues yo usaría un timer, me parece lo más indicado, su función es contar tiempo o eventos.
En la interrupción de un timer hacé que lea al valor del adc
Cada cuánto necesitas muestrear la señal???
     

Desconectado RALF2

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2062
Re: Muestreo con adc?
« Respuesta #2 en: 16 de Marzo de 2008, 22:23:33 »
Que tal menta!
Bueno la idea es tomar una muestra cada cierto tiempo por ejemplo cada 100us pero para ello el pic debe chequear primero un pin del pic y cuando esta pase a bajo "0" la rutina debe tomar digamos 10 muestras cada 100us y almacenarlas en la memoria del pic.
pero no hallo la forma de cargar el timer para que haga eso :?

Desconectado Menta

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 611
Re: Muestreo con adc?
« Respuesta #3 en: 16 de Marzo de 2008, 22:57:20 »
Bueno, yo no uso proton, uso C pero más o menos, lo que haría yo es:

Configurás el timer. En pic c es Setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 ); no sé como es en protón.
El pin ese en cuestión lo pondría en un pin con interrupción, por ejemplo INT_EXT que se puede configurar en el flanco descendente
En la interrupción esta lo que se hace es setear el contador del timer y habilitar la interrución:
{
set_timer1(65536-X);
Enable_interrupts(INT_TIMER1);
}

En tu caso con un cristal de 20 Mhz tienes un clock interno de 5Mhz, con lo cual el tiempo mínimo es de 1/5M = 0.2us
Esto quiere decir que si el tiempo entre muestras lo deseas de 10us se deben contar 10us/0.2us = 50 pulsos de clock interno te quedaría

{
set_adc_channel( 0 );   // poner desde antes el seteo de canal así no interfiere en los tiempos
a=0;                           // iniciar en 0 un contador
set_timer1(65536-50);
Enable_interrupts(INT_TIMER1);
}

###############################

Ahora, qué poner el la interrupción del timer, pues

{
set_timer1(65536-X);    // primero que nada reconfiguro el timer
registro[a]=read_adc();  // tomo la muestra
a=a+1;                         // incremento el contador de número de muestra
if (a==9)                     
Disable_interrupts(INT_TIMER1);     // si se tomaron ya 10 muestras desactivo la interrupción


NOTA: me parece que para un trabajo más fino se debería considerar el tiempo de salto a la interrupción, si es como creo debe ser de un ciclo interno, entonces en lugar de poner X se debe poner (X-1), es decir 49 para el ejemplo de los 10us...

Espero que te sea útil.
« Última modificación: 16 de Marzo de 2008, 23:05:36 por Menta »
     

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: Muestreo con adc?
« Respuesta #4 en: 16 de Marzo de 2008, 23:01:47 »
Hola pana, lo tienes todo aquí http://www.todopic.com.ar/foros/index.php?topic=14917.0

El Basic no es el mismo que utilizas pero la forma de hacerlo tiene que ser muy parecida.

- Comprobacion del pin mediante un simple bucle o usando interrupciones externas si fuera necesario.
- Activar una base de tiempos de 100uSeg (compensada si fuera necesario).
- Hacer la lectura y almacenamiento en un array (memoria Ram que es más rápida).
- Control del numero de lecturas mediante un contador.
- Almacenamiento de los datos en la memoria no volátil del Pic si la tiene o transferencia de los datos al exterior directamente.
- Vuelta al principio.
Saludos desde Granada, España.

Desconectado RALF2

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2062
Re: Muestreo con adc?
« Respuesta #5 en: 17 de Marzo de 2008, 10:12:13 »
Gracias menta por tu comntario, tienes razon en cuanto se pierde algo de tiempo cuando se salta a la rutina de interrupcion el problema es que como el programa esta hecho en basic no se sabe exactamente cuanto dura cada instruccion y eso trae problemas  :shock:

Dogflux buen material referente al timer lo voy analizar con calma, pero me parese que posee el mismo problema con los tiempos, por alli me recomendaron que utilizara una rutina en asm incrustada en el codigo basic, para asi poder controlar los tiempos exactos que dura cada instruccion y asi poder obtener una base de tiempo lo mas exacta posible, aunque resulta deberas problematico.

Lo otro que pienso seria utilizar un clock a 40Mhz de forma tal que los pequeños tiempos que se pierden cuando se pasa de una instruccion a otra en basic no afecten mucho la base de tiempo y de esa manera se pueda utilizar las interrupciones por el tmr0, e.t.c

Nunca pense que necesitaria tiempos tan exactos, a menos que este equivocado en mi apresiacion  :(
 

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: Muestreo con adc?
« Respuesta #6 en: 17 de Marzo de 2008, 14:35:47 »
En general todos los entornos de trabajo suelen llevar herramientas
que permiten calcular los tiempos que tardan las rutinas con mayor
o menor dificultad. De todas formas uno de los ejemplos del enlace
anterior es una rutinita que usa un timer para calcular los tiempos
que tardan en ejecutarse las rutinas Basic.
Saludos desde Granada, España.

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5490
    • Electrónica Didacta
Re: Muestreo con adc?
« Respuesta #7 en: 17 de Marzo de 2008, 15:42:41 »
Ralf, solo un comentario pasajero, además de los calculos realizados, tendras que medir el tiempo que consume las lineas correspondiente al funcionamiento de la pantalla glcd.

es decir, primero escribes las lineas correspondiente al bucle de la conversión,

muestrear:
...
...
...
' aquí va las lineas de otros procesos
...
...
volver a muestrear

ese tiempo añadido a las otras lineas es el tiempo que durará un muestreo real. Uno con los calculos puede hacer aproximaciones, dudo mucho que sea un valor real, sin mencionar el hecho de trabajar en un lenguaje de alto nivel.



La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado RALF2

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2062
Re: Muestreo con adc?
« Respuesta #8 en: 17 de Marzo de 2008, 21:07:27 »
Que tal amigos!
Palitroquez tienes toda la razon por eso es que tengo trancado el serrucho  :mrgreen:
El problema es que las rutinas en basic duran un tiempo que no sabemos cuantos es por lo que seria un poco dificil hacerlo de esta manera, se me ocurre es utilizar una rutina en asembler utilizando el modulo CCP2 en modo de disparo especial, de forma tal que cada cierto tiempo me dispare el adc del pic; ese tiempo el cual puede ser programado por uno seria la base de tiempo del sistema.  :mrgreen:
Lo otro seria elaborar una rutina para que cuando la señal pase por cero (2.5Volt), con pendiente positiva por ejemplo, comiense a almacenar los datos del adc, de no ser asi el adc tomaria muestras a partir de cualquier punto de la señla y eso no es lo que sequiere.

Que les parese?
« Última modificación: 17 de Marzo de 2008, 21:12:55 por RALF2 »

Desconectado Menta

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 611
Re: Muestreo con adc?
« Respuesta #9 en: 18 de Marzo de 2008, 16:00:43 »
Se me ocurre que podrías hacer en basic el programa prescindiendo de la evaluación de ese terardo que te lleva llamar a la subrutina de interrupción. Viste que en los fragmentos de código que te puese en C, usé una variable a que se encargaba de contar hasta 10 las muestras, bueno podrías hacer que esa variable en lugar de contar hasta 10 contara hasta 1.000.000 con una variable de 32 bits poniendo if (a==1000000) en lugar de if (a==9) lo que dure esta comparación estimo que no te afecta, pues está dentro de la subrutina y luego de la reiniciación del set_timer1(65536-X); así que no te afecta siempre y cuando la subrutina termine de ejecutarse antes que se desborde nuevamente el contador.
que logras con eso... bueno puedes hacer 2 cosas:
si debugueas tu programa con proteus puedes ver los tiempos desde que se habilita la interrupción hasta que se deshabilita. Ese tiempo debería ser 10us * 1Mciclos = 10 segundos. Suponete que en el proteus midas que pasaron 10.200000 segundos sabes que el retardo es de 200ms en 1Mmuestras ==> 0.2us que este caso sería el de 1 sólo ciclo de retardo, en caso de que sean más cilos los resultados serían de 10.4, 10.6 ... etc y esos son los ciclos que le deberías restar al 50.
O hacer lo mismo, pero sin el proteus, usando otro timer que se dispare simultáneamente que cuente un tiempo de digamos 0.2 segundos y que al interrumpir se fije en que valor está la variable "a" y la guarde, de ese modo se esperaría que "a" esté próximo a 20000 (ya que 20k * 10us = 0.2seg) si a=19600 aprox es que se demoró 1 ciclo si es 19200 serán 2 y así...
     

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5490
    • Electrónica Didacta
Re: Muestreo con adc?
« Respuesta #10 en: 18 de Marzo de 2008, 17:51:18 »
También puedes setear un pin de un puerto cuando termine la conversión, y luego con el osciloscopio mides el tiempo.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado Menta

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 611
Re: Muestreo con adc?
« Respuesta #11 en: 18 de Marzo de 2008, 18:26:33 »
Hola. Me tomé el trabajo de pasar el código que he propuesto y correrlo y no me funcionaba con un tiempo de  10us así que puse uno de 100us y en lugar de contar hasta 1M contaba hasta 100000 y el resultado fue de 10.86 seg (8.6% de error por demora) pero ese valor equivale a 43ciclos y me parece un poco mucho... voy a probar con el método2...

Con el segundo obtuve el siguiente resultado: en 0,1 seg. se tomaron en promedio 976,33 muestras (pues lo ejecuté varias veces consecutivas 0 => 0.1 => 0.2 => 0.3 ...)
Esto implica que se tardó por muestra 0,1/976,33= 102,42us.
En este caso, que a mi entender es mucho más confiable q el primero, son como 12 ciclos de reloj de retardo...
Adjunto el código.
« Última modificación: 18 de Marzo de 2008, 20:18:28 por Menta »
     

Desconectado RALF2

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2062
Re: Muestreo con adc?
« Respuesta #12 en: 19 de Marzo de 2008, 00:24:53 »
Gracias menta y palitroquez por su interes en mi proyecto, se los agradezco!
Mira menta voy a chequear tu codigo y te comento lo que veo.
A mi se me ocurre otra forma leyendo un programa que vi en proton sobre el CCP.

Como saben el pic16f877 posee un modulo CCP2 (del cual ya hice referencia antes), que puede ser configurado en modo de disparo especial, de forma tal que periodicamente active el ADC del pic para que realice una conversion cada intervalo de tiempo  :mrgreen:  pues ese intervalo seria lo que yo quiero obtener  :-/
Fijense en lo siguiente: supongace que se necesita tomar una muestra cada 0.1ms (100us) de la señal de entrada y almacenar esta en la memoria, todo esto debe realizarse exactamente  dentro de un margen de 100us ni mas ni menos. Vean que eso es lo que quiero, por lo tanto el tiempo que tardo entre adquirir el valor (cargar el condensador del s/h), el tiempo de conversion que es de 25us aproximadamente y el tiempo que tardo en almacenar el dato, y cualquier otro tiempo añadido, todo eso debe hacerse dentro de los criticos 100us, de no ser asi tendria un error en la base de tiempo del osciloscopio como comenta palitroquez :?
Que es lo que quiero hacer con todo esto.
ahora bien como el modulo ccp2 del pic me permite realizar conversiones a intervalos de tiempo   programables por el usuario podria ser una solucion.
menta si tienes practica con el ccp2 prueba, si esta dentro de tus posibilidades, yo lo hare apenas me pueda desocupar en el trabajo y asi podemos comparar resultados  :mrgreen:

Ahora bien si las rutinas en basic son muy largas (cuando se transforman en asembler) entonces todol o referente al ccp2, adc y el almacenaje de os datos abra que hacerlo forzosamente en asembler, no hay otra  :shock:   
« Última modificación: 19 de Marzo de 2008, 00:28:17 por RALF2 »

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5490
    • Electrónica Didacta
Re: Muestreo con adc?
« Respuesta #13 en: 24 de Marzo de 2008, 14:43:44 »
Hola ralf, también me encuentro en una situación similar a la tuya, requiero tomar muestras cada 100uS, y dentro del poco tiempo que me queda, hacer mil cosas mas. La verdad es que creo que no alcanzará hacer todo aquello dentro de 100uS.

Estaba pensando, en concentrarme en los otros procesos, no importa cuando se tarden y de alguna manera ir acumulando los datos que vaya obteniendo del ADC y después que tenga unos cuantos (dependiendo por supuesto del tiempo que lleve en las otras cosas) irlo vaciando.

hace tiempo pregunté ese problema que tenemos :  Ejecutar procesos dentro o fuera de un muestreo

PD: voy a revisar eso de CCP que mencionas


La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado RALF2

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2062
Re: Muestreo con adc?
« Respuesta #14 en: 24 de Marzo de 2008, 14:59:29 »
Que tal palitroquez!
mira la rutina del ccp2 ya esta lista funciona al pelo  :mrgreen:
Lo que hay que hacer es que cada vez que se genere una interrupcion en el ccp2 saltes a la rutina de interrupcion, almacenes el dato en memoria y luego salgas raudo y veloz  :D
o sin utilizar interrupciones puedes esperar a que el ccp2if pase a uno, almacenas el dato en memoria y cuando llegue al numero de muestras que deseas los mandas a la glcd o la pc segun sea el caso, que te parese  :mrgreen:





 

anything