🛠 Registres AVR et interruption timer : échantillonner le multiplexeur

Arduino Esplora — Fiche de carte · avance · Schéma : IMG-esplora-avance-1-esplora-registres-interruption-timer.svg — Schéma fonctionnel du multiplexeur 4 vers 1 de l'Esplora : broches A0-A3 en adresse, A4 en ADC commun, canaux boutons/slider/lumière/température/son, avec le timer TCNT2 en horloge.

Objectifs

Comprendre — puis court-circuiter — la bibliothèque Esplora. Les 10 canaux multiplexés (boutons, slider, lumière, température, micro, TinkerKit A/B, joystick) partagent l'entrée ADC A4, sélectionnés par les broches d'adresse A0–A3 (MAX_CHANNELS=13 dans Esplora.cpp). Ce tutoriel manipule les registres AVR directement (DDRB/PORTB, ADMUX, ADCSRA) et déclenche l'échantillonnage par interruption de comparaison du Timer2, pour un balayage périodique précis sans delay.

Matériel

Code complet

/* Balayage periodique du multiplexeur de l'Esplora SANS la bibliotheque,
   pilote par interruption de comparaison du Timer2 (~1 kHz).
   Adresses physiques d'après 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, entrée 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]);
  }
}

Vérification attendue

Le moniteur série affiche quatre colonnes qui varient quand vous manipulez slider, lumière, température et micro — sans jamais appeler la bibliothèque Esplora (vérifiez avec le gestionnaire de bibliothèques qu'elle n'est pas compilée). La régularité du balayage est garantie par le Timer2 : débranchez le moniteur, l'échantillonnage continue à ~1 kHz.

Erreurs fréquentes

  1. Écrire sur PORTB sans masque : les bits 4–5 de PORTB portent aussi A4/A5 (accéléromètre) ; toujours faire MUX_PORT = (MUX_PORT & 0xF0) | canal.
  2. Oublier le temps d'établissement : après changement de canal, ~50 µs sont nécessaires avant conversion ; un Timer2 trop rapide (plusieurs dizaines de kHz) mélange les canaux.
  3. ADCL/ADCH dans le mauvais ordre : lire ADCH avant ADCL corrompt la dernière conversion ; lire ADCL d'abord verrouille les registres.
  4. Conflit avec la bibliothèque Servo ou tone : Timer2 est aussi utilisé par tone sur l'AVR ; ce croquis n'utilise pas tone, mais si vous l'ajoutez, choisissez Timer1 ou Timer0.
  5. Confondre canaux logiques de la bibliothèque et canaux ADC : le numéro envoyé sur A0–A3 n'est pas le MUX=3 bits d'ADMUX ; le canal ADC reste toujours A4.

Autres tutoriels pour cette carte

Exemples de code pour cette carte

← Retour à la fiche 🛠 Tous les tutoriels