Está en la página 1de 15

LA CONVERSIÓN DE ANALÓGICO A DIGITAL

En una sesión previa ya dijimos que Arduino dispone de 6 convertidores analógico a digital
(ADC) que son los pines A0 a A5, y dijimos que son capaces de convertir valores de
tensión hasta un máximo de 5V, que es la tensión de referencia en Arduino.
Ya dijimos también, que una de las características claves del convertidor, es su número de
bits, que define la finura con los que podemos cuantificar esa conversión a digital. En el
caso de Arduino, son 10 los bits que maneja en la puertas analógicas, lo que significa que
su resolución es 210 =1.024 posibles valores.
Cuanto mayor sea esta resolución mejor es la capacidad de aproximación al valor real
cuya conversión buscamos.

 Es importante entender que una conversión a digital de una señal analógica es siempre
una aproximación, y ni siquiera en el improbable caso de que el valor analógico fuese
exactamente el que nos dice el convertidor, siempre tendremos una incertidumbre.
 En un convertidor como los de Arduino con 10 bits de resolución, cada escalón de medida
es de 5V/1024 = 0,0048828125 V, algo menos de 5mV, lo que significa que no puede
discriminar entre valores de tensión cuya diferencia sea menor que esto.

Sin entrar en muchos detalles, conviene decir que lo que un convertidor ADC hace es
comparar sucesivamente la señal que queremos cuantificar en la entrada, con una tensión
de referencia contra la que hace las comparaciones.
Dicho de otro modo, un ADC no proporciona valores absolutos, sino que proporciona una
comparación cuantificada con relación a un valor de referencia. Por eso, en la
sesión Sensor de temperatura TMP36 hemos calculado la tensión de entrada en uno de
los pines Analógicos como la lectura multiplicada por una relación entre el valor de la
máxima de la entrada 5V con la máxima medida del conversor 1024.

Como las señales que normalmente manejamos en Arduino están alrededor de los 5V,
comparar contra 5V es lo razonable, porque además la industria tiene una gama completa
de sensores cuyo valor máximo devuelve 5V.
Pero cada vez más, la industria produce electrónica de 3,3V, el propio Arduino DUE es un
ejemplo de ello, y si usamos nuestros ADC para digitalizar señales de pico 3,3V, estamos
perdiendo precisión y resolución, porque estamos desperdiciando una parte de las
posibles comparaciones, de hecho un tercio.
En la práctica, al ser 3,3V el máximo de la tensión de entrada compararlo contra 5V
supone que nunca tendremos lecturas mayores de 1.024 * 3,3 /5 = 675 y seguiremos
teniendo escalones de entrada de 5mV.
Pero si el convertidor es un comparador de tensiones, si pudiéramos cambiar el valor de
tensión contra el que comparamos por una de 3,3V, los escalones serian de 3,3V/1024 =
0,00322265625 o sea 3,2 mV. Es decir hemos mejorado la resolución de nuestro
convertidor y sin gastar un chavo.
Por eso en una situación ideal, la tensión de comparación contra la que realizamos
la conversión de analógico a digital, debería ser el valor máximo posible de la señal de
entrada. Porque es cuándo tendremos la mejor resolución posible con ese convertidor.
Los chicos de Arduino, eran conscientes de este asunto y por eso incluyeron un pin
externo, que no habíamos usado hasta ahora, que permite conectar una tensión externa
de referencia, contra la que se comparará la señal que leamos en nuestras puertas A0 a
A5.
Este pin esta rotulado como AREF (Analog Reference o Referencia Analógica en cristiano)
y está dos pines más arriba del digital pin 13:
USANDO LA REFERENCIA ANALÓGICA EXTERNA
La cuestión de la referencia analógica contra la que comparamos las muestras en las
puertas A0-A6, es tan importante, que Arduino provee varias tensiones internas contra las
que comparar y que podemos activar para cambiar dicha referencia.
Para activar una referencia interna de 1,1V en un Arduino UNO usa la instrucción

analogReference(INTERNAL);

Si por el contrario usas un MEGA puedes usar exclusivamente:

analogReference(INTERNAL1V1);
analogReference(INTERNAL2V56);

Que te activará referencias de 1.1V y 2.56V respectivamente.


Si usamos la clave DEFAULT, volvemos a la referencia estándar de 5V en prácticamente
todos los modelos de Arduino.

