Alle paar Stunden mal aufwachen, umschauen, wieder hinlegen

Schönen Sonntag zusammen,

ich taste mich ja gerade an das Thema "Stromsparen, Tiefschlaf" ran.
Dabei grüble ich, wie ich am effektivsten die Dauer der Tiefschlafphase in Stunden bestimme.

Gedanke:

  • RTC schickt 1 Hz Impuls an Interrupt-Eingang
  • Variable = Sekunden werden hochgezählt
  • wenn die gewünschten Sekunden aufgelaufen sind dann Zähler zurück auf 0, mache dies und das, und schlafen

Mich beschleicht aber das Gefühl, es geht noch effizienter. Vor allem zähle ich ja bei der Methode relativ, das gibt dann nach 3,5 Jahren schon einen spürbaren Versatz ;D

Wer hat Ideen oder noch besser Erfahrungen?

Hallo,

wenn du aller paar Stunden was machen willst, warum nutzt du dann das 1Hz Signal der RTC?
Nimm die Alarmregister und stelle die auf 1min. Geht natürlich nur wenn man eine DS3231 hat.
Mit DS1307 gehts nicht.

Oder man baut sich mit dem Alarmregister mit mehr Aufwand einen Wecker, den man dann immer wieder mit ändert nach aufwachen.

Edit:
Was haste denn für eine RTC?

In einem anderen Thread wurde gerade vorgeschlagen: die DS3231 hat interne Alarme. Damit könnte man einen Interrupt auslösen. So muss man nicht jede Sekunden unnötig aufwachen. Wenn der Alarm ausgelöst macht man was und setzt den Alarm ein paar Stunden in die Zukunft

Oder man könnte das 1Hz Signal mit einem 74HC4040 (12 Bit Binärzähler) oder 74HC4060 (14 Bit) weiter runterteilen. Da hätte man am letzten Ausgang ein sehr langsames Signal.

Ah, ich seh schon: hab zu oberflächlich meine DS3231 angeschaut :confused:
Und natürlich hätte ich auch gleich schreiben können, welche ich habe.

Alarmregister - klingt gut!

Die Idee mit den Zählern ist auch gut, aber frisst natürlich wieder Strom. Also lese ich doch erst mal gemütlich das Datenblatt der DS3231.

Wenn ich hängenbleibe melde ich mich wieder. Oder noch besser wenn ich Erfolg vermelden kann :sunglasses:

Klaus_ww:
Die Idee mit den Zählern ist auch gut, aber frisst natürlich wieder Strom.

Stimmt. Daran hatte ich gar nicht gedacht. Sind aber nur maximal 80µA. Hängt von der Temperatur ab. Bei 25°C sind es angeblich nur 8µA. Ist nicht mehr so wie bei TTL wo das mA frisst :slight_smile:

Hallo,

DS3231 - genau richtig. Im Grunde läuft alles mit dem Control- und Status-Register. Und natürlich dem Alarmregister sowieso. Die anderen beiden sind jedoch die, womit der Alarm ausgelöst und wieder gelöscht wird. Wenn ich das hinbekommen habe, bekommst du das auch hin, wie ich dich einschätze. Bei deinem umfangreichen Projekt Portfolio. :slight_smile:

Doc_Arduino:
Wenn ich das hinbekommen habe, bekommst du das auch hin, wie ich dich einschätze. Bei deinem umfangreichen Projekt Portfolio. :slight_smile:

Uhh, Vorschußlorbeeren ... ich gebe mir Mühe!

Hallo,

ich hatte mir damals das Datenblatt reingezogen und als ich dachte ich habs verstanden Funktionen gebaut bis es funktionierte und mich gefreut wie ein Schneekönig. Wecker bauen und immer nachziehen kannste dir eigentlich schenken, wenn du die Alarmregister nutzt um ein 1 Minutenintervall zu setzen. Dann erlebst du den u_long Überlauf sicherlich nicht mehr. Außer du läßt dich 8171 Jahre einfrieren. :slight_smile: Da geht vorher die RTC falsch.

Louis de Funès "Onkel Paul, die große Pflaume" läßt grüßen. :slight_smile:

Edit:
mit 1 Hz komme ich laut meiner Rechnung auf immerhin 136 Jahre bis zum u_long Überlauf.
Der 1 Minutentakt ist jedoch zum Strom sparen effektiver. :slight_smile:

