Conversión AD avanzada en Arduino

La mayor parte de los microcontroladores AVR tienen un conversor analógico-digital (analog to digital converter, ADC) de 10 bits. Para manejarlo, Arduino proporciona la función analogRead(), que simplifica el uso del conversor AD, pero a la vez impide el uso de algunas funcionalidades interesantes.

En este artículo echaremos un vistazo más de cerca al conversor AD del microcontrolador. La explicación se refiere siempre a los micros AVR de 8 bits: para todos microcontroladores de la familia AVR los fundamentos son los mismos, aunque puede cambiar la implementación (registros, localización de los bits, codificación de las configuraciones, etc.).

Referencias

La información presentada en esta publicación se basa en las siguientes referencias:

Qué es un conversor AD

Un conversor AD (en inglés, y a partir de aquí en esta publicación, ADC) es un dispositivo electrónico que permite convertir una tensión analógica de variación continua en un valor digital dentro de un rango definido. El valor analógico a menudo representa alguna magnitud del mundo real: la presión, la temperatura o la velocidad (por poner varios ejemplos) se miden y se presentan al microcontrolador de modo analógico, es decir, pueden tomar cualquier valor dentro de su rango de variación. Además, son continuas: en cualquier momento la señal tiene un valor que puede variar respecto al que tenía en un momento anterior.

El flujo continuo de información analógica se suele denominar señal. A diferencia de las señales analógicas, las digitales no son continuas: se leen (se muestrean) a una frecuencia determinada, y por eso sólo se dispone de valores cada cierto tiempo. Esa velocidad de lectura (cuántas muestras se toman por segundo) se denomina frecuencia de muestreo.

En la gráfica superior se representa la señal analógica en gris, que como se ve es continua. La mayor parte de los ejemplos que se encontrarán al usar sensores suelen generar una señal analógica de entre 0 y 5 voltios, pero no tiene por qué ser así.

La línea azul representa los valores digitales obtenidos. La conversión se realiza en los cambios verticales: en esos momentos de tiempo el ADC muestrea la señal analógica, es decir, la lee y la convierte en un valor digital. Como puede verse, el resultado de la conversión no es exacto, porque el conversor tiene un número reducido de bits para representarlo.

Por eso la señal digital no coincide con la analógica: tiene una precisión limitada. Para mejorarla hay que aumentar el número de bits usados en la conversión.

El tiempo que transcurre entre una muestra y la siguiente (Ts) se denomina periodo de muestreo, y es el inverso de la frecuencia de muestreo.

El ADC del micro AVR

Hay distintos tipos de conversores AD. Todos los micros AVR que tienen un conversor AD utilizan un tipo denominado conversor AD de aproximaciones sucesivas. No es el objetivo de esta publicación explicar en qué consiste este método de conversión: sólo indicaremos que el conversor aumenta o disminuye la tensión por pasos cada vez más pequeños hasta que se parece lo suficiente a la tensión de entrada analógica:

El esquema siguiente muestra un diagrama simplificado del conversor AD en un micro AVR.

Como puede verse,

  • El micro tiene un solo conversor AD
  • La entrada al conversor procede de un multiplexor de 8 canales, que permite elegir una de entre varias patillas de entrada (llamadas ADCx). En el esquema anterior se muestran 8, pero el número de entradas analógicas depende del microcontrolador; por ejemplo, el ATtiny85 sólo dispone de 4.
  • El rango de tensión admitido por el ADC está entre 0 y AREF voltios. Esta tensión (AREF, tensión de referencia) se puede configurar para que sea igual a Vcc (la tensión de alimentación del microcontrolador) o para usar otras tensiones inferiores, que el micro genera internamente.
  • La tensión de entrada se denomina Vin, y es la tensión de la patilla (ADCx) actualmente seleccionada con el multiplexor
  • El ADC sólo puede realizar una conversión cada vez, porque sólo hay un conversor
  • El resultado de la conversión se guarda en dos registros, ADCH y ADCL. Esto es necesario, porque el conversor tiene 10 bits que debe guardar en registros de 8 bits.

La relación entre la tensión de entrada (Vi, lo que se quiere medir) y el valor de salida del conversor (S) es la siguiente:

\[S=V_i \left[\frac{1023}{V_r}\right]\]

Los corchetes indican la operación redondeo: el resultado del conversor es un número entero entre 0 y 1023. Vr es la tensión de referencia AREF.

Modos de operación

