Den Arduino schlafen schicken und von der RealTimeClock wieder aufweckenFreitag, 10 April, 2015 11:07

Der Arduino soll ja mal mit Batterie laufen und deswegen (und überhaupt, nicht wahr?) sind stromsparende Zustände neben der Hauptfunktion ein zweiter Hauptfaktor in der Arduino Programmierung. Wie üblich waren durch Google bereits bekannt gewordene und auch neue Webseiten diesbezüglich auskunftsfreudig.

Dass es zuerst nicht klappen wollte, den Arduino wieder auf zu wecken - schlafen schicken ging ganz wunderbar und prompt, schien zunächst undurchsichtig zu sein. Aber auch hier hatten andere Leute dasselbe Problem und so kam ich der Ursache auf die Spur. - Meine naive Annahme, wenn ich die RTC anweise, den Interrupt zu aktivieren, mit dem sie den Arduino wieder aufwecken soll, dann funktionert das auch war falsch. Vorher putzen quasi muss schon sein :)

Und eine Seite stach aus allen anderen Seiten besonders hervor, weswegen ich sie gerne hier besonders erwähne:

Gammon Forum : Electronics : Microprozessors: Power saving techniques for microprozessors 

Und hier präsentiere ich mein Labor-Script, das funktioniert (Update, für das neue LED-Display und mit 2-stelligen Ausgaben überall :) ):

    
#include <LiquidCrystal_I2C.h>
#include <DS3232RTC.h> 
#include <Time.h>
#include <Wire.h>
#include <avr/sleep.h>
#include <avr/power.h>

// old LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
int counter=0;
int pin2 = 2;

unsigned long(starttime)=2;
unsigned long(sleeptime)=1;

void setup()
{
  Serial.begin(9600);
  pinMode(pin2, INPUT); 
  lcd.begin(20, 4);
  lcd.setCursor(0,0);
  setSyncProvider(RTC.get);
  if(timeStatus() != timeSet) {
lcd.print("Unlucky - no RTC");
Serial.println("Unlucky - no RTC");
  }  
  else {
lcd.print("lucky - got RTC");
Serial.println("lucky - got RTC");
starttime=now();
sleeptime=starttime+30;
delay(2000);
  unsigned long alarmtime=sleeptime+30;
  Serial.print("Sleep time: ");
  SerialDigits(hour(sleeptime));
  Serial.print(":");
  SerialDigits(minute(sleeptime));
  Serial.print(":");
  SerialDigits(second(sleeptime));
  Serial.println("");
  Serial.print("Alarm time: ");
  SerialDigits(hour(alarmtime));
  Serial.print(":");
  SerialDigits(minute(alarmtime));
  Serial.print(":");
  SerialDigits(second(alarmtime));
  Serial.println("");
  RTC.squareWave(SQWAVE_NONE);
  RTC.alarm(1);
  RTC.alarm(2);
  RTC.alarmInterrupt(ALARM_1, true);
  RTC.alarmInterrupt(ALARM_2, false);
  RTC.setAlarm(ALM1_MATCH_HOURS, second(alarmtime), minute(alarmtime), hour(alarmtime), 0);
  Serial.println("Waiting for sleep");
  lcd.clear();
  } 
}

void loop(void)
{
  unsigned long(current)=now();
  unsigned long(soon)=current;
//  do {
 digitalClockDisplay();
//     delay(200);
 if ( (sleeptime > 1 ) and ( sleeptime = soon ) ) {
   enterSleep();
 }
//     soon=now();
//  } while ( soon  current +6);
//  do {
 digitalAlarmsDisplay();
 delay(200);
 if ( (sleeptime > 1 ) and ( sleeptime = soon ) ) {
   enterSleep();
 }
 soon=now();
//   } while ( soon   current +10);
}

