26.1: Introducción
- Page ID
- 82444
Así como nos gustaría leer el estado de los interruptores simples de encendido/apagado, también necesitamos leer datos continuamente variables (es decir, analógicos). Por lo general, esto significa el voltaje de salida causado por alguna forma de sensor como un sensor de temperatura, sensor de fuerza, sensor de luz, etc. Muy a menudo se colocan dispositivos pasivos simples como celdas CdS o FSR en una red de puente resistivo, cuyo voltaje de salida se desplazará con los cambios en el ambiente. Una aplicación aún más sencilla sería el uso de un potenciómetro conectado a una fuente de voltaje fijo. La posición del bote sería controlada por el usuario y podría representar un ajuste de casi cualquier parámetro concebible como volumen, brillo, retardo de tiempo, frecuencia, etc. Para leer cantidades analógicas, el ATMega 328P contiene un solo convertidor analógico a digital de 10 bits multiplexado a través de seis entradas canales. En la placa Arduino Uno, las entradas a estos ADC se encuentran en los pines etiquetados A0 a A5. El entorno de desarrollo de Arduino contiene dos funciones útiles para acceder a tesis, a saber, analogRead ()
y AnalogReference ()
. Las descripciones de las funciones en línea se repiten a continuación:
AnalogRead () 1
Descripción
Lee el valor del pin analógico especificado. La placa Arduino contiene un convertidor analógico a digital de 10 bits de 6 canales (8 canales en el Mini y Nano, 16 en el Mega). Esto significa que mapeará voltajes de entrada entre 0 y 5 voltios en valores enteros entre 0 y 1023. Esto produce una resolución entre lecturas de: 5 voltios/1024 unidades o, 0.0049 voltios (4.9 mV) por unidad. El rango de entrada y la resolución se pueden cambiar usando AnalogReference ().
Se necesitan aproximadamente 100 microsegundos (0.0001 s) para leer una entrada analógica, por lo que la velocidad máxima de lectura es de aproximadamente 10,000 veces por segundo.
Sintaxis
AnalogRead (pin)
Parámetros
pin: el número del pin de entrada analógica para leer (0 a 5 en la mayoría de las placas, 0 a 7 en el Mini y Nano, 0 a 15 en el Mega)
Devoluciones
int
(0 a 1023)
Nota
Si el pin de entrada analógica no está conectado a nada, el valor devuelto por analogRead ()
fluctuará en función de una serie de factores (por ejemplo, los valores de las otras entradas analógicas, qué tan cerca está su mano de la placa, etc.).
Descripción
Configura el voltaje de referencia utilizado para la entrada analógica (es decir, el valor utilizado como la parte superior del rango de entrada). Las opciones son:
- DEFAULT: la referencia analógica predeterminada de 5 voltios (en placas Arduino de 5V) o 3.3 voltios (en placas Arduino de 3.3 V)
- INTERNO: una referencia incorporada, igual a 1.1 voltios en el ATmega168 o ATmega328 y 2.56 voltios en el ATmega8 (no disponible en el Arduino Mega)
- INTERNAL1V1: una referencia incorporada de 1.1V (solo Arduino Mega)
- INTERNAL2V56: una referencia incorporada de 2.56V (solo Arduino Mega)
- EXTERNO: se utiliza como referencia el voltaje aplicado al pin AREF (0 a 5V solamente).
Sintaxis
AnalogReference (tipo)
Parámetros
type: qué tipo de referencia usar (DEFAULT, INTERNAL, INTERNAL1V1, INTERNAL2V56, o EXTERNO).
Devoluciones
Ninguno.
Nota
Después de cambiar la referencia analógica, las primeras lecturas de AnalogRead ()
pueden no ser precisas.
Advertencia
¡No uses nada menos de 0V o más de 5V para el voltaje de referencia externo en el pin AREF! Si está utilizando una referencia externa en el pin AREF, debe establecer la referencia analógica en EXTERNAL antes de llamar a analogRead (). De lo contrario, cortocircuitará juntos el voltaje de referencia activo (generado internamente) y el pin AREF
, posiblemente dañando el microcontrolador en su placa Arduino.
Alternativamente, puede conectar el voltaje de referencia externo al pin AREF
a través de una resistencia de 5K, lo que le permite cambiar entre voltajes de referencia externos e internos. Tenga en cuenta que la resistencia alterará el voltaje que se usa como referencia porque hay una resistencia interna de 32K en el pin AREF
. Los dos actúan como un divisor de voltaje, así, por ejemplo, 2.5V aplicados a través de la resistencia producirán 2.5 * 32/(32+5) = ~2.2V en el pin AREF
.
La función analogRead ()
se utiliza mejor como una “instantánea” de conversión única. Esto es bueno para una interfaz de usuario simple y aplicaciones básicas de sensores. En términos generales, analogReference ()
se llama una vez durante la fase de configuración e inicialización del programa. Además, a menos que haya una razón convincente para hacer lo contrario, el modo predeterminado es el mejor lugar para comenzar. Esto producirá un rango de entrada de pico a pico de 5 voltios con una resolución de bits de poco menos de 4.9 milivoltios (5/1024). Es importante señalar que este rango va de 0 voltios a 5 voltios, no −2.5 voltios a +2.5 voltios. Dependiendo de la amplitud y rango de frecuencia de la señal del sensor, es posible que se requiera algún circuito de procesamiento de entrada para aplicar un desplazamiento de CC, amplificar o reducir la intensidad de la señal, filtrar los extremos de frecuencia, etc.
El código para AnalogReference ()
es casi tan simple como se pone. Simplemente establece (y oculta) una variable global a la que accederá la función analogRead ()
:
uint8_t analog_reference = DEFAULT; void analogReference(uint8_t mode) { analog_reference = mode; }
La función analogRead ()
es un poco más interesante (en realidad, 10 bits más interesantes). Del capítulo anterior vimos que existen varios registros asociados al sistema ADC. Para la operación de conversión única, los registros importantes incluyen ADCSRA
(registro de estado y control ADC A) y ADMUX
(registro de selección de multiplexor ADC). Los bits de registro se repiten a continuación para mayor comodidad:
Registrar | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|---|---|---|
ADCSRA |
ADEN |
ADSC |
ADATE |
ADIF |
ADIE |
ADPS2 |
ADPS1 |
ADPS0 |
ADMUX |
REFS1 |
REFS0 |
ADLAR |
- | MUX3 |
MUX2 |
MUX1 |
MUX0 |
También recuerde que los registros ADCH
y ADCL
contienen los bytes alto y bajo del resultado, respectivamente. Para ADCSRA
, la configuración de ADEN
habilita el ADC. Al establecer ADSC
se inicia una conversión. Permanecerá en uno hasta que se complete la conversión, el hardware lo restablecerá a cero. ADIF
y ADIE
se utilizan con un modo basado en interrupciones no discutido aquí. ADATE
significa AD Auto Trigger Enable que permite activar el ADC desde una señal externa (nuevamente, no se discute aquí). AdPSx
son bits pre-escaladores que establecen la velocidad de conversión. Consulte el capítulo anterior para más detalles.
Para ADMUX
, RefSX
establece la fuente de voltaje de referencia donde 00 = usar pin AREF
, 01 = usar VCC
, 10 = reservado, 11 = usar referencia interna de 1.1 voltios. Ajustar ADLAR
a la izquierda ajusta la palabra de 10 bits dentro de los registros de resultados ADCH
y ADCL
(es decir, justifica a la izquierda, dejando los seis bits inferiores sin usar). Borrar este bit deja el resultado justificado correctamente (es decir, los seis bits superiores no se utilizan). Los cuatro bits MUxx seleccionan qué canal de entrada se utiliza para la conversión. Por ejemplo, para leer desde el canal 5, establezca estos bits en el patrón 0101.
Otros registros están disponibles como ADSRB
y ACSR
que son útiles para otros modos de operación. Sin embargo, no son necesarios para el propósito actual.
El código sigue, limpiado para facilitar la lectura. El código original contiene un número considerable de #
ifdef
s por lo que funciona con diferentes microcontroladores.
int analogRead(uint8_t pin) { uint8_t low, high; if (pin >= 14) pin -= 14; // allow for channel or pin numbers // set the analog reference, input pin and clear left-justify (ADLAR) ADMUX = (analog_reference << 6) | (pin & 0x07); // start the conversion sbi(ADCSRA, ADSC); // ADSC is cleared when the conversion finishes while (bit_is_set(ADCSRA, ADSC)); // read low and high bytes of result low = ADCL; high = ADCH; // combine the two bytes return (high << 8) | low; }
Echemos un vistazo más de cerca. Primero, se declaran dos bytes sin signo para contener el contenido de los registros de resultados altos y bajos; luego se traduce el argumento pin. Tenga en cuenta el uso indocumentado de cualquiera de los números de canal o pin. Siempre tenga cuidado al usar funciones indocumentadas.
uint8_t low, high; if (pin >= 14) pin -= 14; // allow for channel or pin numbers
En este punto se establece la referencia (observe cómo el analog_reference
global se desplaza hasta los bits RefSX
). El número de pin es ANDed con 0x07 para seguridad y OR en ADMUX
. Tenga en cuenta que el resultado se justificará a la derecha ya que no se establece ADLAR
.
ADMUX = (analog_reference << 6) | (pin & 0x07);
La conversión se inicia configurando el bit AD Start Conversion. sbi ()
es una macro que reduce a una sola instrucción de “set bit” en el ensamblaje. Luego esperamos hasta que se borre el bit ADSC
, lo que significa que la conversión está completa. El bucle while
se conoce correctamente como un bucle “busy-wait”; el código simplemente “se sienta” en ese bit, verificándolo una y otra vez hasta que finalmente se borre. Esto hace que el bucle salga. Nuevamente, bit_is_set ()
es una macro que devuelve true
si el bit bajo prueba se establece en uno y false
si está claro.
// start the conversion sbi(ADCSRA, ADSC); // ADSC is cleared when the conversion finishes while ( bit_is_set(ADCSRA, ADSC) );
La conversión ya está completa. ADCL
debe leerse primero, ya que al hacerlo bloquea tanto los registros ADCL
como ADCH
hasta que se lea ADCH
. Hacer lo contrario podría resultar en valores espurios. Los dos bytes se combinan entonces en un único resultado entero de 16 bits mediante ORing el byte bajo con el byte alto desplazado a la izquierda. Como los datos en los registros de resultados estaban justificados a la derecha, los seis bits superiores serán ceros en el entero devuelto, resultando en un rango de salida de 0 a 1023.
low = ADCL; high = ADCH; // combine the two bytes return (high << 8) | low;
Dados los valores predeterminados del preescalador y la sobrecarga de llamadas a funciones, la tasa de conversión máxima es de aproximadamente 10 kHz, lo que es perfectamente aceptable para una amplia variedad de usos. La función es bastante básica y sencilla de usar tal cual. Utilice esta función como guía si desea producir datos justificados a la izquierda (set ADLAR
bit) u otras modificaciones simples. Si el tiempo es esencial y los ciclos de máquina no se pueden perder con el bucle de espera ocupado visto anteriormente, una versión basada en interrupciones o una versión de ejecución libre puede ser una mejor opción.