sommeil-watchdog.ino
Le Nano classique sait descendre à quelques microampères : ce programme dort en PWR_DOWN et se réveille toutes les 8 secondes via le watchdog, sans jamais réinitialiser le programme. Le patron des capteurs sur pile qui durent des mois.
Matériel requis
Un Arduino Nano classique (ATmega328P à 16 MHz, brochage DIL 30 broches sur breadboard, USB mini-B, logique 5 V, broche RESET en bas à gauche). Arduino Nano (de préférence avec le régulateur sobre — les clones chinois varient), LED débranchée de préférence.
Câblage
Retirez la LED d'alimentation ou alimentez directement en 3,3 V pour viser le courant minimal ; sinon le régulateur domine la consommation.
Fonctionnement
Le watchdog configuré en mode interruption (WDIE) génère WDT_vect qui réveille le CPU ; SLEEP_MODE_PWR_DOWN coupe horloges et SRAM. Le réveil reprend juste après sleep_cpu().
Exécution
Dans l'IDE Arduino, sélectionnez la carte Arduino Nano et le processeur ATmega328P, choisissez le port série puis téléversez. L'alimentation 5 V de la carte convient aux capteurs 5 V ; sinon utiliser le 3,3 V des broches adaptées.
Variantes
Réveillez aussi sur une broche (PCINT sur un bouton) pour un réveil événementiel, ou coupez l'ADC avec power_adc_disable() entre deux mesures.
sommeil-watchdog.ino
// Nano en veille profonde reveillee par le watchdog (~8 s).
// Courant ~12 uA en sleep contre ~15 mA eveille : la cle sur pile.
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>
volatile bool reveille = false;
ISR(WDT_vect) { // le watchdog reveille sans reinitialiser
reveille = true;
}
void setup() {
Serial.begin(9600);
MCUSR &= ~(1 << WDRF); // efface la cause reinitialisation
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = (1 << WDP1) | (1 << WDP0) // 8 s environ
| (1 << WDIE); // mode interruption seule
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // veille la plus profonde
}
void loop() {
reveille = false;
mesure();
sleep_enable();
sleep_cpu(); // coupe tout jusqu'au watchdog
sleep_disable();
}
void mesure() {
Serial.begin(9600);
Serial.println(F("reveil : mesure"));
// ... lecture capteur, envoi serie ou radio ...
Serial.end();
// attendre que le TX en cours se vide avant de dormir
while (UCSR0A & (1 << TXC0)) {}
UCSR0A = (1 << TXC0);
}