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
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.
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.
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
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.
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. Da geht vorher die RTC falsch.
Louis de Funès "Onkel Paul, die große Pflaume" läßt grüßen.
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.
Doc_Arduino:
Der 1 Minutentakt ist jedoch zum Strom sparen effektiver.
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 ....
wieviel Aufwand man treibt muß jeder für sich festlegen.
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.
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.
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.
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
Hab so im Datenblatt rumgeschmiert, dass ich A1F nicht mehr lesen konnte
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.