sommeil-watchdog.ino
El Nano clásico sabe bajar a unos microamperios: este programa duerme en PWR_DOWN y despierta cada 8 segundos vía el watchdog, sin reiniciar nunca el programa. El patrón de sensores a pila que duran meses.
Hardware
Un Arduino Nano clásico (ATmega328P a 16 MHz, formato DIL de 30 patillas para breadboard, USB mini-B, lógica de 5 V, pin RESET abajo a la izquierda). Arduino Nano (mejor con el regulador sobrio; los clones chinos varían), LED mejor desconectada.
Cableado
Retira el LED de alimentación o alimenta directo a 3,3 V para buscar la corriente mínima; si no, el regulador domina el consumo.
Funcionamiento
El watchdog en modo interrupción (WDIE) genera WDT_vect que despierta la CPU; SLEEP_MODE_PWR_DOWN corta relojes y SRAM. El despertar continúa justo tras sleep_cpu().
Ejecución
En el IDE de Arduino, selecciona la placa Arduino Nano y el procesador ATmega328P, elige el puerto serie y carga. El rail de 5 V de la placa conviene a sensores de 5 V; si no, usa 3,3 V en pines compatibles.
Variantes
Despierta también con un pin (PCINT en un botón) para despertar por evento, o corta el ADC con power_adc_disable() entre medidas.
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);
}