Sleep Modus

Hallo, habe schon wieder eine Frage :wink:

Will, dass ein Programm erst dann startet, wennich einen Taster betätige, also in ein Sleep modus nach dem Upload des Codes wechselt.
set_sleep_mode(SLEEP_MODE_PWR_SAVE);
sleep_mode() Ist das die richtige Funktion dazu?

Das setzt nur den Modus. Aber aktiviert ihn noch nicht.

Das ganze ist hier erklärt:

Da steht auch wie du da wieder raus kommst. Im Abschnitt "Waking from sleep with a signal". Dazu musst du den Taster an einen Interrupt Eingang anschließen

Der sleep-Modus hat beim Arduino wenig Sinn weil zuviel andere Elektronik auf der Platine ist. Der Sleep-Modus macht erst Sinn wenn Du den ATmega alleine betreibst.
Grüße Uwe

Stimmt. Wenn es dir nur darum geht, dass das Programm nicht startet bis was passiert, dann mache eine Schleife in setup(), die solange ausgeführt wird bis der Taster gedrückt wird.

Ok. Habe viele Beispielcodes dazu gefunden, aber die Bibliotheken dazu kann ich nicht finden. Könnt ihr da paar Links empfehlen?

Das ist alles Teil der AVR libc die du schon installiert hast. Daher das #include <avr/sleep.h>

http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html

Verständnisfrage zum Sleepmodus:
habe an den Pin 2 einen Wippschalter dran gemacht an 5 V und an Pin 2. Mit foldenden Sketch will ich, dass die LED angeht, wenn ich den Taster betätige. Nur die LED geht von alleine an. Ist RiSING falsch an der Stelle?

#include <avr/sleep.h>
#include <avr/power.h>
 
int pin = 2;
int pinled=13;
 
void wakeUp()
{
  Serial.print("WakeUp"); //
  detachInterrupt(0); //
  digitalWrite(13,HIGH); 
}
 
void EnterSleep()
{
  attachInterrupt(0, wakeUp, RISING);
  delay(100); 
  sleep_enable(); //
  sleep_mode(); //
  sleep_disable(); //
}
 
void setup()
{
  Serial.begin(9600);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //
  pinMode(pin, INPUT);
  pinMode(13, OUTPUT); 
}
 
void loop()
{
 Serial.print("Hello World");
 delay(5000);
 Serial.print("Sleep");
 EnterSleep(); //
}

Der Pulldown fehlt wohl

Am Schalter? So etwa?
pinMode(pin, INPUT_PULLDOWN); PULLDOWN gibt es aber so nicht oder?

Pulldowns gehen nur extern.

Du kannst aber die internen Pullups verwenden und den Taster statt an 5V auf Low legen. Dann ist er gedrückt Low. Du bekommst also eine fallende Flanke beim Drücken und eine steigende beim Loslassen.

User_ino:
Am Schalter? So etwa?
pinMode(pin, INPUT_PULLDOWN); PULLDOWN gibt es aber so nicht oder?

Gibts nicht.

[Du kannst aber die internen Pullups verwenden und den Taster statt an 5V auf Low legen. Dann ist er gedrückt Low. Du bekommst also eine fallende Flanke beim Drücken und eine steigende beim Loslassen.]

Ok, die LED geht an, wenn der Schalter gedrückt wird, also verlässt der Arduino den Schalafmodus.
Aber die LED leuchtet dann die ganze Zeit, auch wenn ich den Schalter öffne. Wie mach ich, dass die wieder ausgeht, wenn ich de Schalter öffne, also dass Arduino in den Schafmodus wechselt? Aus dem Code detachInterrupt(0) entfernen?

Vielleicht mit
digitalWrite(13,LOW);

:wink:

Vielleicht solltest du EnterSleep() auch nur aufrufen, wenn der Taster nicht gedrückt ist und zusätzlich eine kleine Entprellzeit vergangen ist ?

Was ist hier falsch?
Mit attachInterrupt(0,wach,LOW) wird Arduino aus dem Schlaf erweckt, mit attachInterrupt(0,EnterSleep,CHANGE) soll der doch einschlafen. Der bleibt aber die ganze Zeit im Sleepmodus

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

int Schalterpin = 2;
int pinled=13;

void wach() //
{
Serial.print("Aufwachen"); //
attachInterrupt(0,EnterSleep,CHANGE); //
digitalWrite(13,HIGH);

}

void EnterSleep() // Schafmodus
{

attachInterrupt(0, wach,LOW); // Schalter am Pin 2, Schalter auf Masse, beim Einschalten wird der Sleepmodus verlassen
sleep_enable(); //
sleep_mode(); //
sleep_disable(); //
digitalWrite(13,LOW);
}

void setup()
{
Serial.begin(9600);
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //
pinMode(Schalterpin , INPUT_PULLUP); // Damit wird der Schalter auf Masse gelegt
pinMode(13, OUTPUT);

}

