Attiny85 sleep

Attiny85sleep

Un Attiny85 consuma qualche milliampere da sveglio a 5V.

Attiny85sleep3

Anche l’attiny85 dopo aver fatto qualche operazione può essere messo a dormire per risparmiare energia e può essere svegliato tramite un evento esterno o tramite il watchdog timer.

Per svegliarlo con il watchdog timer si può usare questo codice:


    #include <avr/sleep.h>
    #include <avr/wdt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
int i=0;
uint8_t originalValue=0;
volatile boolean f_wdt= 1;

void setup()
{
 setta_watchdog(9);     // 0=16ms,1=32ms,2=64ms,3=128ms,4=250ms,5=500ms,6=1s,7=2s,8=4s,9=8s
}

void loop()
{
 if (f_wdt==1)                 // aspetta lo scadere del tempo
 {  
   f_wdt=0;                    // resetta il flag
   TCCR1 = originalValue;      //ripristina il registro TCCR1 per riabilitare il timer.
   originalValue = TCCR1;      //salva il valore del timer 1
   TCCR1 = 0;                  //spegne timer 1
   dormi();
                               //inserire qui il codice
 }
}
void dormi()
{
 cbi(ADCSRA,ADEN);                    // ADC off
 set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep profondo
 sleep_enable();                      // abilita lo sleep
 for(i=0;i<3;i++)                     // ripete lo sleep diverse volte
 sleep_mode();                        // sleep qua
 sleep_disable();                     // sveglia qua 
 sbi(ADCSRA,ADEN);                    // ADC on
}

void setta_watchdog(int j)
{
 byte bb;
 int ww;
 if (j > 9 ) j=9;
 bb=j & 7;
 if (j > 7) bb|= (1<<5);
 bb|= (1<<WDCE);
 MCUSR &= ~(1<<WDRF);
 WDTCR |= (1<<WDCE) | (1<<WDE);    
 WDTCR = bb;                       
 WDTCR |= _BV(WDIE);
}
ISR(WDT_vect)
{
 f_wdt=1;       //imposta flag globali
}
  

Dove c’è setta_watchdog(9) si impostano i secondi di sleep, per esempio con 9 si avranno 8 secondi, con 8 4 secondi, con 7 2 secondi e così via, per un tempo maggiore c’è un ciclo for appena prima dello sleep mode, se si vuole un tempo minore si può cancellare il ciclo for.

Il consumo in questa modalità di sleep è di circa 7µA a5V.

Attiny85sleep1

Invece un codice con interrupt esterno che permette di scendere sotto il microampere, è il seguente:


#include <avr/sleep.h>                      
#define BODS 7                     //BOD Sleep bit in MCUCR
#define BODSE 2                    //BOD Sleep bit abilitante in MCUCR
byte i,adcsra, mcucr1, mcucr2;
void setup()
{
  for (i=0;i<5;i++)
  {  
    pinMode(i, INPUT);       //tutti i pin input
    digitalWrite(i, HIGH);
  }
}

void loop()
{
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    MCUCR &= ~(_BV(ISC01) | _BV(ISC00));      //int0 low
    GIMSK |= _BV(INT0);                       //abilita int0
    adcsra = ADCSRA;                          //salva ADCSRA
    ADCSRA &= ~_BV(ADEN);                     //disabilita ADC
    cli();                                    //stop interrupts per eseguire BOD
    mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);  //brown-out detector off
    mcucr2 = mcucr1 & ~_BV(BODSE);            
    MCUCR = mcucr1;                           
    MCUCR = mcucr2;
    sei();                                    //interrupts abilitati per sveglia
    sleep_cpu();                              //sleep qua
    sleep_disable();                          //sveglia qua
    ADCSRA = adcsra;                          //ripristina ADCSRA
                                              //inserire qui il codice    
}

ISR(INT0_vect)                      //interrupt int0 sveglia
{
    GIMSK = 0;                     //disabilita interrupt esterni
}  

Funziona solo con segnale LOW al D2 e bisogna ricordarsi di mettere in outuput i pin da usare prima del codice.

Attiny85sleep2

Il consumo è di circa 0,5µA a 5V, sicuramente con queste correnti in gioco bisognerà tenere in considerazione anche l’autoscarica della batteria da usare, la disattivazione dei sensori e quant’altro per risparmiare corrente, un saluto e alla prossima.

I commenti sono chiusi.