El conversor AD tiene dos modos de operación: conversión única y conversión continua (denominada free running en la hoja de datos de AVR).

Conversión única

En este modo, el programa que usa el conversor debe iniciar la conversión cada vez que lo necesite. Cuando la conversión se completa, el resultado se guarda en los registros ADCH y ADCL, el bit ADIF se pone a 1 y el conversor se detiene.

Para comenzar una conversión hay que poner a 1 el bit ADSC (AD Start Conversion) en el registro ADCSR. El bit se mantendrá con ese valor (1) mientras el conversor esté realizando la conversión, y se pondrá automáticamente a cero cuando la conversión termine.

Antes de poner a 1 el bit de inicio de la conversión se debe seleccionar el canal analógico que quiere usarse (el pin ADCx). Esto se hace ajustando el valor del registro ADCMUX al número indicado en la hoja de características para cada canal.

La detección del final de la conversión desde el programa que la solicita puede hacerse mirando el valor del bit ADSC (cuando vuelva a valer 0, la conversión habrá terminado), o puede hacerse mediante interrupciones (el conversor dispara una interrupción con el bit ADIF cuando termina la conversión).

Modo continuo (free running)

En modo continuo, el programa inicia la primera conversión de la misma forma que en el modo de conversión única, pero después no es necesario volver a iniciarla: el conversor empieza una nueva conversión cada vez que termina la anterior.

Cuando se usa este modo, si se desea cambiar el canal (el pin de entrada ADCx) debe hacerse antes de que comience la conversión siguiente.

Reloj de conversión

El conversor AD necesita una señal de reloj para fijar los tiempos de su funcionamiento. Esta señal se denomina CLOCK, y es proporcionada internamente por el microcontrolador a partir de la señal de reloj, con un factor de reducción denominado prescaler, que divide la frecuencia del reloj del micro para generar la señal CLOCK.

El pre-escalado se define con los tres bits ADPSx del registro ADCSRA, y puede tomar valores de 2, 4, 8, 16, 32, 64 o 128 según el estado de esos tres bits. La frecuencia del reloj de conversión se obtiene a partir de la frecuencia de reloj (Fc) del micro y de este factor de pre-escalado (Ps) de modo sencillo:

\[F_a=\frac{F_c}{P_s}\]

Por tanto, la frecuencia de conversión AD depende de la frecuencia del micro y del valor de este factor de escala. La siguiente tabla muestra las frecuencias de conversión AD en KHz que se obtienen para distintas frecuencias de funcionamiento del micro con los posibles valores de pre-escalado:

Prescaler20 MHz16 MHz12 MHz8 MHz1 MHz
210 MHz8 MHz6 MHz4 MHz500 KHz
45 MHz4 MHz3 MHz2 MHz250 KHz
82.5 MHz2 MHz1.5 MHz1 MHz125 KHz
161.25 MHz1 MHz750 KHz500 KHz62.5 KHz
32625 KHz500 KHz375 KHz250 KHz31.25 KHz
64312.5 KHz250 KHz187.5 KHz125 KHz15.625 KHz
128156.25 KHz125 KHz93.75 KHz62.5 KHz7.813 KHz

Las frecuencias del microcontrolador que se reflejan en la tabla (columnas) son las frecuencias soportadas por el software de Arduino a partir de 1 MHz. Es posible, por supuesto, utilizar frecuencias intermedias (por ejemplo, 7 Mhz), pero en ese caso sería necesario modificar el código de Arduino que depende de la frecuencia (retardos temporales, reloj interno, etc.) o bien programar el micro directamente sin hacer uso de Arduino.

El fabricante recomienda que la frecuencia de funcionamiento del conversor AD esté entre 50 y 200 KHz para conseguir una resolución real de 10 bits (en la tabla se indican estos casos en color verde). Si la frecuencia es mayor, la precisión de la medida se degrada, y aunque el resultado sigue siendo un número de 10 bits, los errores introducidos por el aumento de velocidad hacen que los bits menos significativos no aporten información real.

Como es de esperar, Arduino configura el pre-escalado del conversor AD dentro de estos límites. Esta configuración se encuentra en el fichero wiring.c, donde puede verse que, para el caso de 16 MHz de reloj del micro (por ejemplo), el factor de pre-escalado se configura a 128.