analogReference(DEFAULT);

 Cuidado con la referencia DEFAULT, porque en el DUE significa 3,3V porque es su tensión de
referencia. Asegúrate de esto antes de usarlo alegremente.

Cuando conectemos una tensión de referencia al pin AREF, tenemos que avisar a Arduino
de que queremos usarla. Y eso lo hacemos con la instrucción

analogReference(EXTERNAL);

Usad la cabeza cuando modifiquéis la referencia analógica, porque si no tenéis cuidado,


cenareis Arduino a la brasa. Es relativamente fácil de liarla con ciertas acciones que
parecen inocentes:

 Asegúrate de que si usas una referencia externa los GND de Arduino y de la referencia
sean el mismo uniéndolos. No hacer esto tiene muy mal pronóstico a la primera de cambio.
 No uses bajo ninguna circunstancia menos de 0v en el pin AREF ( O una señal que varíe y
pueda tener transitorios negativos) porque el resultado es impredecible.
 Si conectas una tensión externa de referencia, no llames a analogRead() antes de ejecutar
la instrucción analogReference(EXTERNAL), porque harías un cortocircuito entre la señal
de comparación interna y la tensión externa en AREF, y posiblemente podrás aprovechar
la ocasión para comprarte ese Arduino nuevo al que le tienes tantas ganas.
 No conectes a AREF menos de 1V ni más de 5V, no puedes poner 12 y esperar que te dé
un valor tranquilamente.

CIRCUITO DE PRUEBA
Vamos a montar un circuito de prueba con un display I2C como vimos en la sesión.. y un
potenciómetro. Pero en esta ocasión, conectaremos en los extremos del potenciómetro
GND y 3,3V de modo que en el pin central que leeremos con A1, no puede nunca superar
los 3,3V simulando un sensor con ese valor máximo.
Al ir girando el potenciómetro, leeremos una caída de tensión entre 0V y 3,3V. y la lectura
del pin A1, dará valores entre 0 y 670, ya que estamos en el caso que definíamos un poco
más arriba.

El programa simplemente leerá el pin analógico A1 y enviara su valor a un display I2C de


16 caracteres por dos líneas tal y como vimos en la sesión….

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27
LiquidCrystal_I2C lcd(I2C_ADDR,2, 1, 0, 4, 5, 6, 7);

void setup()
{
lcd.begin (16,2); // Inicializar el display con 16 caraceres 2 line
as
lcd.setBacklightPin(3,POSITIVE);
lcd.setBacklight(HIGH);
lcd.home (); // vamos al principio
lcd.print("Prometec.net");
}

void loop()
{
lcd.setCursor ( 0, 1 ); // Vamos a la segunda linea
lcd.print(analogRead(A1));
}

Aquí teneis un minivideo con las lecturas del potenciómetro


Si ahora conectamos la tensión de 3,3V interna de Arduino al pin AREF, tendremos un
circuito como este:

Veamos ahora el programa:

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR 0x27


LiquidCrystal_I2C lcd(I2C_ADDR,2, 1, 0, 4, 5, 6, 7);

void setup()
{ lcd.begin (16,2); // Inicializar el display con 16 caraceres 2 lineas
lcd.setBacklightPin(3,POSITIVE);
lcd.setBacklight(HIGH);
lcd.home (); // vamos al principioe
lcd.print("Prometec.net");

analogReference(EXTERNAL); // Atentos aqui


}

void loop()
{ lcd.setCursor ( 0, 1 ); // Vamos a la segunda linea
lcd.print(analogRead(A1));
lcd.print(" "); // Para borrar rastros en pantalla
}

Aqui teneis un video con la diferencia:

¿Para qué sirve el pin AREF en Arduino?

En muchas ocasiones cuando estamos trabajando en nuestros proyectos


