Translate

viernes, 13 de julio de 2012

Conversor ADC


En otro tutorial vimos como el módulo PWM funcionaba como una especie de conversor digital -> analógico (DAC). El conversor analógico-digital (ADC) que equipa a muchos microcontroladores hace justo lo contrario, convirtiendo un voltaje analógico externo en un número, con el que podremos operar.

Como siempre empezaremos con una introducción sobre los fundamentos de un conversor AD y los registros usados para su manejo en los PIC. Tras entender el proceso, presentaremos las rutinas de C18 para el manejo del ADC y escribiremos nuestras propias funciones, que nos permitirán optimizar el rendimiento del ADC y no depender de un compilador en particular.

En la siguiente entrada veremos como al igual que pasaba con el puerto serie, usando interrupciones podemos optimizar el rendimiento del PIC mientras estamos usando el conversor AD.

Codigo asociado a esta entrada:  adc1.c

------------------------------------------------------------------------------------------

Conceptos básicos de un ADC:

  • Un ADC convierte mide el voltaje V en un pin (que tendrá que estar declarado como entrada con el correspondiente registro TRISA) y lo convierte en un número. El voltaje se mide en referencia a un voltaje mínimo, Vref(-) , y a un voltaje máximo, Vref (+):

                        V_norm = ( V – Vref(-) ) / (Vref(+) –Vref(-) )

  • La fórmula anterior corresponde a un voltaje normalizado. Si el voltaje V alcanza el máximo (Vref+) tendremos una salida de 1 y si se queda en el mínimo (Vref-) una salida de 0.
  • Normalmente Vref- suele ser Vss=GND=0V y Vref+ = Vcc = 5V, pero pueden usarse otros voltajes de referencia. Si por ejemplo queremos medir una señal que sabemos que oscila entre 2 y 3 voltios usaríamos Vref-=2 y Vref+=3. Así aprovecharíamos mejor el rango dinámico del conversor.

  • Como el microcontrolador no va a manejar números en coma flotante, el voltaje normalizado se expresa con un entero, convirtiendo el intervalo real [0,1] en el intervalo de niveles enteros entre [0 y Nmax-1]. La resolución del ADC es una característica fundamental y nos dice el número de niveles con los que cubrimos el intervalo [0,1]. Por ejemplo, en los PIC solemos tener una resolución de 10 bits, que representan 2^10=1024 niveles. El intervalo real [0,1) se aplicaría al intervalo [0,1023]. Si asumimos un rango de 5V, tendremos que la resolución de cada nivel es de r=5/1024 V=4.88 mV. Según la documentación de Microchip (esto puede variar para otros microcontroladores) cualquier voltaje entre [0 y r] (o por debajo de 0, lo que corresponde a  V<Vref-) se cuantificaría en el nivel 0. Entre r y 2r tendríamos una salida de nivel 1. Así hasta llegar a nivel 1023 que cuantificaría voltajes por encima de 1023r = 1023x 5/1024 = 4.995V. Como se ve, voltajes por debajo de Vref- o por encima de Vref+ son posibles y se cuantifican como nivel mínimo 0 o máximo, 1023.  Niveles por debajo de 0V o por encima de la tensión de alimentación (normalmente 5V) pueden ser dañar el PIC.

