
Lo Sleep Mode, come dice il nome stesso, è una modalità di funzionamento dei microcontrollori a bassissimo consumo di corrente.
È una modalità che viene generalmente usata nei sistemi alimentati a batteria in modo da preservarne la carica per il tempo più lungo possibile.
Il risveglio del microcontrollore può avvenire tramite un reset oppure tramite un interrupt, interno, ad esempio tramite il Watchdog oppure esterno tramite il cambio di stato di un pin.
Vedremo alcuni esempi di uso dello Sleep Mode e risveglio proprio tramite cambio di stato di un pin.
Il circuito che utilizzeremo è molto semplice ed il suo funzionamento è il seguente: ad ogni pressione del pulsante cambierà lo stato del led a bordo della scheda.
Tra un cambio di stato e il successivo il sistema entrerà in Sleep Mode per ridurre la corrente consumata.
Il programma è il seguente:
#include <avr/sleep.h> #include <avr/power.h> const byte LED = 1; // D1 / pin 6 const byte SWITCH = 2; // D2 / pin 7 / PCINT2 volatile byte last_sw_state = HIGH; volatile byte led_state = HIGH; // Interrupt Service Request. Executed when the state of the pin changes ISR(PCINT0_vect) { byte sw_state; sw_state = digitalRead(SWITCH); // or faster: (PINB >> PINB2) & 1 if (last_sw_state==HIGH && sw_state==LOW) { // Falling edge led_state = !led_state; } last_sw_state = sw_state; } void setup() { pinMode (LED, OUTPUT); pinMode (SWITCH, INPUT_PULLUP); cli(); // Disable interrupt // Pin change interrupt PCMSK |= bit (PCINT2); // D2 / pin 7 GIFR |= bit (PCIF); // Clear any outstanding interrupts GIMSK |= bit (PCIE); // Enable pin change interrupts sei(); // Enable interrupt } void loop() { digitalWrite (LED, led_state); enter_sleep (); } void enter_sleep () { // Enter sleep set_sleep_mode(SLEEP_MODE_PWR_DOWN); ADCSRA = 0; // Turn off ADC power_all_disable (); // Power off ADC, Timer 0 and 1, serial interface sleep_enable(); sleep_cpu(); // …zzz // Wake up sleep_disable(); power_all_enable(); // Power everything back on }
Oppure possiamo cambiare la logica di funzionamento e far sì che il led cambi di stato solo in seguito alla pressione del pulsante per almeno un secondo:
#include <avr/sleep.h> #include <avr/power.h> const byte LED = 1; // D1 / pin 2 const byte SWITCH = 2; // D2 / pin 6 / PCINT2 volatile byte last_sw_state = HIGH; volatile byte led_state = LOW; volatile long last_sw_change_millis = 0; byte sw_state = HIGH; long sw_read_millis = 0; // Interrupt Service Request. Executed when the state of the pin changes ISR(PCINT0_vect) { } void setup() { pinMode (LED, OUTPUT); pinMode (SWITCH, INPUT_PULLUP); cli(); // Disable interrupt // Pin change interrupt PCMSK |= bit (PCINT2); // D2 / pin 7 GIFR |= bit (PCIF); // Clear any outstanding interrupts GIMSK |= bit (PCIE); // Enable pin change interrupts sei(); // Enable interrupt } void loop() { sw_state = digitalRead(SWITCH); // or faster: (PINB >> PINB2) & 1 sw_read_millis = millis(); if (last_sw_state==HIGH && sw_state==LOW) { // Falling edge last_sw_change_millis = sw_read_millis; } if (last_sw_state==LOW && sw_state==LOW && sw_read_millis-last_sw_change_millis>1000) { led_state = !led_state; digitalWrite (LED, led_state); enter_sleep (); } last_sw_state = sw_state; } void enter_sleep () { // Enter sleep set_sleep_mode(SLEEP_MODE_PWR_DOWN); ADCSRA = 0; // Turn off ADC power_all_disable (); // Power off ADC, Timer 0 and 1, serial interface sleep_enable(); sleep_cpu(); // …zzz // Wake up sleep_disable(); power_all_enable(); // Power everything back on }
Un po’ di misure
Nelle mie prove la corrente assorbita dall’intera scheda senza Sleep Mode è di circa 15 mA con il led spento e di circa 17 mA con il led acceso.
Attivando lo Sleep Mode i consumi calano a circa 5 mA con il led spento e circa 7 mA con il led acceso.
Ovviamente la scheda Digispark con cui ho fatto le prove ha un secondo led sempre acceso (che indica la presenza di alimentazione) e diversi altri componenti passivi che impediscono di scendere sotto certi consumi ma il datasheet dell’Attiny85 indica, per il solo microcontrollore, consumi dell’ordine di qualche µA quando è in Sleep Mode.