Hallo,
wenn du den Sleep Modus direkt über die Register steuern willst, kann ich dir ein Beispiel geben.
In meinem Canon Zeitraffer Timer geht ein ATTiny84 zwischen den Auslösungen immer wieder in den Sleep Mode. Das Projekt ist hier Zeitraffersteuerung für Canon Kamera | Glaskugelsehen Blog beschrieben. Ich häng den Code mal hier mit rein.
/* Programm löst eine Canon 550D programmgesteuert aus. Über einen Drehkodierschlater lassen sich 15
verschiedene Zeiten einstellen. Kodierer an D0-3 angeschlossen (PA0..3)
Focus und Auslöser werden über FET geschaltet, Focus über D9, Auslöser über D10 (PB0, PB1)
Im Bulb Modus muss bei Reset der Focus Button gedrückt gehalten werden.
Der Prozessor bleibt die meiste Zeit im Sleep Modus. Timing ist erprobt bei 8MHz Takt
Dieses Programm wurde von Reinhard Nickels (rnickels@web.de) erstellt und steht unter GNU GPL.
*/
#include <avr/sleep.h>
#include <avr/wdt.h>
#define POWER 7 // stellt die Messspannung für den Drehkodierer bereit
#define FOCUS 9
#define SHOT 10
#define BULB 4
byte wdtime; // Variable für Schlafzyklus
byte mode;
boolean first=true;
volatile boolean f_wdt = true;
int wd_counter = 0;
/*
Schalter-
stellung 0 1 2 3 4 5 6 7 8 9 A B C D E F
Zeit AUS 3 sec 5 sec 10 sec 15 sec 30 sec 1 min 5 min 15 min 30 min 1 h 2 h 3 h 4 h 5 h 6 h
Fokus-
Vorlaufzeit - |1 sec -> |4 sec ->
*/
// 0 1 2 3 4 5 6 7 8 9 10(A) 11(B) 12(C) 13(D) 14(E) 15(F)
// unsigned int Shot[16]= {0, 3, 5, 10, 15, 30, 60, 300, 900, 1800, 3600, 7200, 10800, 14400, 18000, 21600};
unsigned int Shot[16]= {0, 7, 15, 33, 4, 7, 13, 68, 205, 410, 820, 1640, 2460, 3280, 4100, 4920};
void setup() {
pinMode(FOCUS,OUTPUT);
pinMode(SHOT,OUTPUT);
pinMode(POWER,OUTPUT);
pinMode(BULB, INPUT);
if (!digitalRead(BULB)) {
while (!digitalRead(BULB)) {
} // warte auf HIGH
digitalWrite(FOCUS, HIGH);
digitalWrite(SHOT, HIGH);
while(1) { // stay to next RESET
}
}
for (int i=0;i<4;i++) {
pinMode(i, INPUT);
digitalWrite(i, HIGH); // Pullups
}
digitalWrite(POWER, HIGH);
delay(200); // zur Stabilisierung der Spannung- hier als Testausgang, kann im endgültigen Prog entfallen
// mode=kodierer();
mode = ~PINA & B0001111;
digitalWrite(POWER, LOW);
if (mode==0) {
for (int i=0;i<4;i++) {
digitalWrite(i, LOW); // damit kein Strom an den Pullups verbraucht wird
}
system_sleep(); // ohne Watchdog init warte auf Reset
}
else if (mode<=3) wdtime=4; // 250ms
else wdtime=8; // 4s
setup_watchdog(wdtime);
}
void loop() {
if (f_wdt) { // wait for timed out watchdog / flag is set when a watchdog timeout occured
f_wdt=false; // reset flag
digitalWrite(FOCUS, HIGH);
if (mode<=5) delay(1000);
else delay(4000);
digitalWrite(SHOT, HIGH);
delay(100);
digitalWrite(SHOT, LOW);
digitalWrite(FOCUS, LOW);
}
pinMode(FOCUS,INPUT); // Ausgänge für Schlafen vorbereiten
pinMode(SHOT,INPUT);
pinMode(POWER,INPUT);
for (int i=0;i<4;i++) {
digitalWrite(i, LOW);
}
while (wd_counter < Shot[mode]) { // x-1 * 4s bei Mode 8
system_sleep(); // hier gehts zum schlafen und ab hier gehts weiter
wd_counter++;
}
wd_counter=0;
pinMode(FOCUS,OUTPUT);
pinMode(SHOT,OUTPUT);
pinMode(POWER,OUTPUT);
for (int i=0;i<4;i++) {
digitalWrite(i, HIGH);
}
}
// set system into the sleep state
// system wakes up when wtchdog is timed out
void system_sleep() {
ADCSRA &= ~(1<<ADEN); // switch Analog to Digitalconverter OFF
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
sleep_mode(); // System sleeps here
// continue from here
sleep_disable(); // System continues execution here when watchdog timed out
ADCSRA |= (1<<ADEN); // switch Analog to Digitalconverter ON
}
void setup_watchdog(int ii) {
// ii: 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms,6=1s,7=2s,8=4s,9=8s
byte bb;
if (ii > 9 ) ii=9; // 1001
bb=ii & 7; // xxxx & 0111 = 0aaa
if (ii > 7) bb|= (1<<5); // xx1xxaaa
bb|= (1<<WDCE); // WDCE is BIT4 xx11xaaa
MCUSR &= ~(1<<WDRF); // Watchdog Reset Flag wird gelöscht
// start timed sequence
WDTCSR |= (1<<WDCE) | (1<<WDE); // WDE Watchdog enable, WDCE Watchdog Change Enable (must be set by prescaler use)
// set new watchdog timeout value
WDTCSR = bb; // ??
WDTCSR |= (1<<WDIE); // Watchdog Timeout INT enable
}
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
f_wdt=true; // set global flag
}
Das Programm ist gut kommentiert, die entsprechenden Initialisierungen des Sleep Mode sind ziemlich übersichtlich.
Reinhard