Doc_Arduino:
Der 1 Minutentakt ist jedoch zum Strom sparen effektiver. :slight_smile:

Jo, reichen sollte das, aber eben noch stromsparender ist m.E. der Alarm, sonst muss der arduino ja doch jede Minute mal wach werden. Sicher nicht das dicke Ding, aber wenn ich schonmal am Sparen bin .... :grin:

Hallo,

wieviel Aufwand man treibt muß jeder für sich festlegen. :wink:

jede Minute aufwachen, Zähler vergleichen, nö niemand will was, hinlegen, sind nur paar Takte.

Irgendwann aufwachen, Zähler vergleichen, irgendwas machen, zusätzlich Weckzeiten neu berechnen, RTC Wecker stellen, hinlegen, sind paar Takte mehr.

Wenn man das jetzt auf die Spitze treiben möchte, würde ich vergleichen wie lang die zusätzliche Berechnung und RTC stellen dauert im Verhältnis zum gewünschten Intervall. Also was man einspart an Rechentakten.

Auch ein guter Gedanke!
Ich werde einfach mal probieren, letztlich soll's halt batteriesparend sein. Und für mich machbar

So Freunde,

ich habe mir ein paar Libs angeschaut die unterstützen, aber die fressen zu viel Speicher. Also zu Fuß machen war die Devise.

Da hab ich auch gleich mal gelernt, wie I2C so funktioniert und wie simpel das auf dem arduino machbar ist.
Und die ersten Versuche waren auch gleich erfolgreich.

Für mein "Problem" werde ich einen zyklischen Alarm jede Stude auslösen und die per Interrupt zählen. Ersteres macht die RTC von alleine, letzteres läßt sich stromsparend und einfach am arduino umsetzen.

Dann mal ran an die Arbeit!

Danke euch für die Tipps!

Ich glaube, ich muss doch den Doc konsultieren :confused:

Ich fummel jetzt schon "ewig" am Alarm 1 und dem Control Register rum aber es will einfach nicht - zumindest nicht wie ich ;D

Ziel: erstmal im Sekundentakt einen Interrupt raushusten.

Interrupt-Routine am Uno funktioniert - manuell getestet mit Kabel.

Ich setzte die A1 Register alle auf 0x80, also nur Bit 7 gesetzt. Das soll laut Tabelle 2 der Mask Bits zu einem sekündlichen Alarm führen.

Mask-Bits.PNG

Das Control Register setzte ich auf 0x05, also binär 000000101. Damit ist der Interrupt aktiviert und der Alarm 1.

Theoretisch, is klar.

Das ganze mache ich zu Fuß via Wire Befehlen.

Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x07);  //move pointer to Alarm 1 first register (from 07h to 0Ah)
  //setting Alarm 1
  Wire.write(0x80);              // 10000000 binary, seconds 
  Wire.write(0x80);              // 10000000 binary, minutes
  Wire.write(0x80);              // 10000001 binary, hours
  Wire.write(0x80);              // 10000001 binary, date
  Wire.endTransmission();
  
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x0E);  //move pointer to control register
  Wire.write(0x05);          //00000101
  Wire.endTransmission();

Welches Brett vor dem Kopf versperrt mir noch die Sicht auf den Sekunden-Interrupt?
Ach ja, sicherheitshalber habe ich am Pin 2 (= Interrupt 0) des Uno noch den Pullup aktiviert. Könnte ja sein, dass die RTC am Ausgang keinen hat.

Achtung, ich habe Null Ahnung, was Du da machst, aber solltest Du bei "Alarm once per second" vier Bits setzen wollen, so ist das nicht 0x80, sondern irgendwas mit F. Oder?

In einer Lib steht: #define ALARM_1_once_per_SEC B1111 // once a second

agmue:
Achtung, ich habe Null Ahnung, was Du da machst

Hehe, ich offenbar auch nicht :slight_smile:

Es geht aber tatsächlich um 4 Bits in 4 Registern, also schreibe ich 4 Bytes. Und nicht 4 Bits in einem Byte.

Klaus_ww:
Es geht aber tatsächlich um 4 Bits in 4 Registern, also schreibe ich 4 Bytes. Und nicht 4 Bits in einem Byte.

Jetzt habe ich "Figure 1. Timekeeping Registers" entdeckt. Schau noch mal zu A1F, ob da was getan werden muß, also Rücksetzen nach Alarm oder so.