Nivel
Voltaje
0
<r
1
[r,2r]
2
[2r,3r]
1023
>1023r

  • Aunque un PIC puede tener del orden de 8-12 posibles canales (pines) de entrada analógica, solo tiene normalmente un único módulo ADC, lo que significa que no podemos tomar medidas simultáneas de varios canales. Si es necesario, lo que podemos hacer es ir conectando (seleccionando) los sucesivos canales al ADC para ir midiendo sus voltajes.
  • El proceso de una conversión ADC se divide en un tiempo de adquisición Ta (durante el cual un condensador interno se carga al voltaje exterior) y un tiempo de conversión Tc (durante el cual se desconecta el pin exterior y se cuantifica el voltaje del condensador).
  • El tiempo de adquisición Ta depende de las características eléctricas del PIC (en particular de la capacidad del condensador). Si no se respeta este tiempo, el condensador no habrá alcanzado el nivel del voltaje exterior y la medida será incorrecta. Los datasheet de los PIC indican los Ta recomendados para diversas familias.
  • Otro aspecto importante de la adquisición es recordar que Microchip recomienda una impedancia máxima para el sensor (o lo que sea) suministrador de voltaje que está conectado a nuestro pin. En la mayoría de los casos se recomienda que dicha impedancia no supere los 2.5 Kohmios. Según entiendo con mis escasos conocimientos de electrónica, impedancias mucho mayores harían que (debido a corrientes de pérdida siempre presentes) el condensador no llegara nunca a cargarse al voltaje de entrada o tardase mucho en hacerlo, lo que daría lugar a que la medida posterior fuese incorrecta. Si la impedancia de nuestra fuente es muy superior a la recomendada deberíamos plantearnos insertar un driver.
  • El tiempo de conversión Tc depende fundamentalmente del número de bits del conversor. La unidad básica es el llamado Tad, aproximadamente el tiempo necesario para ganar un bit adicional. La conversión total tarda entre 11 y 14 Tad (contando con la descarga final del condensador para estar listo para otra medida. El reloj del ADC se debe ajustar (como una fracción del oscilador principal) para que dicho Tad no sea inferior a un valor mínimo especificado en los datasheet. Por ejemplo para la familia PIC18F252/452 el Tad mínimo es de 1.6 usec y Tc = 14 Tad. En cambio para la familia PIC18F2520/4520 tenemos un Tad mínimo de 0.75 usec y un Tc = 11 Tad.

Un comentario final: aunque es muy conveniente tener un ADC integrado dentro del microcontrolador, si lo pensamos en términos de nivel de ruido, etc. las cercanías de un microcontrolador con la líneas de reloj, rápidos cambios en las líneas digitales, comunicaciones, etc. no es el mejor sitio para ubicar un ADC. Esto quiere decir que si estamos muy interesados en la precisión, tal vez sería conveniente considerar un ADC aparte, que nos comunicaría los datos adquiridos a través de SPI o similares. Una vez dicha la advertencia nos centraremos en como usar de la forma más eficiente el ADC de un microcontrolador (en este caso un PIC).



Los registros de control del ADC en un PIC (familia 18F 2520/4520)

Para estos ejemplos voy a usar código para la familia PIC18F2520/4520 con algunos comentarios sobre la familia 252/452. El conversor AD es una de los módulos de un PIC donde hay más diferencias entre modelos: distintos número de canales AD, diferentes formas de programar que canales son digitales o analógicos, la posibilidad o no de programar tiempos de adquisición, etc.

Esto hace que la configuración del ADC sea bastante dependiente del modelo y siempre sea bueno tener a mano la documentación ante comportamientos inesperados. Por ejemplo, los registros asociados al puerto serie son los mismos entre una amplia gama de dispositivos. Por el contrario, es fácil que el número de registros de configuración cambie entre modelos.

La familia PIC18F2520 tiene 3 registros de control asociados al ADC (ADCON0, ADCON1 y ADCON2). Por el contrario, la familia 252/452, al tener menos funcionalidades, sólo necesita 2 (ADCON0 y ADCON1). De todas formas, los nombres y funciones de los bits comunes serán los mismos que los aquí descritos, aunque pueden estar situados en diferentes registros.

Además de los registros de control tenemos otros dos registros ADRESH y ADRESL (AD result High/Low) donde se guarda el resultado de la conversión, pero estos si son comunes entre dispositivos.


Veamos un resumen de estos registros (de nuevo, los datasheet de Microchip son los mejores manuales de usuario):

Registro ADCON0: permite seleccionar (CHS) el canal del que tomaremos la medida. También tiene el bit que habilita el conversor (ADON) y que arranca (GO) el proceso de conversión.

Bit #
Bit 7
bit 6
bit 5
bit 4
bit 3
bit 2
bit 1
bit 0
Nombre
X
X
CHS3
CHS2
CHS1
CHS0
GO
ADON
Función
No usado
 No
 usado
Selección de canal: 
desde 0 (0000) a 12 (1100)
Lanza ADC
ON/OFF

ADON: Encendido (1) o apagado (0) del modulo ADC.

GO  : Se pone a 1 para iniciar el proceso de conversión. Cuando la conversión ha terminado el módulo lo pone a 0. Así es como sabemos que podemos recoger el resultado (en ADRESH/ADRESL)

CHS: selecciona cual de los posibles 13 canales analógicos se conecta al ADC para medir.



Registro ADCON1: dedicado a seleccionar cuales de los posibles canales se van a usar como entradas analógicas y a programar el uso o no de voltajes de referencia externos (distintos de los valores 0 y 5V por defecto)

Bit #
bit 7
bit 6
bit 5
bit 4
bit 3
bit 2
bit 1
bit 0
Nombre
X
x
VCFG1
VCFG0
PCFG3
PCFG2
PCFG0
PCFG0
Función
No usado
No
usado
Uso (1) de 
Vref (+),Vref(-)
Reparto canales 
digitales / analógicos

VCFG1: por defecto (0) usamos Vss=Gnd=0V como Vref-. Si es 1 se tomara como Vref-  el voltaje presente en AN2.

VCFG0: Lo mismo que el anterior pero para Vref+. Por defecto usaremos Vdd (alimentación, típicamente 5 o 3.3V) como Vref+. Si es 1 se usa el voltaje presente en AN3 como Vref+.

PCFG:  Posiblemente no necesitaremos todos los posibles canales analógicos. Estos bits permiten decidir cuales de los pines se dedican a canales analógicos y cuales permanecen como canales digitales. Los valores posibles van desde 0000 (todos analógicos) a 1111 (todos digitales).

Los canales analógicos se denotan en la documentación como AN0, AN1, AN2, etc. Los dispositivos con 8 canales (252/452) los reparten entre el puerto A y el E. Los que tienen 13 canales usan también parte del puerto B (2520/4520). Mirar la documentación, porque el orden no es consecutivo. Por ejemplo, para el 4520

Canal
AN0
AN1
AN2
AN3
AN4
AN5
AN6
AN7
AN8
AN9
AN10
AN11
AN12
Pin
RA0
RA1
RA2
RA3
RA5
RE0
RE1
RE2
RB2
RB3
RB1
RB4
RB0


Registro ADCON2: información para determinar los tiempos Ta y Tc del conversor y la forma en la que el resultado (10 bits) se guarda en ADRESH:ADRESL (16 bits).

Bit #
bit 7
bit 6
bit 5
bit 4
bit 3
bit 2
bit 1
bit 0
Nombre
ADFM
x
ACQT2
ACQT2
ACQT2
ADCS2
ADCS1
ADCS0
Función
Formato
No usado
Programación T adquisición
Reloj del ADC

ADFM: Formateo del resultado. El conversor da 10 bits que se guardan en dos registros (ADRESH:ADRESL) de 8 bits, por lo que 6 de los 16 bits estarán vacíos. Si ADFM=1 el resultado está desplazado a la derecha, por lo que los 6 bits más significativos de ADRESH estarán vacíos. Si es 0 se justifica a la izquierda y son los 6 bits menos significativos de ADRESL los que están vacíos.  El caso ADFM=1 se suele usar cuando nos interesan los 10 bits. El resultado se puede pasar a un entero de 16 bits como: 
                                                                       res = (ADRESH<<8)+ADRESL;

El caso ADFM=0 se suele usar si sólo queremos los 8 bits más significativos. En ese caso basta hacer: res = ADRESH;

ACQT: bits para la programación del T de adquisición. Recordar que el tiempo de adquisición es el que debemos esperar después de seleccionar (conectar) un canal al ADC mientras se carga el condensador cuyo voltaje posteriormente mediremos. Si escogemos 000 el usuario es responsable de la espera (de unos pocos usec, especificada en la documentación) entre la selección del canal (poner los bits CHS adecuados en ADCON0) y el inicio del proceso de conversión (poner a 1 el bit GO de ADCON0).

El modo manual (000) era la norma entre familias anteriores, que de hecho no contaban con estos bits de configuración. En la familia 2520/4520 es posible programar dicho tiempo de espera. De esta forma tras seleccionar el canal podemos inmediatamente lanzar la conversión (ADCON0.GO=1) y el módulo esperara el tiempo programado antes de iniciar la conversión. Esto permite optimizar el aprovechamiento del ADC como veremos.

El tiempo de adquisición es la suma de varios factores, siendo los principales la capacidad del condensador a cargar y el tiempo que tarda el amplificador del ADC en estabilizarse. Es importante consultar el datasheet si queremos optimizar el muestreo porque podemos encontrarnos bastantes diferencias entre diversos modelos.

ADCS: seleccionan la velocidad del reloj del ADC como una fracción (div = 2, 4, 8, 16, 32, 64) del reloj principal (aunque también es posible asociarlo a un oscilador RC independiente). El inverso de la frecuencia del ADC determina el llamado Tad, que viene a ser el tiempo dedicado a obtener cada bit del resultado:

         F_ad = Fosc / div        
         Tad = 1/F_ad =  div / Fosc  (en microsec si Fosc está en MHz)

Obviamente deberíamos escoger un divisor bajo para obtener la frecuencia más alta (Tad más pequeño) posible para tardar lo menos posible en cada conversión. Sin embargo hay una limitación: el Tad no puede ser menor que un cierto tiempo mínimo dependiente del modelo. Por ejemplo para la familia 252/452 se recomienda que Tad sea como mínimo 1.6 usec. En cambio para la 2520/4520 podemos bajar a 0.75 usec.

Eso significa que si tenemos un cristal de 20 Mhz, el divisor escogido sería:

1:32  si tenemos un 452, ya que Tad = div / Fosc = 32/20 Mhz = 1.6 usec = recomendado

1:16 si tenemos un 4520 ya que Tad = div / Fosc = 16/20 MHz = 0.8 usec > 0.75 usec recomendados


Nuestro primer programa con el ADC

El proceso a seguir para una conversión (según se describe en la documentación de Microchip) es el siguiente:
  1. Configurar el ADC con la asignación de canales (PCFG), programar el reloj del ADC (bits ADCS), seleccionar o no voltajes de referencia (VCFG), etc.
  2. Una vez configurado, habilitar el ADC (ADON=1)
  3. Escoger canal (bits CHS) a usar (el pin dado se conecta al condensador)
  4. Esperar (delay) Ta mientras se carga el condensador (este paso puede ser evitado programamos la espera)
  5. Lanzar la conversión (GO=1)
  6. Esperar a completar a que la conversión concluya (GO=0).
  7. Extraer el resultado de ADRESH:ADRESL
  8. Si hemos terminado con el ADC, apagarlo para reducir consumo.
Ahora que conocemos los detalles escribiremos el primer programa para un PIC18F4520 usando las rutinas de C18 y no tendremos dificultades en imaginar que está haciendo cada rutina por debajo.

Las rutinas básicas para operar en C18 con el ADC pueden verse en este código ejemplo del manual de C18:

  OpenADC(ADC_FOSC_16&ADC_RIGHT_JUST, ADC_INT_OFF&ADC_VREFPLUS_VDD&ADC_VREFMINUS_VSS,7); // (1)-(2)
  SetChanADC(ADC_CH0);     // Paso 3)                     
  Delay10TCYx(5);          // Paso 4) -> delay de adquisición
  ConvertADC();            // Paso 5)
  while( BusyADC() );      // Paso 6) -> delay de conversion.
  res = ReadADC();         // Paso 7)
  closeADC();              // Paso 8)

Vemos que C18 tiene casi una función para cada paso del proceso. Por ejemplo, el compilador MikroC Pro es mucho más monolítico, lo que lo hace más simple pero menos adaptable. En MikroC Pro, todo lo anterior se resume en una sola llamada:

 res = ADCRead(0);   que configura, selecciona canal 0, espera, lanza conversión y cuando termina devuelve res.

Los parámetros que recibe OpenADC son esencialmente los valores de ADCON0, ADCON1 y ADCON3. Como siempre la ventaja es que damos valores a dichos registros combinando diversas banderas más fáciles de recordar. Para aquellos dispositivos con sólo disponen de ADCON0 y ADCON1 la función sólo usa dos parámetros en vez de tres. Con SetChanADC seleccionamos (ADC_CH0) AN0=RA0 como el pin cuyo voltaje vamos a medir.

Normalmente la configuración del ADC se hace una sola vez y luego se hacen sucesivas conversiones (posiblemente de diferentes canales). Podemos agrupar el código anterior en una función que reciba como argumento el canal a muestrear y haga todas las etapas (aunque como veremos más adelante, en ciertas circunstancias es más eficiente "romper" la función para no tener una función bloqueante):

uint16 ADC_read(uint8 ADC_channel)
 {
  uint16 ad_res;
      
  SetChanADC(ADC_channel);
  Delay10TCYx(5);
  ConvertADC();
  while(BusyADC());
  ad_res = ReadADC();
  return ad_res;
}

Una llamada al código anterior mide el voltaje del canal deseado una sola vez. Si el voltaje en el canal analógico está cambiando rápidamente, querremos muestrearlo muchas veces por segundo para seguir sus cambios. Supongamos que queremos tomar 2000 muestras por segundo. A esto es a lo que se suele denominar una frecuencia de muestreo de 2000 Hz. Con este ritmo, deberemos lanzar tomar una muestra cada 1/2000 seg = 0.2 msec = 200 usec/muestra.

El código quedaría:

 TRISB=0; TRISC=0; TRISAbits.TRISA0=1;
 while(1)
     {
      PORTCbits.RC0=1; res=ADC_read(ADC_CH0); PORTCbits.RC0=0;
      PORTB=res>>2;
      Delay10TCYx(250);
     }
  

Declaramos PORTB y PORTC como salidas y RA0 como entrada. Dentro del bucle, tras el código de la conversión, simplemente esperamos 500 usec (2500 ciclos @ 20 MHz) antes de una nueva conversión. Hemos dejado fuera la configuración del ADC (misma línea de antes) y el apagado del módulo (porque lo estamos usando continuamente).
Para ver si está funcionando hemos conectado un potenciómetro en RA0 y una tira de LEDS en PORTB, donde mostramos los 8 bits más significativos del resultado.  Moviendo el potenciómetro veremos cambiar los LEDs.

La orden de poner RC0 a 1 al arrancar la conversión y de bajarlo al terminar es para controlar el tiempo que tardamos. Con un osciloscopio podríamos ver claramente el tiempo dedicado a la conversión como la parte en la que este alta la señal del pin RC0. Como ya hemos hecho en otras ocasiones, incluso con un simple voltímetro podemos estimar dicho tiempo de forma bastante aproximada. En particular para este programa he medido un voltaje en RC0 de 0.56V. El voltaje que el mismo voltímetro me da para Vcc es de 4.86V. El voltaje medido en RC0 dividido por 4.86 representa el porcentaje en el que RC0 está en alto del total del periodo. Por lo tanto podemos escribir que si t es el tiempo dedicado a la conversión entonces:

   t / (t + 500)   = fracción de tiempo en alto  = 0.56/4.5  = 0.11  (11%)

Despejando obtenemos un valor aproximado para t de unos 60 usec.

Obviamente esto funcionará cuando el periodo sea lo suficientemente rápido para que el voltímetro responda con el valor medio del voltaje a lo largo del periodo.

        

La captura de la izquierda muestra varios pulsos de conversión. Vemos que el espaciado entre pulsos no son los 500 usec sino unos 560. La razón es que además de los 500 usec programados en el delay, precisamos otros 60 usec para completar la conversión AD (lo que concuerda con la estimación del voltímetro). Vemos que el espaciado entre terminar una conversión y empezar otra si son los 500 usec exactos que hemos programado.

A la derecha, en un zoom del pulso de captura vemos con mayor precisión el tiempo dedicado a la conversión, unos 55 usec.

Esta duración del proceso de conversión (55-60 usec) nos impone un límite máximo de unos 15-18000 muestras por segundo a nuestros proyectos (además, si nos acercamos a dicho límite el micro no podrá hacer nada más, al estar ocupado en un 100% en tomar muestras).

Si en el programa anterior cambiamos el delay entre muestras a  Delay10TCYx(1); (equivalente a 2 usec) veremos que el voltaje del pin RC0 sube a 4.42V, lo que corresponde a una ocupación del 92% (4.42/4.86). En la figura adjunta se aprecia gráficamente dicha dedicación casi exclusiva al proceso de conversión. El espaciado entre muestras es de 59 usec (55 + delay) lo que corresponde a unas 17000 muestras por segundo (16950 en la medida del osciloscopio)


Aunque 15000 muestras por segundo pueden ser más que adecuadas, vamos a ver que es posible mejorar dichos resultados, aprovechando lo que hemos visto de la programación del ADC en base a registros de control y el estudio de las especificaciones detalladas del micro que estamos usando.


Modificaciones del código:

En primer lugar escribiremos una función equivalente a la anterior (ADC_read2) pero evitando usar las llamadas a las funciones de C18. De esta forma nos damos cuenta de que implementar dichas funciones es muy sencillo y nos evitamos llamadas a funciones (lo que esperamos que mejore el tiempo necesario):

#define select_ADC(ch) { ADCON0 &= 0b11000011;  ADCON0 |= (ch<<2); }
uint16 ADC_read2(uint8 ch)
 {
  uint16 ad_res;      
  select_ADC(ch);                                //SetChanADC(ADC_channel);
  Delay10TCYx(5);
  ADCON0bits.GO=1;                               //ConvertADC();
  while(ADCON0bits.GO);                          //while(BusyADC());  
  ad_res =ADRESH; ad_res<<=8; ad_res+=ADRESL;    //ad_res = ReadADC(); 
  return ad_res;
}

Si repetimos el bucle anterior con esta función vemos que el tiempo baja a unos 45 usec, una ganancia del 15%.
Podemos mejorar un poco más si nos ajustamos a las especificaciones del PIC usado (18F2520/4520). La documentación indica que para esta familia basta un tiempo de adquisición (entre seleccionar canal y lanzar conversión) de unos 3 usec, lo que a 20 MHz equivale a unos 15 ciclos . Claramente los 50 ciclos (10 usec) de antes son excesivos. Nos bastaría con especificar un retrado de p.e. 20 ciclos:

uint16 ADC_read2b(uint8 ch)
 {
  uint16 ad_res;
      
  select_ADC(ch);                                //SetChanADC(ADC_channel);
  Delay10TCYx(2);
  ADCON0bits.GO=1;                               //ConvertADC();
  while(ADCON0bits.GO);                          //while(BusyADC()); 
  ad_res =ADRESH; ad_res<<=8; ad_res+=ADRESL;    //ad_res = ReadADC(); 
  return ad_res;
}
 
Con esto bajamos a unos 40 usec, otro 10% adicional. Notad que dependiendo del PIC usado este código tendría que ser modificado.

Finalmente podemos usar una característica adicional de la familia 18F2520/4520. El tiempo de adquisición puede ser preprogramado, lo que hace que podamos lanzar la conversión nada más seleccionar el canal. Tras poner a 1 el bit GO, el módulo ADC no lanza la conversión inmediatamente sino que espera el tiempo programado. El tiempo se especifica en unidades de Tad y hay que programarlo en la configuración (OpenADC) del módulo:

   OpenADC(ADC_FOSC_16 & ADC_RIGHT_JUST & ADC_4_TAD,
           ADC_INT_OFF & ADC_VREFPLUS_VDD & ADC_VREFMINUS_VSS, 7);

En este caso preprogramamos un delay de 4 x Tad. Como Tad = 16/20 = 0.8 usec eso equivale a 3.2 usec, que es superior al tiempo de adquisición mínimo recomendado para estos PIC. La función de conversión queda ahora:

uint16 ADC_read2b(uint8 ch)
 {
  uint16 ad_res;
      
  select_ADC(ch);                                //SetChanADC(ADC_channel);
  ADCON0bits.GO=1;                               // Launch conversion without delay
  while(ADCON0bits.GO);                          //while(BusyADC()); 
  ad_res =ADRESH; ad_res<<=8; ad_res+=ADRESL;    //ad_res = ReadADC(); 
  return ad_res;
}

Como vemos no tenemos que preocuparnos del delay, ya que el módulo lo respetará. Con este nuevo código la duración de la llamada a la función es de unos 24 usec. Las ganancias se pueden detectar con la bajada del voltaje del pin RC0 o más gráficamente, monitorizando RC0 con el osciloscopio. En la figura se adjuntan las capturas de la duración de la función para el original y las tres modificaciones propuestas (de arriba abajo y de izquierda a derecha). Vemos que hemos conseguido reducir a la mitad el tiempo, pudiendo llegar hasta unas 40000 muestras/segundo (24 usec por conversion).


    

En otra entrada veremos como combinar el uso del ADC con interrupciones. En primer lugar veremos como usar una interrupción de un temporizador para lanzar la conversión AD a intervalos exactos. En segundo lugar veremos como usar la interrupción del propio módulo ADC para evitar que la función anterior sea bloqueante. El uso de la interrupción AD nos permite no tener que esperar (línea while(ADCON0bits.GO)) hasta que el módulo termine: la interrupción nos avisará cuando el resultado este listo en ADRESH:ADRESL.

Antes de explorar esta combinación de ADC + INTS, vamos a ver un pequeño proyecto (brújula electrónica ) en el que  usaremos lo que ya sabemos del ADC. Consiste en leer el voltaje de dos sensores magnéticos (en dos ejes perpendiculares) y combinar su información para obtener una desviación en grados respecto al norte magnético.






17 comentarios:

  1. Si, excelente explicacion.

    ResponderEliminar
  2. excelentes todos los tutoriales! super utiles y amenos para los que, al igual que yo, se inician en el uso del pic8f...mil gracias!

    ResponderEliminar
  3. Excelente tutorial muy masticable pero tengo una pregunta cuando yo caracterizo y linealizo un sensor resistivo el me genera una ecuacion como hago para introducir esa ecuacion en el micro (teniendo en cuenta que es un pi18fxxx)

    ResponderEliminar
  4. Más que excelente!!! Me sirve para todas las prácticas y me hace su realización 10.000 veces más fácil!!!
    Gracias, gracias, gracias! :)

    ResponderEliminar
  5. Te hago una consulta, si hago la conversión nuevamente a tensión en un programa C, qué fórmula debería usar ADC*5/1024 ó ADC*5/1023. Siempre he tenido esa duda. Por lo que vos explicás acá, nunca se llegaría a los 5V, que serían cuantificados en 1023, entonces 1023*5/1024=4.995. Me podrías dejar clara esta duda por favor. Mil gracias

    ResponderEliminar
  6. Creo que esto resuelve mi duda: http://ww1.microchip.com/downloads/en/AppNotes/Achieving%20Higher%20ADC%20Resolution%20Using%20Oversampling%2001152A.pdf
    la fórmula correcta es ADC*5/1023. Efectivamente sí convierte los 5V en 1023, y los 4.995 en 1022.

    ResponderEliminar
  7. Buenos días, si yo quisiera sensar 2 señales a la vez a 50KHz, seria posible? a mi parecer no por que como hay un único ADC, debo asignar a 2 canales diferentes, y para ello debo esperar un tiempo (tiempo de adquisición) el cual es del orden de microsegundos, alguien que me aclare si es posible o no. gracias

    ResponderEliminar
  8. seleccionar un tiempo de adquisición bajo

    ResponderEliminar
  9. [Hola,excelente trabajo nunca habia visto un blog con estos temas bien explicados,espero que puedas continuar con demas temas sobre pics, espero ver algo sobre I2C y algo sobre Tivas de TI etc... ]

    Quisera saber como configurar un acelerometro o gyroscopio, he leido que toca a frecuencias bajas para su configuracion .como es esto? ,pero mi integrado(IMU 6DOF digital) no da señales de vida,no se si sera la comunicacion I2C, y no se como empezar a probar
    podrias decirme algo asi como un numeros de pasos(1.. 2... 3.. 4..) para empezar a trabajar este IMU con un pic en general

    ResponderEliminar
  10. ¿El tiempo de conversión Tc depende fundamentalmente del número de bits del conversor? Esto no es del todo correcto, aunque influye en ello, el tiempo depende fundamentalmente de la frecuencia de muestreo a la que puede operar un adc

    ResponderEliminar
  11. Referente a tu comentario final:
    esta demostrado que si tu usas un chip alejado de otro chip el ruido es mayor debido a las grandes capacidades que se generan, de echo los mejores adc tienen todas sus funciones extras integradas en el mismo chip para minimizar capacidades

    ResponderEliminar
  12. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  13. Este comentario ha sido eliminado por un administrador del blog.

    ResponderEliminar
  14. Este comentario ha sido eliminado por un administrador del blog.

    ResponderEliminar