La hoja de características indica que la frecuencia de conversión se puede subir hasta un máximo de 1 MHz (casos indicados en color naranja). Con esto se pueden conseguir velocidades de muestreo mayores con una precisión algo degradada (inferior a 10 bits). Para frecuencias superiores a 1 MHz (casos marcados en color rojo) el funcionamiento correcto no está garantizado.

El tiempo necesario para realizar una conversión AD completa depende de esta frecuencia. El conversor AD necesita 13 ciclos de reloj AD para realizar una conversión (la primera conversión es siempre más lenta: el fabricante especifica que se requieren 25 ciclos de reloj AD en esta conversión). La tabla siguiente muestra los tiempos necesarios para completar la conversión en microsegundos para las frecuencias de conversión AD definidas con el pre-escalado:

Prescaler20 MHz16 MHz12 MHz8 MHz1 MHz
21.31.6252.1673.2526
42.63.254.3336.552
85.26.58.66713104
1610.41317.33326208
3220.82634.66752416
6441.65269.333104832
12883.2104138.6672081664

En la siguiente tabla se presentan las máximas frecuencias de muestreo en KHz que pueden conseguirse con cada configuración de reloj AD, y que se obtienen simplemente calculando la inversa del periodo de muestreo (el tiempo de conversión completa mostrado en la tabla anterior):

Prescaler20 MHz16 MHz12 MHz8 MHz1 MHz
2769.23615.39461.538307.6938.46
4384.62307.69230.77153.8519.23
8192.31153.85115.3976.929.62
1696.1676.9257.6938.464.81
3248.0838.4628.8519.232.40
6424.0419.2314.429.621.20
12812.029.627.214.810.60

Como puede verse, para aumentar la velocidad de conversión AD sin salirse de los límites recomendados puede ser necesario bajar la frecuencia de reloj del micro. Por ejemplo, con el micro a 16 MHz sólo se puede usar el pre-escalado de 128, y se consiguen 125 KHz de frecuencia AD, y con ello un tiempo de conversión de 104 microsegundos (es decir, una frecuencia máxima de conversión completa de 9600 Hz). Al bajar a 12 MHz se puede usar el pre-escalado de 64 para conseguir una frecuencia AD de 187.5 KHz, que supone un tiempo de conversión de 96.3 microsegundos (unos 14400 Hz de frecuencia de conversión completa).

De todos modos, no siempre es posible bajar la velocidad del reloj del micro, y en cualquier caso la mejora de velocidad que se consigue no es muy grande. Si se necesitan frecuencias de conversión mayores asegurando una precisión alta, probablemente el conversor AD de los microcontroladores AVR no es el dispositivo adecuado. En estos casos se puede sustituir el micro por otro de la familia Xmega, que tienen conversores AD de 12 bits y velocidades muy superiores, o bien se puede usar un circuito integrado de conversión AD externo.

Resolución

Como se ha indicado, la resolución del conversor AD es de 10 bits. Esto implica que el resultado de la conversión es un número con valores entre 0 y 1023. Si la referencia de tensión del conversor (VREF) se configura a 5 voltios, esto significa que el cambio de tensión más pequeño que puede detectarse es de 5 / 1023 = 4.9 mV.

También se ha indicado que el fabricante recomienda mantener la frecuencia del conversor AD entre 50 y 200 KHz para no reducir la resolución real de la conversión. La nota de aplicación AVR120 explica este aspecto:

La precisión del conversor AD depende también del reloj AD. La frecuencia máxima de reloj AD está limitada por el circuito interno de conversión digital-analógico (DA). Para un funcionamiento óptimo, el reloj AD no debería exceder los 200 KHz. Sin embargo, frecuencias de hasta 1 MHz no reducen la resolución de conversión AD de modo significativo.

La operación con frecuencias AD superiores a 1 MHz no está caracterizada.

Por tanto, el fabricante sólo garantiza una buena resolución de conversión AD en el rango de frecuencias sugerido, pero no especifica cuánta resolución se pierde al aumentar la frecuencia por encima de 200 KHz. Tampoco lo hace para frecuencias superiores a 1 MHz: en esos casos, simplemente indica que no han hecho ensayos y no saben cómo responderá el conversor AD.

Es por ello interesante realizar algún ensayo que permita valorar el funcionamiento del conversor a frecuencias altas. Conviene notar que estos ensayos no son concluyentes, porque hacen uso (como se verá) del reloj interno del micro para medir los tiempos, y porque el efecto de usar una frecuencia AD fuera de los rangos sugeridos por el fabricante podría depender de los procesos de fabricación, y por ello ser distinto de un microcontrolador a otro, aunque sean del mismo tipo.