void wake () {
 sleep_disable();
}
void enterSleep(void)
{
  lcd.setCursor(0,1);
  lcd.print("... entering sleep                ");
  lcd.setCursor(0,2);
  lcd.print("S1: ");
  LedDigits(hour(sleeptime));
  lcd.print(":");
  LedDigits(minute(sleeptime));
  lcd.print(":");
  LedDigits(second(sleeptime));
  lcd.setCursor(0,3);
  lcd.print("A1: ");
  LedHexes(RTC.readRTC(ALM1_HOURS));
  lcd.print(":");
  LedHexes(RTC.readRTC(ALM1_MINUTES));
  lcd.print(":");
  LedHexes(RTC.readRTC(ALM1_SECONDS));
  delay(2000);
  lcd.noBacklight();
  delay(2000);
  lcd.off();
  // disable ADC
  ADCSRA = 0;
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  noInterrupts ();
  // This is triggered by interrupt
  attachInterrupt (0, wake, LOW);
  // turn off brown-out enable in software
  // turn on brown-out enable select
  MCUCR = bit (BODS) | bit (BODSE);
  // this must be done within 4 clock cycles of above
  MCUCR = bit (BODS);
  interrupts ();
  sleep_mode();
  
  /* After wake up continue from here. */
  
  detachInterrupt (0); 
  power_all_enable();
  lcd.on();
  sleeptime=1;
  setSyncProvider(RTC.get);
  RTC.alarmInterrupt(ALARM_1, false);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("..just woke up!!");
  delay(2000);
}

void setAlarmOnce() {
  unsigned long alarmtime=sleeptime+60;
  Serial.print("Sleep time: ");
  SerialDigits(hour(sleeptime));
  Serial.print(":");
  SerialDigits(minute(sleeptime));
  Serial.print(":");
  SerialDigits(second(sleeptime));
  Serial.println("");
  SerialDigits(hour(alarmtime));
  Serial.print(":");
  SerialDigits(minute(alarmtime));
  Serial.print(":");
  SerialDigits(second(alarmtime));
  Serial.println("");
}

void digitalClockDisplay(void)
{
  lcd.setCursor(0,0);
  LedDigits(hour());
  lcd.print(':');
  LedDigits(minute());
  lcd.print(':');
  LedDigits(second());
  lcd.print(' ');
  char tempF[6];
  int t = RTC.temperature();
  float celsius = t / 4.0;
  dtostrf(celsius, 5, 1, tempF);
  lcd.print(celsius);
  lcd.print((char)223);
  lcd.print('C');
  lcd.setCursor(0,1);
  LedDigits(day());
  lcd.print('.');
  LedDigits(month());
  lcd.print('.');
  lcd.print(year());
  lcd.print("  ");
}

void digitalAlarmsDisplay() {
lcd.setCursor(0,2);
lcd.print("S1: ");
LedDigits(hour(sleeptime));
lcd.print(":");
LedDigits(minute(sleeptime));
lcd.print(":");
LedDigits(second(sleeptime));
lcd.setCursor(0,3);
lcd.print("A1: ");
LedHexes(RTC.readRTC(ALM1_HOURS));
lcd.print(":");
LedHexes(RTC.readRTC(ALM1_MINUTES));
lcd.print(":");
LedHexes(RTC.readRTC(ALM1_SECONDS));
lcd.print("       ");

}

void LedDigits (int digits)
{
  if(digits < 10)
lcd.print('0');
  lcd.print(digits);
}

void SerialDigits (int digits)
{
  if(digits < 10)
Serial.print('0');
  Serial.print(digits);
}

void LedHexes (int digits)
{
  if(digits < 16)
lcd.print('0');
  lcd.print(digits, HEX);
}

Etwas lang geworden :)

Categories:

[ [Kommentare ausblenden] ]
Bitte auch die verwendete Bibliotheken verlinken + Versionsangabe. Ich habe zwei ds3231 bibliotheken probiert und keine von beiden geht zu kompilieren. Auch fehlt Sommer/Winterzeit Automatik
Bibi, 08.01.2017, 00:50h #
Hier Kommentar einfügen
Name:
e-Mail:
Website:
spam-schutz, bitte code eingeben: captcha, sorry
Kommentar:

Eingaben erinnern
Benachrichtigen bei neuen Kommentaren?
Die E-Mail-Adresse wird nicht angezeigt,
Eingabe von http://www.URL.com wird automatisch zu Link,
html ausgeschaltet