Schlafmodus mit Wecken durch Pin Change Interrupt (PCI)

Das nachfolgende Programmbeispiel zeigt, wie ein schlafender Attiny azyklisch "von außen" mit einem Pin Change Interrupt, ausgelöst durch das Drücken eines Tasters, geweckt wird.


Funktion:

Nach Neuanlauf des Attiny wird dieser in den Schlafmodus gesetzt. Durch Drücken der Taste "LED Ein" wird ein PCI am Pin PB3 ausgelöst, der die LED für 2 Sekunden einschaltet. Anschließend geht der Attiny wieder in den Schlafmodus, wo er bis zum nächsten Tastendruck verharrt.


Infos zum PCI beim Attiny findet man hier!


Verwendete Library:

sleep: Die verwendete Library sleep ist Bestandteil der Arduino-IDE und muss deshalb nicht installiert werden.


Hinweis:

Wer mit Registerprogrammierung und Pin Change Interrupt nicht vertraut ist, sollte sich zum Verständnis des Programms folgende Seiten ansehen: Bitmanipulation und Pin Change Interrupt Attiny


//Sleep Mode mit PCI-Wecken
//Code fuer Attiny
//Author Retian
//Version 1.0


#include <avr/sleep.h>


//Prototypen:
void gotoSleep(void);


#define ledPin 4


volatile bool statusLeuchten = false;
bool statusSleep = true;


void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);

  //Setzen der Register fuer Pin-Change-Interrupt Pin PB3
  //Loeschen des Global Interrupt Enable Bits (I) im Status Register (SREG)
  SREG &= 0x7F; //entspricht "cli();"
  //Setze des Pin Change Interrupt Enable Bit
  GIMSK |= (1 << PCIE);
  //Setzen des Pin Change Enable Mask Bit 3 (PCINT3)  ==> Pin PB3
  PCMSK |= (1 << PCINT3);
  //Setzen des Global Interrupt Enable Bits (I) im Status Register (SREG)
  SREG |= 0x80; //entspricht "sei();"
}


void loop() {
  if (statusLeuchten)
  {
    digitalWrite(ledPin, HIGH);
    delay(2000);
    digitalWrite(ledPin, LOW);
    statusLeuchten = false;
    statusSleep = true;
  }

  if (statusSleep)
  {
    gotoSleep();
    statusSleep = false;
  }
}


//Attiny in den Schlafmodus setzen

void gotoSleep()
{
  byte adcsra;

  adcsra = ADCSRA; //ADC Control and Status Register A sichern
  ADCSRA &= ~_BV(ADEN); //ADC ausschalten

  MCUCR |= (1 << SM1) & ~(1 << SM0); //Sleep Modus = Power Down
  MCUCR |= _BV(SE); //Sleep Enable setzen
  sleep_cpu(); //Schlafe ....
  MCUCR &= ~(1 << SE); //Sleep Disable setzen
 
  ADCSRA = adcsra; //ADCSRA-Register rückspeichern
}


//Interrupt Serviceroutine (Pin-Change-Interrupt)
ISR(PCINT0_vect)
{
  statusLeuchten = true;
}

Ergebnis:

Der Stromverbrauch des Testaufbaues beträgt ca. 17 mA bei leuchtender LED (ca. 7,5 mA ohne LED). Wie nachfolgendes Bild 1 zeigt, beträgt im Schlafmodus der Stromverbrauch weniger als 0,5 µA !!

 

Bild 1: Multimeter mit Anzeige des Stromverbrauchs im Schlafmodus von weniger als 0,5 µA (Messbereichsvorwahl 200 µA)


Zurück zu Attiny im Schlafmodus