El Convertidor Análogo-Digital en Arduino

Primero que nada disculpas a todos por haber estado desaparecido durante el último mes. Se me juntaron muchas cosas del trabajo y estuve un par de semanas completamente desconetado de Internet.

Regresando al tema, habrán visto que en algunas entradas anteriores he hecho uso del convertidor Análogo-Digital incluído en el Arduino. Pero poco o nada me he detenido a explicar su funcionamiento o como utilizarlo.

Para dar continuidad a los artículos de Arduino, en esta entrada les explicaré algunas generalidades sobre convertidores Análogos-Digital y cómo utilizarlos en el Arduino.


Lo análogo y lo digital


Al principio, solo solo existían los circuitos análogos. La electrónica digital y su uso generalizado es relativamente reciente, antes de ello los circuitos electrónicos análogos eran la regla.

La diferencia entre ambos tipos de circuitos es bastante sencilla: Mientras que en los circuitos digitales su funcionamiento está determinado por las combinaciones de estados lógicos que usualmente identificamos como 1s y 0s. En la electrónica análoga los valores son continuos es decir que una señal puede tomar cualquier valor de voltaje o corriente dentro del rango para el que fué diseñado. Si en la electrónica digital solo tenemos blanco o negro, en la electrónica análoga las señales son todas escalas de gris.

Si bien la mayoría de equipos electrónicos modernos están controlados por lógica o controladores digitales, vivimos en un mundo análogo así que se hace necesaria la existencia de un dispositivo que convierta los valores que observamos a nuestro alrededor en datos digitales que se puedan analizar.

Midiendo el mundo análogo


El convertidor Análogo-Digital (ADC por sus siglas en inglés) es un dispositivo que toma una señal análoga (corriente, voltaje, temperatura, presión, etc.), cuantifica la señal y le asigna un valor que se muestra a su salida en formato digital.

Los ADC más comunes son aquellos que convierten señales de voltaje o corriente a su equivalente digital aunque podemos encontrarlos para medir diversidad de magnitudes análogas. Afortunadamente los Arduinos incluyen de fábrica uno o varios ADC que nos permiten convertir niveles de voltaje a valores digitales.

En general hay tres cosas que nos interesa saber sobre un ADC:
  1. La resolución
  2. El tiempo de conversión
  3. El rango de trabajo
Vamos ahora a revisar en detalle cada una de estas tres características.

La resolución del convertidor


Uno de los mayores incovenientes de convertir señales análogas a su equivalente en digital es que pasamos de una señal que por naturaleza es continua y sin cortes a un dato discreto, que solo puede tener ciertos valores. Este proceso es conocido como "cuantificación".

Generalmente la cantidad de valores discretos en los que un ADC puede traducir una señal análoga a digital se conoce como su resolución y usualmente es medida en base al número de bits que el ADC tiene a su salida. El número de bits representa la cantidad máxima de valores discretos o de pasos que un ADC puede tener.

Supongamos por ejemplo que tenemos un convertidor ADC de 3 bits. Este convertidor podrá tener solo 8 valores diferentes a su salida. Esto significa que nuestros voltajes al ser convertidos podrían tener mas o menos la siguiente distribución (asumiendo un voltaje máximo de 5V):

Entrada análoga (V)Salida digital
0.000 - 0.6250
0.625 - 1.2501
1.250 - 1.8752
1.875 - 2.5003
2.500 - 3.1254
3.125 - 3.7505
3.750 - 4.3756
4.375 - 5.0007

Para calcular el número de valores discretos que el ADC es capaz de convertir utilizaremos esta fórmula:


Seguramente ahora te estarás preguntando: ¿Qué tanta resolución necesito? La respuesta depende muchísimo de la aplicación. Si por ejemplo estás fabricando un "dimmer" digital posiblemente estos 8 pasos de resolución sean más que suficiente para la esa aplicación. Si en cambio estás haciendo un control en que requires muchísima precisión tener solo 8 pasos de conversión puede resultar desastroso.

El Arduino Mega que utilizaremos en este ejemplo posee 10 ADC con una resolución de 10bits cada uno. Esto significa que para cada entrada análoga tenemos disponibles 1024 pasos o valores discretos, para la mayoría de aplicaciones esto resulta más que suficiente.

El tiempo de conversión y la frecuencia de muestreo


Lástimosamente la conversión de una señal análoga a su equivalente valor digital no es instantánea, esto significa que el convertidor tarda algún tiempo (usualmente muy pequeño) en realizar el proceso de conversión. Esto limita el número de conversiones que podemos realizar en una unidad de tiempo, a este número de conversiones que puede realizar un ADC usualmente se le conoce como frecuencia de muestreo o en ingles "sampling rate".

Podemos entender este parámetro como la precisión del convertidor en el tiempo. Un ADC con un tiempo de conversión de 1 segundo es más lento que uno que tarde 0.001segundos en hacer una conversión. La frecuencia de muestreo máxima del ADC se calcula utilizando el inverso del tiempo de conversión:


