🛠 Registres AVR et interruption timer : échantillonner le multiplexeur
Objectives
Understand — then bypass — the Esplora library. The 10 multiplexed channels (buttons, slider, light, temperature, microphone, TinkerKit A/B, joystick) share the ADC input A4, selected by address pins A0–A3 (MAX_CHANNELS=13 in Esplora.cpp). This tutorial manipulates AVR registers directly (DDRB/PORTB, ADMUX, ADCSRA) and triggers sampling via Timer2 compare match interrupts, for precise periodic scanning without delay.
Hardware
- Arduino Esplora + micro-USB cable.
- Knowledge: ATmega32u4 Port B pinout (PB0–PB5 = A0–A5... watch out for the Arduino analog mapping), ATmega16U4/32U4 datasheet.
- No external components.
Full Code
/* 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]);
}
}
Expected Verification
The serial monitor displays four columns that vary when you manipulate the slider, light, temperature, and microphone — without ever calling the Esplora library (verify with the library manager that it is not compiled). The regularity of the scan is guaranteed by Timer2: disconnect the monitor, and sampling continues at ~1 kHz.
Common Errors
- Writing to PORTB without a mask: Bits 4–5 of PORTB also carry A4/A5 (accelerometer); always use
MUX_PORT = (MUX_PORT & 0xF0) | channel. - Forgetting the settling time: After changing channels, ~50 µs are required before conversion; a Timer2 that is too fast (tens of kHz) mixes up channels.
- Reading ADCL/ADCH in the wrong order: Reading ADCH before ADCL corrupts the last conversion; reading ADCL first locks the registers.
- Conflict with the Servo library or tone: Timer2 is also used by
toneon the AVR; this sketch does not use tone, but if you add it, choose Timer1 or Timer0. - Confusing library logical channels with ADC channels: The number sent to A0–A3 is not the 3-bit MUX value of ADMUX; the ADC channel always remains A4.
Other tutorials for this board
Code examples for this board
joystick-couleur.inoArduinojeu-boutons.inoArduinoslider-luminosite.inoArduinothermometre-couleur.inoArduinosonometre.inoArduinoaccelerometre-tilt.inoArduino