Arduino Leonardo Sleep Mode

Hallo,

ich Versuche gerade einem Arduino Leonardo Board beizubringen nach einem Interrupt aufzuwachen.

Das Tutorial im Learning Bereich (http://playground.arduino.cc/Learning/ArduinoSleepCode) trifft ungefähr das was ich versuche.

Mein Problem ist leider, dass das Board nicht aufwacht.

Wenn ich den Quellcode ausführe sieht man über den Serial Monitor wie das Board einschläft

SLEEP
SEI

Danach ist nichts mehr zu sehen. Wenn der Interruptpin (Pin 2) auf Low gezogen wird, sieht man auf dem Board die Pin13 LED gemütlich blinken, das Board wacht aber nicht auf.

Hat jemand eine Idee woran das liegt?

// Routinen fuer Sleep-Mode
void sleepPinInterrupt(void)
{
  Serial.println(F("ISR"));
  sleep_disable();
  //detachInterrupt(1);
  
  uint8_t state = digitalRead(ledPin);
  if (state == 0)
  {
    digitalWrite(ledPin,HIGH);
  }
  else
  {
    digitalWrite(ledPin,LOW);
  }
}

void enterSleepMode(void)
{  
  Serial.println(F("SLEEP"));
  sleep_enable();
  attachInterrupt(1, sleepPinInterrupt, LOW);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  cli();
  sei();
  Serial.println(F("SEI"));
  delay(1000);
  sleep_cpu();
  sleep_disable();
  Serial.println(F("WACH"));
}

Serial hat in Interrupt-Routinen nichts verloren!

Das hier ist unsinnig:

  cli();
  sei();

Damit deaktivierst du die Interrupts und aktivierst sie sofort danach wieder. Das ist sinnvoll wenn man bestimmte Sachen dazwischen macht, aber nicht so direkt hintereinander

Hier steht mehr: http://www.gammon.com.au/forum/?id=11497 Und für Interrupts den Teil bei "waking from sleep with a signal"

Das CLI stand an der falschen Stelle. Sollte dafür sein das der Interrupt nicht ausgeführt wird bevor das Board schläft

Die Seite hat mich leider auch nicht weitergebracht, da gehts um einen ATmega328.

Der Interrupt wird auf jedenfall ausgeführt. beim Einschlafen geht die LED an und bei Low-Signal aus…

SLEEP
CLI
CPU
// Routinen fuer Sleep-Mode
void sleepPinInterrupt(void)
{
  sleep_disable();
  detachInterrupt(1);
  digitalWrite(ledPin,LOW);
}

void enterSleepMode(void)
{  
  Serial.println(F("SLEEP"));
  digitalWrite(ledPin,HIGH);
  sleep_enable();
  cli();
  attachInterrupt(1, sleepPinInterrupt, LOW);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  Serial.println(F("CLI"));
  delay(1000);
  sei();
  Serial.println(F("CPU"));
  delay(1000);
  sleep_cpu();
  sleep_disable();
  Serial.println(F("WACH"));
}

zerb: Die Seite hat mich leider auch nicht weitergebracht, da gehts um einen ATmega328.

Der Code scheint aber im Prinzip auch nicht anders zu sein. Natürlich hast du einen anderen Prozessor, aber der Compiler scheint das meiste korrekt zu übersetzen. Zumindest das was wichtig ist. Also sleep_disable(), sleep_enable(), set_sleep_mode() und sleep_cpu();

Was vielleicht nicht geht ist der Teil mit dem Watchdog Timer und Brownout Detection. Das ist auch optional, und Browout Detection auszuschalten spart auch nur 25µA. Aber die Grundlagen sollten genauso gehen.

Beim Leonardo arbeitet der Controller Deinen Sketch ab und häld zugleich Verbindung über USB. Es kann ruhig sein daß beim Aufwachen aus dem Sleepmodus die USB Verbindung nicht initialisisert wird und darum der Leonardo nicht mehr funktioniert.

Grüße Uwe

Das scheint es wirklich zu sein.

Hab gerade mal versucht über den WatchDog das Board zu reseten, aber damit kommt er auch nicht wieder ins leben.

Die einzige Option ist glaube ich den Sleep Mode auf Idle zu ändern, wo die Schnittstellen aktiv bleiben Nur in der Variante schläft er nicht ein. gibt es da eine Besonderheit für diesen Mode?

Serial Monitor (trotz High Signal)

SLEEP
WACH
SLEEP
WACH
SLEEP
WACH
SLEEP
// Routinen fuer Sleep-Mode
void sleepPinInterrupt(void)
{
  detachInterrupt(1);
  digitalWrite(ledPin,HIGH);
}

void enterSleepMode(void)
{    
  Serial.println(F("SLEEP"));
  delay(100);
  digitalWrite(ledPin,LOW);
  sleep_enable();
  cli();
  attachInterrupt(1, sleepPinInterrupt, LOW);
  set_sleep_mode(SLEEP_MODE_IDLE);  
  sei();
  delay(1000);
  sleep_cpu();
  delay(1000);
  sleep_disable();
  Serial.println(F("WACH"));
}

Im Idle Mode läuft noch der Takt und damit diverse interne Komponenten. Entsprechend ist der Stromverbrauch anscheinend auch nicht viel weniger als normal. Bringt also nicht wirklich was.

Das kann aber auch teilweise daran liegen, dass damit noch Timer0 läuft und der Prozessor damit jede ms aufwacht (wegen millis()). Den Timer kann man aber auch getrennt abschalten.

Also mit dem IDLE und alles abschalten klappt es. Mal sehen wie viel Strom man dadurch spart.

// Routinen fuer Sleep-Mode
void sleepPinInterrupt(void)
{
  sleep_disable();
  power_all_enable();
  detachInterrupt(1);
}

void enterSleepMode(void)
{    
  Serial.println(F("SLEEP"));
  delay(100);
  sleep_enable();
  cli();
  attachInterrupt(1, sleepPinInterrupt, LOW);
  set_sleep_mode(SLEEP_MODE_IDLE);  
  sei();
  power_all_disable();
  delay(100);
  sleep_cpu();
  sleep_disable();
  Serial.println(F("WACH"));
}