Ensayos de conversión a alta velocidad

Para verificar la viabilidad de utilizar frecuencias altas de conversión AD, que permiten obtener más muestras por segundo, se definen y ejecutan varios ensayos de conversión. El objetivo concreto de los ensayos consiste en medir la reducción en la precisión de la conversión y en medir el periodo de muestreo (y con ello la frecuencia de muestreo) alcanzable.

La programación se realiza utilizando Arduino, y por ello es necesario utilizar una configuración hardware concreta e introducir algunos cálculos adicionales para obtener una medida precisa de las dos magnitudes de interés.

Hardware

Para obtener una medida fiable de la precisión es necesario conocer con exactitud la tensión analógica de entrada que el conversor va a medir y a convertir en un valor digital de 10 bits. Esto puede conseguirse si la tensión de entrada se genera con un divisor de tensión cuyas resistencias son conocidas. Al mismo tiempo, es necesario conocer con exactitud la tensión de alimentación del micro y de este divisor resistivo. Estas dos tensiones pueden ser la misma, pero en cualquier caso es imprescindible que no cambien durante la ejecución del ensayo.

Por eso es importante que el microcontrolador disponga de un condensador de desacoplo, y que el montaje del circuito sea compacto, proporcionando pistas cortas en la sección analógica que reduzcan la captación de interferencias.

El divisor resistivo puede implementarse mediante resistencias discretas, o bien mediante un potenciómetro. En este segundo caso hay que asegurarse de que el potenciómetro no cambia sus características durante el ensayo. La calidad del potenciómetro determinará la precisión de la resistencia obtenida una vez ajustado a una posición concreta. Por otro lado, la resistencia puede cambiar por efectos térmicos: por ello, es importante dejar el circuito en funcionamiento (alimentado) durante un tiempo antes de comenzar el ensayo, de modo que llegue al equilibrio térmico.

Medida de la precisión

La falta de precisión tiene dos efectos en la medida del conversor:

  • Modifica el valor medio de la medida, que debería ser igual al valor de la tensión de entrada
  • Modifica la variabilidad de la medida, que debería ser constante si la entrada no cambia

Para medir ambos efectos es necesario conocer la tensión de entrada y el valor digital que, teóricamente, debería generar el conversor AD. Este valor es el resultado ideal de la conversión, que se usará para compararlo con un promedio de los resultados de conversión.

Este promedio debe ser de larga duración para eliminar de la medida la influencia de cualquier variación periódica o cuasi-periódica introducida por interferencias externas.

La variabilidad de la medida se obtiene calculando la raíz positiva de la varianza del resultado de conversión (la desviación estándar con signo positivo). Esta magnitud es la media de las diferencias entre las muestras procesadas y su valor medio, y es un buen indicador de la variabilidad.

El cálculo de la desviación típica puede hacerse sin necesidad de calcular la raíz cuadrada: basta con elegir un número de muestras que sea potencia de 2 y utilizar la raíz de ese número en los cálculos. Al mismo tiempo, la diferencia entre la muestra y la media debe calcularse en valor absoluto, es decir, cambiando el signo si el resultado es negativo. Como la raíz de n es potencia de 2, la división se convierte en un desplazamiento de bits y la operación puede hacerse muy rápidamente.

Medida del periodo y frecuencia de muestreo

Para medir el periodo de muestreo se utiliza el reloj interno proporcionado por Arduino, al que se tiene acceso mediante la función micros(). Esta función devuelve el tiempo en microsegundos que ha transcurrido desde que se inició el proceso (desde que el micro fue alimentado).

Arduino hace uso de una interrupción generada por un temporizador para calcular el tiempo. Debido a la configuración del temporizador, la precisión del tiempo es de 4 microsegundos. Por ello, y dado que se está haciendo una medida estática y se aplican promedios, se puede también calcular el periodo de muestreo como el promedio de los tiempos medidos para cada muestra.

Implementación del código de ensayo

TBD

Resultados

TBD

! Comentario

  1. gustavo romero's Gravatar gustavo romero
    octubre 28, 2015    

    hola , buenisima informacion muy clara y precisa
    me encantaria leer una una nota parecida refiriendose a los timer , como activar sus interrupciones y los modos de disparo , estare atento a que puedan subir esa info
    podrian dar ejemplos .

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Proyecto ICARO

Galería de vídeo de Jóvenes Científicos