Jetzt haste mich erwischt: A1F ... was meinste damit?

Und gerade habe ich das Spiel mal mit Alarm 2 probiert im Minutentakt - kommt auch kein Interrupt raus :angry:

Das Spiel übrigens mit 2 RTCs probiert, nicht dass eine hinüber ist.
Wenn, dann sind beide hinüber ....

Oh man, ich hab's gefunden :sunglasses:

Hab so im Datenblatt rumgeschmiert, dass ich A1F nicht mehr lesen konnte :smiling_imp:

Das Flag wird gesetzt wenn timer-match eintritt und muss dann wieder gelöscht werden.
Und jetzt timert das Teil so hübsch vor sich hin, ich könnt mir ein Loch in den Bauch freuen.

Wenn das mal kein Karma wert ist!!!

So, ich geh jetzt Register spielen :grinning:

Klaus_ww:
Und jetzt timert das Teil so hübsch vor sich hin, ich könnt mir ein Loch in den Bauch freuen.

Ich freue mich mit und bekam gerade einen Pudding gereicht ... :grin:

Hallo,

kaum das man mal nicht da ist wird man gerufen. :slight_smile:
Aber schön das es auch so geklärt werden konnte.

Ich hatte mir damals eine umfangreichere Funktion gebastelt, erst Register auslesen, gewünschte Bits ändern, zurückschreiben.

bool delete_RTC_DS3231_Alarmregister (int i2c_adresse, byte welches_Flag)
{
  bool error = false;    // Fehlerstatus setzen
  byte AL_1 = 1;     // welches_Flag = 1 > A1F wird gelöscht
  byte AL_2 = 1;     // welches_Flag = 2 > A2F wird gelöscht
                     // welches_Flag = 3 > A1F und A2F werden gelöscht
  
  if (welches_Flag >= 1 && welches_Flag <= 3)  {      
    Wire.beginTransmission(i2c_adresse);     // Connect
    Wire.write(0x0F);                        // Anfrage ab/der Register Nummer 0Fh
    if (Wire.endTransmission() > 0 )         // war Connect fehlerfrei?
      { 
       error = true;                         // I2C Busfehler
       return error;                         // Abruch
      } 
    Wire.requestFrom(i2c_adresse, 1);        // 1 Byte lesen, Register 0x0F einlesen  
    if (Wire.available() > 0 )               // sind Daten vorhanden?
      {
       _addr_0F = Wire.read(); 
      }  
    
    switch (welches_Flag)  {
      case 1 : AL_1 = 0; break;
      case 2 : AL_2 = 0; break;
      case 3 : AL_1 = 0; AL_2 = 0; break;
      default : Serial.println(F("sollte nicht passieren"));
    }    
    // Registerinhalt 0x0F modifizieren   
    bitWrite(_addr_0F, 0, AL_1);   // Status Register 0x0F Bit 0 A1F
    bitWrite(_addr_0F, 1, AL_2);   // Status Register 0x0F Bit 1 A2F
  
    // Registerinhalt 0x0F zurückschreiben
    Wire.beginTransmission(i2c_adresse);
    Wire.write(0x0F);                       // setzen auf Registernummer
    Wire.write(_addr_0F);
    if (Wire.endTransmission() > 0 )  {     // Byte in Register schreiben
      error = true;                         // I2C Busfehler
    }      
  }
  else  {
    Serial.println(F("Parameterfehler")); 
  }
  return error;    
}

und das Zusammenspiel der AlarmMask Bits Table 2 und der Bits vom Register 0x0E legt fest welcher Alarm bzw. welcher Takt am Ende aktiv ist.

bitWrite(addr_0E, 0, 1);   // Control Register 0x0E Bit 0 A1IE  (Alarm 1 Settings enabled/disabled)
bitWrite(addr_0E, 1, 0);   // Control Register 0x0E Bit 1 A2IE  (Alarm 2 Settings enabled/disabled)
bitWrite(addr_0E, 2, 1);   // Control Register 0x0E Bit 2 INTCN (0 = Takt aktiv, 1 = Alarm Register aktiv
bitWrite(addr_0E, 3, 0);   // Control Register 0x0E Bit 3 RS1   (Takteinstellung wenn INTCN = 0
bitWrite(addr_0E, 4, 0);   // Control Register 0x0E Bit 4 RS2   (Takteinstellung wenn INTCN = 0

frohe Ostern