🛠 Registres AVR et interruption timer : échantillonner le multiplexeur
Objetivos
Comprender — y luego anular — la biblioteca Esplora. Los 10 canales multiplexados (botones, deslizador, luz, temperatura, micrófono, TinkerKit A/B, joystick) comparten la entrada ADC A4, seleccionados mediante los pines de dirección A0–A3 (MAX_CHANNELS=13 en Esplora.cpp). Este tutorial manipula directamente los registros AVR (DDRB/PORTB, ADMUX, ADCSRA) y dispara el muestreo mediante una interrupción de comparación del Timer2, para lograr un barrido periódico preciso sin usar delay.
Material
- Arduino Esplora + cable micro-USB.
- Conceptos: esquema de pines del puerto B del ATmega32u4 (PB0–PB5 = A0–A5... atención al mapeo analógico de Arduino), hoja de datos del ATmega16U4/32U4.
- Ningún componente externo.
Código completo
/* Balayage periodique du multiplexeur de l'Esplora SANS la bibliotheque,
pilote par interruption de comparaison du Timer2 (~1 kHz).
Adresses physiques d'apres Esplora.cpp : A0..A3 = adresse, A4 = commun.
Sur l'ATmega32u4, A0..A4 correspondent a PORTB bit0..bit4. */
#include <avr/io.h>
#include <avr/interrupt.h>
#define MUX_PORT PORTB
#define MUX_DDR DDRB
#define ADC_COM 4 // A4 -> ADMUX MUX = 4
volatile uint16_t mesures[6]; // boutons non mesures ici : canaux analogiques
volatile uint8_t canal = 0;
ISR(TIMER2_COMPA_vect) {
// 1) selection du canal sur A0..A3
MUX_PORT = (MUX_PORT & 0xF0) | (canal & 0x0F);
// 2) lancement d'une conversion sur A4 (ADMUX deja configure)
ADCSRA |= (1 << ADSC);
}
ISR(ADC_vect) {
mesures[canal] = ADCL | (ADCH << 8); // lecture 10 bits
canal = (canal + 1) % 6; // cycle : 4=slider? voir note
}
void setup {
Serial.begin(9600);
MUX_DDR |= 0x0F; // A0..A3 en sortie
ADMUX = (1 << REFS0) | ADC_COM; // ref 5V, entree A4
ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1); // /64
// Timer2 en CTC, comparaison ~1 kHz (16 MHz / 1024 / 16)
TCCR2A = (1 << WGM21);
TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20);
OCR2A = 124;
TIMSK2 = (1 << OCIE2A);
sei;
}
void loop {
static uint32_t t = 0;
if (millis - t > 250) {
t = millis;
// Canaux physiques : dependront du cablage exact du mux (voir Esplora.cpp)
Serial.print("c4="); Serial.print(mesures[4]);
Serial.print(" c5="); Serial.print(mesures[5]);
Serial.print(" c6="); Serial.print(mesures[6]);
Serial.print(" c7="); Serial.println(mesures[7]);
}
}
> NO VERIFICADO: la tabla de correspondencia exacta número de canal → sensor en el código sin librería depende de las constantes internas de Esplora.cpp (CH_SLIDER, CH_LIGHT, etc.); verifíquelos en el código fuente de la biblioteca antes de interpretar sus mediciones.
Verificación esperada
El monitor serie muestra cuatro columnas que varían cuando manipula el deslizador, la luz, la temperatura y el micrófono — sin llamar nunca a la biblioteca Esplora (verifique con el gestor de bibliotecas que no está compilada). La regularidad del barrido está garantizada por el Timer2: si desconecta el monitor, el muestreo continúa a ~1 kHz.
Errores frecuentes
- Escribir en PORTB sin máscara: los bits 4–5 de PORTB también llevan A4/A5 (acelerómetro); siempre haga
MUX_PORT = (MUX_PORT & 0xF0) | canal. - Olvidar el tiempo de estabilización: después de cambiar de canal, se necesitan ~50 µs antes de la conversión; un Timer2 demasiado rápido (varias decenas de kHz) mezcla los canales.
- ADCL/ADCH en el orden incorrecto: leer ADCH antes que ADCL corrompe la última conversión; leer ADCL primero bloquea los registros.
- Conflicto con la biblioteca Servo o tone: Timer2 también es utilizado por
toneen el AVR; este sketch no usa tone, pero si lo añade, elija Timer1 o Timer0. - Confundir canales lógicos de la biblioteca y canales ADC: el número enviado a A0–A3 no es el MUX de 3 bits de ADMUX; el canal ADC sigue siendo siempre A4.
Otros tutoriales para esta placa
Ejemplos de código para esta placa
joystick-couleur.inoArduinojeu-boutons.inoArduinoslider-luminosite.inoArduinothermometre-couleur.inoArduinosonometre.inoArduinoaccelerometre-tilt.inoArduino