void loop()
{
Serial.print("Hello World");
delay ( 1000);

}

Der bleibt aber die ganze Zeit im Sleepmodus

Glaub ich nicht. Er wird "Hello WorldHello World ..." schreiben, jede Sekunde eins mehr. Die LED bleibt natürlich aus.

Wann wird denn EnterSleep() , oder von mir aus
attachInterrupt(0, wach,LOW);
zuerst mal aufgerufen?

Was passiert bei einem prellenden Taster ?

Ich würde keine zwei verschiedenen Routinen dynamisch an den Interrupt hängen.

Also die Funktion wach() wird aufgerufen, wenn ich den Schalter schliesse. Der ist auf Masse. Die Funktion EnterSleep() wird aufgerufen, wenn ich den Schalter öffne, HelloWorld wird in der Tat geschrieben. Wie kann man das denn sonst machen, wenn man keine 2 Rutinen an einen Interrupt hängt?

Also die Funktion wach() wird aufgerufen, wenn ich den Schalter schliesse

... aber nur, wenn attachInterrupt(0,wach,FALLING); vorher mal aufgerufen wurde :wink:

EnterSleep() braucht doch gar keine Interrupt-routine zu sein, oder ?

void loop() {
 Serial.print("HelloWorld "); 
 delay(1000); 
 if (digitalRead(Schalterpin) == HIGH) {  // Taste losgelassen: Schlafen
  delay(10); // Tasten prellen abwarten
  EnterSleep();
 }
}
void wach()              //
{
  Serial.print(" wach "); //  Vorsicht ! 
  //  Interrupt Routinen sollten keine Serial-Ausgaben machen, geht nur bis der Puffer voll ist.
  digitalWrite(13,HIGH); // Als Demo, dass wir hierher gekommen sind !
}

#include <avr/sleep.h>
#include <avr/power.h>
int Schalterpin = 2;
int pinled=13;

void setup()
{
Serial.begin(9600);
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //
pinMode(Schalterpin , INPUT_PULLUP); // Damit wird der Schalter auf Masse gelegt
pinMode(13, OUTPUT);

}

void loop() {
Serial.println("HelloWorld ");
delay(1000);
if (digitalRead(Schalterpin) == HIGH) { // Taste losgelassen: Schlafen
delay(10); // Tasten prellen abwarten
EnterSleep();
}
}
void wach() //
{
Serial.println(" wach "); // Vorsicht !
// Interrupt Routinen sollten keine Serial-Ausgaben machen, geht nur bis der Puffer voll ist.
digitalWrite(13,HIGH); // Als Demo, dass wir hierher gekommen sind !
}
void EnterSleep()
{
sleep_enable(); //
sleep_mode(); //
sleep_disable(); //
Serial.println(" Sleep "); //
digitalWrite(13,LOW);
}

Also in der Loop wird ständig Hello World geschrieben. Die LED leuchtet auch. Drückt man den Schalter, wird zwar Hello World nicht mehr geschrieben, aber die LED leuchtet und "Sleep" wird auch nicht geschrieben? Habe doch gesagt, dass in der Funktion EnterSleep() die LED aus sein soll.

und wo wird wach() attached ? Am besten in setup

void EnterSleep()
{
  Serial.println(" Sleep "); // 
  digitalWrite(13,LOW);
  sleep_enable(); //
  sleep_mode(); //  hier schläft er ein, das nächste was er ausführen wird, sollte wach() sein 
  sleep_disable(); //
}
In Setup kann ich doch keine Funktionen definieren. 

Habe es so geändert: 
[#include <avr/sleep.h>
#include <avr/power.h>
int Schalterpin = 2;
int pinled=13; 

void setup()
{
  Serial.begin(9600);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //
  pinMode(Schalterpin , INPUT_PULLUP);  // Damit wird der Schalter auf Masse gelegt
  pinMode(13, OUTPUT);
 
}


void loop() {
 Serial.println("HelloWorld "); 
 
 delay(1000); 
 if (digitalRead(Schalterpin) == HIGH) {  // Taste losgelassen: Schlafen
  delay(10); // Tasten prellen abwarten
  EnterSleep();
 }
  if (digitalRead(Schalterpin)==LOW)
 { 
  
  delay(10);
  wach();
  }
 
}
void wach()              //
{
  Serial.println(" wach "); //  Vorsicht ! 
  //  Interrupt Routinen sollten keine Serial-Ausgaben machen, geht nur bis der Puffer voll ist.
  digitalWrite(13,HIGH); // Als Demo, dass wir hierher gekommen sind !
}
void EnterSleep()
{ 
  Serial.println("Sleep");
  digitalWrite(13,LOW);
  sleep_enable(); //
  
  //sleep_disable(); //
  
}

Jetzt geht die LED beim Schalter an und ausmachen, aber loop wird immer ausgeführt, weil der serielle Monitor immer "Hello World"
schreibt, also wird der Sleep modus gar nicht aktiviert oder?