Al igual que el parámetro de la resolución, que la frecuencia de muestreo sea buena o mala depende mucho de que tan rápido cambie el valor análogo que deseamos medir. Por ejemplo si tenemos una sonda que mide la humedad en el suelo, el valor a medir no va a cambiar hasta que transcurran algunos minutos por lo que un ADC que tarde 1 segundo en realizar la conversión no nos va a dar mayor problema, por el contrario si estamos queriendo convertir a digital una señal de audio, 1 segundo de tiempo de conversión se queda sumamente corto para capturar las frecuencias que el oido puede distinguir.

Una forma simple para elegir un ADC es que la frecuencia de muestreo sea "al menos"  el doble de la frecuencia de la señal que queremos convertir (ver Teorema de muestreo de Nyquist-Shannon). Por ejemplo si queremos medir una señal que oscila a 60Hz lo menos que necesitaremos es un ADC que logre tomar 120 muestras por segundo.

Según la hoja de especificaciones del ATmega1280, el tiempo de conversión del ADC varía entre 13μs  y 260μs lo que implica una frecuencia de muestreo teorica entre 3.8kHz y 76.92kHz. Obviamente el ATmega1280 no es lo suficientemente rápido como para alcanzar la máxima frecuencia de muestreo teórica del ADC.

El rango de trabajo


La tercer característica, pero no la menos importante, que debemos tomar en consideración al elegir un ADC es el rango de voltajes/corrientes que acepta en su entrada, este parámetro es escencial para evitar "quemar" (literalmente) nuestro ADC.

La única forma de saber el rango del ADC es revisando su hoja técnica, usualmente encontraremos el rango de valores de voltaje y de corriente aceptados en la entrada como también las tolerancias aceptadas.

Para el Arduino Mega, según las especificaciones técnicas el rango de entrada va desde 0v hasta Vcc (5V).

Voltajes de referencia


El voltaje de referencia es un voltaje utilizado como valor "maximo" por el ADC para realizar el proceso de conversión.

El Arduino Mega puede utilizar dos valores como referencia para realizar la conversión, el primero es el voltaje de alimentación (5V) y el otro es un voltaje externo en tanto este no supere el voltaje de alimentación (Vcc).

¿Para que usar un voltaje de referencia externo? Si recuerdan, la resolución de nuestro ADC está limitada a un numero de pasos predefinido por el fabricante. En el caso de que la señal que deseamos medir tenga un valor menor al voltaje de alimentación entonces el rango de valores que podemos utilizar se reduce y por lo tanto reducimos también la precisión.

Por ejemplo: Nuestra señal varía desde 0 a 2.5V. Si calculamos nuestro tamaño de "paso" para cada valor utilizando la referencia de la alimentación (5V):


Pero si en cambio utilizamos el voltaje de referencia de 2.5V:



Puedes ver como el tamaño de paso se reduce casi a la mitad utilizando el valor máximo de voltaje medido como referencia, aumentando en consecuencia la precisión de los valores medidos para esa señal en particular.

¿Qué hacer si quiero medir un voltaje mayor que el rango de entrada?

Un truco básico es utilizar un divisor de voltaje. Para el divisor de voltaje se recomienda utilizar resistencias de valores altos para que las corrientes se mantengan al mínimo. Por ejemplo si quisieras medir 100V con un Arduino cuya entrada máxima son 5V:

Primero divides entre el voltaje máximo que quieres medir entre el voltaje de referencia (5V) para encontrar el numero de resistencias que deberá tener tu divisor de voltaje:



Como tener un divisor de voltaje con 20 resistencias es un poco incómodo y ocupa mucho espacio podrías tener algo como lo siguiente:


En este caso estarás midiendo 1/20 del voltaje. Solo ten cuidado con las tolerancias de las resistencias. Si asumimos por ejemplo que la tolerancia de las resistencias es del 5%, su valor real podria variar entre 0.95K y 1.05K es posible que tengas que utilizar un divisor mas grande para así jugar seguro y luego agregas un pequeño factor de corrección mediante software.

El dimmer digital


Ahora vamos a poner en práctica los conocimietos sobre ADC que hemos adquirido y vamos a utilizar algunas funciones muy útiles del Arduino. En este caso vamos a fabricar un dimmer de LED digital.

Un "dimmer" o un "atenuador" es un sencillo dispositivo que atenua la intensidad de una luz. Seguramente más de alguno ha utilizado o tienes uno de estos dispositivos en sus hogares.

Atenuar un LED es un poco más complicado, el problema es que los LED no funcionan calentando un filamento como los focos incandescentes sino que convierten directamente la energía eléctrica en luz. Esto los hace muy eficientes, tan eficientes que si los hacemos funcionar fuera de su rango optimo de trabajo, por ejemplo reduciendo la corriente, desperdiciaremos mucha energía en forma de calor y adicionalmente podriamos notar algunas diferencias en el color del LED en tanto reducimos su intensidad.