electrónicos se es necesario trabajar a X voltaje de referencia. Supongamos que
tenemos un sensor de temperatura LM35, este sensor ofrece una salida de tensión
lineal con respecto a la temperatura, utiliza un factor de escala de 10 mV/°C.
Imaginemos entonces que necesitamos este sensor para medir la temperatura de
cierto lugar utilizando nuestro Arduino UNO. Para poder leer la temperatura del
lugar necesitamos convertir la medida de temperatura que es una medida física a
otra de tipo eléctronico. Este trabajo es el que precisamente hace el sensor. Ahora,
el voltaje de salida que nos proporciona el LM35 es una señal analógica que
debemos convertirla a una señal digital para poder procesarla, el mago que realiza
este proceso se llama Conversor Analógico/Digital.
El Arduino UNO o más bien, el microcontrolador ATmega 328 utiliza un ADC de 10 bits ¿qué
quiere decir el número diez? El diez nos indica el exponente en base dos que generará el número
combinaciones posibles para representar una señal analógica, o bien el número de bits. Así, en
nuestro caso tendremos 2^10 = 1024 combinaciones posibles para representar la señal que irá
desde 0 a 2^10 – 1 = 1023. Para capturar la medida analógica, el arduino uno posee seis entradas
analógicas donde cada una está conectada a un canal del conversor. Así, se podría utilizar un pin
de entrada analógica del arduino para leer el voltaje que proporciona el LM35. Para leer este
voltaje se utiliza una función llamada analogRead() que proporciona un rango de valores
comprendidos entre 0 y 1023. Como ya sabemos, este rango proviene de la resolución de bits en
el conversor del microcrontrolador. Pero estos valores están tomados en referencia a 5 volts.
Para dejar este apartado más claro, utilizaremos una resolución de bit de 3. Esto quiere decir que
el ADC tendrá 2^3 posibles combinaciones, que irán desde 0 a 7 en escalones de 0.625 V cada
uno. Así, cuando el voltaje en la entrada del conversor esté entre 0 y 0.625 V, tendremos un valor
digital de 0. Si el valor está comprendido entre 3.75 y 4.375 V tendremos un valor digital de 6 y
así.
{rokbox title=|Gráfica que muestra los valores digitales del ADC para cada rango de voltaje de
una señal analógica Este conversor ilustrativo posee un número de bits de 3, logrando representar
hasta 8 valores digitales de 0 a 7.|
thumb=|http://www.clase911.com/CV/images/problems/arefarduino.jpg|}http://www.clase911.c
om/CV/images/problems/arefarduino.jpg{/rokbox}
Volviendo a nuestro Arduino UNO tenemos que la resolución de bits es 10. Teniendo entonces
escalones de 4.88 mV. Es decir que cada escalón en nuestro conversor representará 4.88 mV.
Para nuestro sensor de temperatura, el máximo valor de voltaje que puede brindar es de 1500 mV
o bien 1.5 V. Entonces esto nos indica que ya nuestro arduino no estaría leyendo voltajes que
están por arriba de 1.5 V y es aquí donde entra el en juego el pin AREF.
Si ya nuestro valor máximo no es de 5 V sino de 1.5 V, tendríamos que utilizar un voltaje de
refencia externo para no desperdiciar resolución y tener mayor exactitud a la hora de la medición.
El encargado de esto es el pin AREF que nos permite utilizar un voltaje de referencia externo.
¿Cómo le decimos al Arduino UNO que ya no vamos a utilizar 5 V como voltaje de referencia?

Utilizamos una función dentro de nuestro programa llamada analogReference().


Para duemilanove y compatibles con ATmega328:

1 //Importante: este voltaje debe estar comprendido entre 0 y 5 Volts DC.


2 analogReference(EXTERNAL);

Es necesario llamar esta función antes que se lean los valores de voltaje utilizando
analogReference() ya que de lo contrario podrías dañar tu Arduino.

Si deseamos entonces trabajar a 1.5 V de referencia tendríamos que utiliza un


simple divisor de voltaje en donde el voltaje que entre a AREF sea de 1.5 Volts.
Para lograr esto, el arduino utiliza una resistencia interna de 32 k como protección
que tendrá un efecto en el divisor de tensión. Así, para lograr un voltaje de
aproximadamente 1.5 V aplicando una fuente de voltaje de 2.5 , nuestra resistencia
externa será:

1.5 = 2.5*32/(32+R)

Es decir, R = 74.67 kohms = 75 kohms para valores comerciales. Otra idea sería
utilizar un diodo zener que brinde un voltaje de referencia de 1.5 V. Con esto
entonces tendríamos escalones equivalentes a 1.46 mV, es decir hemos reducido
casi 3 veces el valor de los escalones teniendo una mejor precisión en nuestras
medidas ya que los cambios de temperatura son bastantes lentos.
Para obtener el valor de 1.46 mV utilizamos la fórmula del escalón o de resolución:
Resolución = Vi/2^n
1.46 mV = 1.5/1024

Espero que este artículos les haya servido para entender un poco más sobre el
AREF y para qué sirve.

Adquisición de datos con Arduino I: Tiempo de muestreo y Resolución

En la mayoría de proyectos que realizamos con Arduino necesitamos que la


placa conozca magnitudes del mundo real, como pueden ser de luz o
temperatura, para que esta active una serie de actuadores, como pueden
ser motores o leds. Para ello las placas de Arduino cuentan con entradas
analógicas con las que, a través, de sensores, medimos dichas magnitudes.

Las dudas vienen, cuando nos planteamos que un ordenador o


microcontrolador en este caso, es un sistema digital y las magnitudes que
deseamos medir son analógicas, por ello necesitamos un sistema que pase
de analógico a digital, el cual llamaremos ADC (Analog digital coverter).
Como es lógico Arduino cuenta con un ADC.

Este conversor ADC va conectado a un multiplexor, para que así, con uno
solo de estos podamos tener varías entradas, como es en el caso de las
placas Arduino que normalmente cuenta con 6 de estas. La Arduino
MEGA en cambio cuenta con 16 entradas analógicas.

El tiempo de muestreo, es el tiempo que transcurres entre dos mediciones


consecutivas, es fundamental para la adquisición de datos y se suele
expresar en frecuencia. Siempre que midamos un sistema como puede ser
el sonido, necesitamos que nuestra frecuencia de muestro sea superior a la
frecuencia del sistema, de no ser así, la representación que obtengamos con
nuestro muestreo, del sistema, no será correcta.

A continuación, haremos un programa con Arduino para calcular el tiempo


de muestreo que tiene nuestra placa. Para este ejemplo solo requerimos de
una placa Arduino y el código será el siguiente:

void setup(){

Serial.begin(9600);
muestreo();

void loop(){
}

void muestreo(){

unsigned long time1=0;


unsigned long time=0;
Serial.println("*************************");
Serial.println("ENSAYO TIEMPO DE MUESTRO:");
Serial.println("*************************");
for(byte i =0; i<4; i++){
time1=micros();
int A=analogRead(A0);
time=micros()-time1;
Serial.print(" Muestra: ");
Serial.print(i+1);
Serial.print(" Tiempo: ");
Serial.println(time);
}

Activando el serial monitor podremos ver los resultados de nuestro


experimento:

Excepto en la primera medida, las demás tiene un tiempo de muestreo de


112 micro segundos, lo que equivale a una frecuencia de muestreo de 8.928
kHz, podemos tomar por valido ya que estoy utilizando una placa Arduino
UNO. A demás debemos tener en cuenta una pequeña perdida de tiempo
que tenemos al guardar y calcular las variables time1 y time.

Otro factor a tener en cuenta del ADC es su resolución, para ello hablamos
de los bits de resoluciónque tiene, los bits no permiten hacer
combinaciones, cuantos mas tengamos mayor numero de combinaciones
podremos hacer, cada una de estas combinaciones muestra una medida del
sistema analógico, la cantidad de medidas que tenemos serán 2 elevado al
numero de bits de resolución. Puesto que Arduino UNO, en mi caso, tiene
un ADC de 10 bits de resolución tendrá 1024 combinaciones. La
placa Arduino DUE por ejemplo cuenta con un ADC de 12 bits
(4096 combinaciones).
Pero hay un segundo factor que interviene en la resolución, es el rango de
medida, El rango de Voltae de las placas Arduino por defecto es de 5v o
3.3v. Con esto sabemos que en voltios tenemos una resolución igual a;

A continuación haremos un ejemplo con Arduino de la resolución


midiendo el voltaje en un potenciómetro, iremos girando las manecilla del
potenciómetro y veremos que conversión da el ADC y a que corresponde
en voltaje. Comprobaremos a demás que el paso calculado antes de
4.88mV es correcto.

El código que utilizaremos es el siguiente:

int contador;

void setup(){

contador=1;
Serial.begin(9600);
Serial.println("*****************");
Serial.println("ENSAYO RESOLUCION");
Serial.println("*****************");
}

void loop(){

muestreo();
contador++;
}

void muestreo(){

int A=analogRead(A0);
float B= float(A)*5/1023;
Serial.print(" Muestra: ");
Serial.print(contador);
Serial.print(" Medida Digital: ");
Serial.print(A);
Serial.print(" Medida Analogica: ");
Serial.println(B, 5);

delay(1000);
}

Una vez compilado, abrimos el serial monitor y comenzamos a rotar el


potenciómetro para ver que sucede, si ha sido montado correctamente, os
saldrá lo siguiente:

A partir de estos datos reales podemos conocer el resolución


tenemos cuando trabajamos en el rango de voltaje de 0 a 5v, para ello
cogemos dos muestras cuales quieras, por ejemplo la 21 y la 22 y hacemos
lo siguiente:

La resolución medida ha cuadrado con la teórica.


//

//

En ocasiones, utilizaremos sensores cuyo rango de voltaje no será igual a


[0, 5v]. En primer lugar, tenemos que tener en cuenta, que no debemos
introducir en la placa Arduino voltajes mayores de 5v o 3.3v, partiendo de
esto podemos cambiar el límite superior del rango de voltaje. De
manera interna o externa:

La manera interna de cambiarlo, es utilizando sowftware únicamente, para


ello utilizaremos la función analogReference(). Esta función nos permitirá
cambiar el límite superior del rango de voltaje, en la placa Arduino
UNO por ejemplo, si introducimos como parámetro INTERNAL el límite
de voltaje superior será de 1.1v. En la placa Arduino mega podemos
introducir como parámetro INTERNAL1V1 y INTERNAL2V56 siendo el
nuevo límite 1.1v y 2.56v respectivamente.

A continuación haremos un nuevo ejemplo análogo al anterior, con una


placa Arduino utilizando la función interna analogReference para que su
voltaje de referencia sea 1.1v. Para alimentar el potenciómetro
requeriremos una fuente de 1.1v, para crearla utilizaremos un divisor de
tensión y un seguidos de tensión:

Una vez montado cargamos el siguiente programa, para verificar que


funciona correctamente:
int contador;

void setup(){
analogReference(INTERNAL);
contador=1;
Serial.begin(9600);
Serial.println("******************");
Serial.println("ENSAYO RESOLUCION");
Serial.println("REFERENCIA INTERNA");
Serial.println("******************");
}

void loop(){

muestreo();
contador++;
}

void muestreo(){

int A=analogRead(A0);
float B= float(A)*1.1/1023;
Serial.print(" Muestra: ");
Serial.print(contador);
Serial.print(" Medida Digital: ");
Serial.print(A);
Serial.print(" Medida Analogica: ");
Serial.println(B, 5);

delay(1000);
}
Como hicimos antes podemos tomar dos muestras, la 19 y 20, por ejemplo
y calcular la nueva resolución que tenemos:

Conseguimos pues una resolución casi 5 veces mayor que la anterior.

Finalmente, queda la manera externa para cambiar el voltaje de referencia,


para ello utilizaremos el pin AREF. El funcionamiento de este pin es
sencillo el voltaje que introduzcamos por el, será la nueva referencia, pero
cuidado, dicho voltaje debe estar entre entre 1.1v y 5v.

Para el siguiente ensayo utilizaremos la configuración


anterior, generaremos con el divisor de tensión y el seguidor de
tensión 2.5v, y los llevaremos al pin AREF, el resto lo dejaremos igual.
Respecto al código utilizaremos el siguientes:

int contador;

void setup(){
analogReference(EXTERNAL);
contador=1;
Serial.begin(9600);
Serial.println("******************");
Serial.println("ENSAYO RESOLUCION");
Serial.println("REFERENCIA EXTERNA");
Serial.println("******************");
}

void loop(){

muestreo();
contador++;
}

void muestreo(){

int A=analogRead(A0);
float B= float(A)*2.5/1023;
Serial.print(" Muestra: ");
Serial.print(contador);
Serial.print(" Medida Digital: ");
Serial.print(A);
Serial.print(" Medida Analogica: ");
Serial.println(B, 5);

delay(1000);
}

Activamos el Serial monitor y vemos los resultados:


Con esto damos por terminado el primer tutorial de adquisión de datos
con Arduino. Tened siempre en cuenta el tiempo de muestreo que tenéis y
tratad siempre una buena resolución, ajustada al rango de voltaje que
trabaja vuestro sensor. Hasta otra.

También podría gustarte