El ADC (Analog to Digital Converter)
convierte un valor de tensión analógico en su
equivalente valor digital expresado en unos y ceros en uno o varios
registros del microcontrolador. El ATMEGA 1280 dispone de un ADC de 10
bits, con una tensión de referencia de 5V podemos obtener una
resolución de 5/1024 V, es decir el ADC detecta cambios en la
señal analógica cada 4.88 mV y por tanto el
número en binario del registro o registros donde guardemos la
conversión representará incrementos de este valor de
tensión (si vale 500 pues la tensión de entrada sera
500*4.88 mV).
Este micro tiene hasta 16 entradas multiplexadas al ADC, con bastante
opciones y configuraciones, en este caso sólo se van a ver las
necesarias para hacer una conversión analógica digital
simple desde una V de referencia de 5V comparada con tierra (single
ended mode en el datasheet) que es lo que usaremos en el proyecto.
El pin de alimentación es AVcc que no debe tener una diferencia
de mas de 0.3V con Vcc, lo normal es conectarlo a Vcc y así
viene en la placa del Arduino Mega. El ADC toma una muestra de la
tensión de entrada y lo mantiene contante mientras se realiza la
conversión . Como referencia de voltaje podemos usar una externa
en la patilla AREF, nuestra resolución será
Vref/número de bits de ADC, y una vez alcanzada esta
tensión en el pin de entrada tendremos el valor máximo
((Vref/2^n)*(-1+2^n) n=número bits adc) en el registro digital
del ADC. También nos permite seleccionar un voltaje de
referencia interno de 1.1V ,2.56V o AVcc, en este caso no debemos
conectar nada a AREF.
El ADC para su funcionamiento necesita una señal de reloj con
una frecuencia comprendida entre 50 KHz y 200 KHz para una
resolución de 10 bits, si menos resolución es requerida
se le puede proporcionar hasta una frecuencia de 1MHz para realizar las
conversiones en menos tiempo, para proporcionar esta señal de
reloj el ADC cuenta con un prescaler que genera la señal
requerida a patir de la señal de reloj. La señal de reloj
de nuestro micro es el cristal externo y éste es de 16 MHz, para
generar una señal de reloj válida para el ADC a
través del prescaler tendremos que usar los 7 bits (128 en
decimal) lo que nos proporcionara una frecuencia de reloj de ADC de
16MHz/128 = 125 KHz.
Una conversión analógica digital requiere de 13 ciclos de
reloj del ADC que con un prescaler de 128 serían 1664 ciclos de
reloj (por lo que tenemos la opción de habilitar una
interrupción que nos avise de cuando se ha finalizado esta
conversión), la primera conversión que realizamos
tras activar el módulo del ADC ésta requiere de 25 ciclos
de reloj ya que tiene que inicializar todo el hard.
Todo esto para circuitos con una impedancia de salida de 10K o menos,
para circuitos con una impedancia mayor el tiempo de muestreo
dependerá del tiempo que tarde en cargarse el condensador que
retiene la magnitud de la señal a través de esa
impedancia. Señales con una frecuencia mayor que Fadc/2
(Nyquist) deben de ser evitadas ya que se distorsionan.
Circuito de entrada, muestreo y mantiene la señal durante la conversión.
Registros ADC.
Los registros del ADC en el microcontrolador son los siguientes:
Los bits 7 y 6 REFS1 y REFS0: se encargan de seleccionar el voltaje de
referencia del ADC, si un voltaje de referencia externo es aplicado en
AREF no se pueden usar los voltajes de referencia internos.
Cuando se selecciona las referencias internas se recomienda poner un condensador en el pin de AREF a tierra para eliminar ruido.
Bit 5 ADLAR (ADC Left Adjust Result): los 10 bits de la
conversión del adc se deben de guardar en dos registros de 8
bits destinados a éste fin, que son los máximos bits que
podemos tener por dirección de memoria. Poniendo 0 como viene
por defecto en este bit tenemos 8 bits en el registro de menor peso y 2
bits en el de mayor peso, para sacar el resultado debemos leer los dos
registro y valor máximo será 3FF (1024). Poniendolo a uno
tenemos 8 bits en el registro de mayor peso y dos en el de menor, esto
lo hacemos cuando no necesitamos una precisión de 10 bits,
leemos sólo los 8 bits de mayor peso en un sólo registro
obteniendo una resolución de Vref/256, más que suficiente
para la mayoría de los casos y de esta forma evitamos tener que
leer más de un registro en el programa.
Bits 4:0 MUX4:0: estos bits se encargan (junto a otro bit MUX5 en otro
registro) de seleccionar el pin de nuestro microcontrolador cuya
entrada está conectada al ADC, tenemos 16 pines con la
opción de ADC, aquí seleccionamos cual de ellos estamos
leyendo. Si los bits son cambiados mientras se realiza una
conversión el cambio no tiene efecto hasta que ésta
esté completa.
Bit Mux5: junto a los 4 anteriores selecciona que entradas y que
funciones de la electrónica están seleccionadas. Siempre
debemos cambiar de canal antes de iniciar la conversión, si no
el resultado será el del canal anterior
Bit 2:0 ADTS2:0: seleccionan la fuente de disparo automático del ADC.
En nuestro caso nos interesan las opciones de la primera columna (single ended input) que son las que vamos a utilizar.
Bit 7 ADEN (ADC Enable): enciende (1) y apaga (0) el adc.
Bit 6 ADSC (ADC Start Conversion): cuando estamos "in single
conversion mode" poniendo este bit a 1 iniciamos cada
conversión, este bit está a 1 mientras se realiza la
conversión y se pone a cero cuando se finaliza. En "Free running
mode" ponemos este bit a uno para iniciar sucesivas conversiones,
escribir un cero en este bit no tiene efecto. La conversión
también se puede iniciar de forma automática disparada
desde varias fuentes seleccionables. Para seleccionar el Free Running
Mode debemos poner un 1 en ADATE y 000 en sus bits de selección
(explicado más abajo).
Bit 5 ADATE (ADC Auto Trigger Enable): cuando está a 1 el
disparo automático del adc se encuentra habilitado y éste
iniciara una conversión cuando una de las fuentes seleccionada
le proporciones un flanco de subida en su entrada. Si un flanco de
subida ocurre cuando se está realizando una conversión
éste es ignorado. La fuente es seleccionada mediante los bits
ADTS2:0 de ADCRSB Si cambiamos de una fuente con su entrada a cero a
una fuente con entrada con la entrada a 1 tenemos un flanco de subida y
la conversión se inicia.
Bit 4 ADIF (ADC Interrupt Flag): este bit se pone a uno cuando la
conversión se ha realizado y los registros donde se guarda el
resultado han sido actualizados, mediante este bit y habilitando su
interrupción en los registros correspondientes podemos iniciar
la conversión e irnos a hacer otras cosas, así no tenemos
que comprobar por soft si ya ha finalizado la conversión, ya nos
avisará la interrupción.
Bit 3 ADIE (ADC Interruptio Enable): habilita la interrupción del ADC indicada por el bit anterior.
Bits 2:0 ADPS2:0: (ADC Prescaler Select Bits): seleccionan por cuanto
se va a dividir la señal de reloj del micro para generar la
señal de reloj del ADC que debe estar comprendida entre 50 Khz y
200 KHz para 10 bits de resolución.
Estos son los registros donde se almacena el resultado de la
conversión, ADCH es el de mayor peso y mediante ADLAR
seleccionamos si vamos a usar una resolución de 8 ó 10
bits, explicado más arriba. Con ADLAR=0 ADCL se debe de leer
primero y luego ADCH, el resultado de una conversión no es
actualizado si hemos leído ADCL hasta que no hayamos
leído ADCH.
En estos registros se deshabilitan la entrada digital del pin
escribiendo un 1 en el bit correspondiente, cuando vamos a usar la
entrada como analógica y la entrada digital no es necesaria se
debe escribir un uno en el registro ya que de esta forma reducimos el
consumo de corriente del micro.
ADC en C.
En el AVR-gcc no tenemos ninguna librería específica para
usar el ADC, la única que tendremos que añadir al
programa es el avr/interrupt.h si se va a usar la interrupción
del ADC.
Se va a realizar un programa sencillo para leer un potenciometro que
forma un divisor de tensión y sacar el valor de la lectura por
el LCD, se compara con el valor leído en el polímetro
para comprobar su correcto funcionamiento. El ADC se configura en Free
Running Mode, la resolución es de 8 bits que para el
ejemplo es suficiente.
lcd_escribir_c(unidades | 0b00110000); lcd_escribir_c('.'); lcd_escribir_c(decimas | 0b00110000); lcd_escribir_c(centesimas | 0b00110000); lcd_escribir_c('V'); }
Se configura el ADC de forma que éste realiza conversiones de
manera continua y guarda su salida en el registro ADCH que es el
que usamos en las distintas funciones, hubiese sido más
acertado crear un char copia_ADCH = ADCH; para operar siempre con el
mismo valor de ADCH en cada ciclo del búcle, por si entre
función y función cambia el valor de ADCH, pero bueno
para el ejemplo vale de esta forma que ya he subido el video y no lo
cambio, se puede ver como alguna vez oscila alguna línea
mientras que otra no y ésto es debido a lo anterior.
En la pantalla se representa el valor del registro ADCH en la primera
línea binario, en la segunda línea su valor pasado a
decimal, en la tercera el caracter del LCD que escribiriamos con ese
valor (no tiene nada que ver pero queda bien...) y por último el
valor de tensión real a la entrada del adc que es el que nos
interesa y comparamos con el polímetro para saber que estamos
realizando la conversión de manera correcta, la
resolución es de 5/256 V, por lo que en la cuarta línea
tenemos el valor decimal de ADCH multiplicado por 0.0195V.
El resto de funciones sirven para sacar el registro ADCH a la pantalla del LCD en binario, decimal y tensión real.
Con ésto y las dos actualizaciones anteriores (LCD e
Interrupciones externas) ya se puede empezar con el primer
módulo del hexápodo, el interfaz físico, que
consta de un LCD, 3 pulsadores y un potenciometro y sirve para que el
hexápodo pueda comunicarse con una persona de manera
autónoma sin la necesidad de un PC por ejemplo. Por lo que el
siguiente paso es meter el código de esta actualización y
las dos últimas en su cabecera todo junto y crear el esqueleto
del programa inicial de desarrollo para el hexápodo que se
usará para ir añadiendo módulos y probar su
correcto funcionamiento. Dotar a un proyecto de un LCD es algo muy
útil.