Una solución sencilla muy práctica para atenuar LEDs con circuitos digitales es utilizar "modulación de pulsos". La ventaja de utilizar esta técnica es que permite que el led mantenga su color (ya que siempre funciona utilizando la misma corriente) y simplemente cambia la intensidad de la luz emitida. Realmente lo que sucede es que el led se esta apagando y encendiendo muy rapidamente lo que reduce la cantidad de luz que emite, esto ocurre tan rapido que nuestro ojo no lo nota y pareciera que el led esta reduciendo su intensidad.

Afortunadamente Arduino ya incluye la funcionalidad para generar señales PWM e incluso ya lo hemos discutido en una de las primeras entradas de este blog.

El circuito que utilizaremos en esta ocasión es sumamente sencillo, estos son los materiales que vamos a necesitar:
  • 1 x Arduino Mega
  • 1 x Resistencia 330Ohm (o 470Ohm)
  • 1 x Diodo Led
  • 1 x Potenciometro (resistor variable) de 1K.
El diagrama del circuito es el siguiente:



Programando nuestro Arduino

void setup() {
  pinMode(2,OUTPUT);
}

En el setup no es requisito configurar como salida el PIN donde conectaremos el LED, sin embargo lo dejo indicado solo para que quien lea el código sepa que en esa línea es donde lo conectaremos.

Para el loop principal utilizaremos el siguiente código:

El código funciona en tres pasos:

int value;
void loop() {
  value = analogRead(0);
  value = map(value,0,1023,0,255);
  analogWrite(2,value);
  delay(20);
}
  1. Leemos el dato del voltaje del potenciometro.
  2. Usamos la funcion map para cambiar el rango de entrada de 0-1023 a 0-255 (el rango que soporta analogWrite)
  3. Escribimos el nuevo valor mapeado como PWM a la salida donde está conectado el LED.
  4. Utilizo un pequeño delay para evitar que el valor cambie muy frecuentemente.
La función map permite convertir un rango especificado en otro. Esto es muy útil cuando uno necesita que el valor análogo de la entrada se corresponda con un rango diferente en la salida. En este caso nuestro valor de entrada varía entre 0 y 1023 pero la función analogWrite está esperando un máximo de 255.

Para finalizar los dejo con un pequeñísimo video del funcionamiento:



¡¡Y eso es todo!! Espero que esta entrada les haya ayudado a entender como funcionan los convertidores análogo-digital y lo puedan utilizar para sus proyectos e inventos.

Sin nada más que decir... ¡¡Hasta la próxima!!


Créditos:
  1. Fotografía tubos de vacío por Project Dehli licencia CC BY-NC-ND.
  2. Gráfico ADC de How to Choose the Right DAC Hardware for your System.
  3. Gráfico de frecuencia de muestreo de About Oscilloscope Sample Rate.
  4. Fotografía de LEDS por Mike Deal aka ZoneDancer licencia CC BY-ND.

Comentarios

kmargopolis ha dicho que…
saludos y muy buenos tus tutoriales
Unknown ha dicho que…
Hola, muy bueno el tutorial.
Tiene un Error en la ecuación del tiempo de respuesta y frecuencia de muestreo, es el inverso, no dividido por 1, es 1 dividido por el tiempo. Saludos!
Jimmy ha dicho que…
Saludos y muchas gracias por el tutorial que has hecho me parece una buena base para la implementacion de un sistema de adquisicion de datos por cierto la razon es que hecho estoy en el proceso de realizar un proyecto de ese tipo pero tengo problemas cuando trato de muestrear una señal cuadrada generada a partir de un multivibrador astable hecho con el 555 la frecuencia de mi señal es de 20kHz por cierto estoy utilizando matlab y arduino pero al parecer de la pagina oficial de arduino http://arduino.cc/es/Reference/AnalogRead se dice que la maxima frecuencia de muestreo del mismo es de 10kHz mi arduino es un MEGA 2560 y estoy pensando en usar un divisor de frecuencias para acoplar la frecuecia de la señal a lo que podriamos decir es el ancho de banda del arduino pero dado el conocimiento que veo tienes me gustaria saber si me podrias dar una sugerencia para mi problema ya que cuando grafico en matlab la señaal que obtengo no es la esperada
Manuelez ha dicho que…
hey que tal, está buena la información... he visto el mismo ejemplo que haces en muchos blog pero que sucede si la entrada ya no es una señal análoga lineal sino es una señal análoga variable?... cómo haría mi programación?...

Entradas populares de este blog

Reactivando el Blog

Emulando el Raspberry Pi OS con QEMU en Linux

Escribiendo Mensajes al Blockchain de Bitcoin