RTC statt delay

Hallo allerseits,
ich bin auf der suche nach einem Codeschnippsel, der statt delay eine RTC verwendet.
Konkret, ich habe ein Projekt in dem eine RTC verbaut ist.
Immer zu einer bestimmten Uhrzeit wird ein Code ausgeführt, was super klappt.

Nun möchte ich noch einen kleinen Code alle 30 min ausführen lassen und dabei happerts... :blush:
Ich weiss nicht wie ich statt dem delay(1800000); die RTC benutzen kann ?

Kann mir jemand helfen ? Hoffe ihr versteht was ich meine...

Klingt für mich noch nichteinmal nach der Notwendigkeit, eine RTC zu verwenden. Delays() zu vermeiden gehört hier ja schon zum guten Ton, da wird dann oft das mit der IDE mitgelieferte Beispiel blinkWithoutDelay angeführt. :wink:

Hallo sth77,
ok, habe ich schon mal was von gehört... Schau ich mir mal an.
Aber gibt es eine möglichkeit das mit einem RTC zu machen ?

Wenn du eine RTC hast, hast du sicher auch eine Variable für die Minuten oder?
Wenn diese Variable 0 oder 30, ist soll dein Code ausgeführt werden.

if((min == 0) | (min == 30)){
  // dein Code
}

Grüße,
J3RE

Definiere eine Variable mit der Minute in welcher Dein Code ausgeführt werden soll. (minute = 20)
Hol Dir in loop() einfach von der RTC immer die Minuten und vergleiche den Wert mit der Variablen.
Wenn RTC.minute == gemerket_minute (z.B. Minute 30), dann führe Deinen Code aus und setze die Variable auf den nächsten Minutenwert.
minute = (minute + 30) % 60
Dann vergleichst Du wieder wie oben den aktuellen Wert mit Deiner Variable.

Was passiert bei der Rechnung?

minute = 20
minute = minute + 30 = 50
minute = minute + 30 = 80 <- falscher Minuten Wert.
minute = (minute + 30) % 60 = 20 <- richtiger Minutenwert.

Das klappt übrigens mit beliebigen Abständen zwischen 1 und 60, nicht aber mit Werten größer als eine Stunde.

Mario.

So in etwa vllt:

#include <time.h>
#define meinIntervall 60 * 30
.
.
time_t aktuelleZeit;
time_t alteZeit;
.
.
.

aktuelleZeit = now();
if ( aktuelleZeit - alteZeit >= meinIntervall){
alteZeit = aktuelleZeit;
//do something
}

Wie man die time Klasse mit dem RTC synchronisiert steht auch dort beschrieben.
Man kann das aber auf so kurzen Intervallen immer noch mit millis() machen.

J3RE:

if((min == 0) | (min == 30)){

// dein Code
}

Bei diesem Code hast Du das Problem, das der Code vermutlich mehrmals in der gleichen Minute abgearbeitet wird, denn loop() benötigt in der Regel weniger als eine Minute zum Durchlauf. Du musst also verhindern, das in der gleichen Minute der Code nochmal ausgeführt wird.

Außerdem gibt es eine time_alarm lib. Die arbeitet dann mit einem Callback auf eine Funktion. Die Lib braucht aber jede Menge speicher und ist m.M.n. nicht besonders schnell.

WOW 8)
Bin gerade überwältigt... Vielen Dank für die Erklärungen und Hilfen.
Wieder was gelernt :smiley:

Aber in der Zeit in der Ihr hier fleißig gepostet habt, habe ich mich an Millis() versucht und etwas brauchbares getippt.

long previousMillis = 0;        
long Pause = 10000;        // Pause zwischen Ping´s (10000 = 10sek)

void setup()
{
  Serial.begin(9600);
  Serial.println(F("Starte Serial-Monitor"));
}

void loop()
{
unsigned long currentMillis = millis();
unsigned long currentmillis = millis();

if(currentMillis - previousMillis > Pause) {
  previousMillis = currentMillis;
  currentmillis = 0;
  Serial.println(F("Sende Ping .."));
  Serial.println(F("warte 10 Sekunden ..."));
  }
}

Nun habe ich aber gelesen das ja millis irgendwann überläuft (nach 47 Tagen?), wie kann ich das denn verhindern ?

Hallo Mario :grin:, dein Vorschlag werde ich mir mal näher ansehen... vielen Dank... Damit wäre ja der miilis Überlauf hinfällig

J3RE:
Wenn du eine RTC hast, hast du sicher auch eine Variable für die Minuten oder?
Wenn diese Variable 0 oder 30, ist soll dein Code ausgeführt werden.

if((min == 0) | (min == 30)){

// dein Code
}

Ma könnte das vieleicht auch so lösen:

if((min == 0 && sec == 0) | (min == 30 && sec == 0)){
  // dein Code
}

Oder nicht ?

mkl0815:

J3RE:

if((min == 0) | (min == 30)){

// dein Code
}

Bei diesem Code hast Du das Problem, das der Code vermutlich mehrmals in der gleichen Minute abgearbeitet wird, denn loop() benötigt in der Regel weniger als eine Minute zum Durchlauf. Du musst also verhindern, das in der gleichen Minute der Code nochmal ausgeführt wird.

stimmt, habe ich vergessen...:slight_smile:

Cetax:
Ma könnte das vieleicht auch so lösen:

if((min == 0 && sec == 0) | (min == 30 && sec == 0)){

// dein Code
}




Oder nicht ?

Ja aber nur wenn der Code länger als eine Sekunde benötigt. Der Nachteil zu den anderen Lösungen ist halt, dass man nach dem Einschalten auf die volle/halbe Stunde warten muss.

Grüße,
J3RE

Dann wird der Code immernoch mehrmals in der Sekunde ausgefgührt.
Am einfachsten ist die Stunden, Minuten und Sekunden in Sekunden umzurechnen und nur mit eine Variable kontrolieren.
Benute eine Variable die auf 1 gesetzt wenn das erste mal die Zeit übereinstimmt und 0 gersetzt wird enn sie nicht übereinstimmt.
Die Aktion wird durchgeführt und die Variable auf 1 gesetzt, wenn die Zeit richtig ist, und die Variable 0 ist. So wird die Aktionnur einmal aufgerufen.
Grüße Uwe

uwefed:
Dann wird der Code immernoch mehrmals in der Sekunde ausgefgührt.
Am einfachsten ist die Stunden, Minuten und Sekunden in Sekunden umzurechnen und nur mit eine Variable kontrolieren.
Benute eine Variable die auf 1 gesetzt wenn das erste mal die Zeit übereinstimmt und 0 gersetzt wird enn sie nicht übereinstimmt.
Die Aktion wird durchgeführt und die Variable auf 1 gesetzt, wenn die Zeit richtig ist, und die Variable 0 ist. So wird die Aktionnur einmal aufgerufen.

oder so:

if(((min == 0) && (minOld == 30)) | ((min == 30) && (minOld == 0)){
  minOld = min;
  // dein Code
}

Grüße,
J3RE

J3RE Wie machst Du das wenn Du mehr als 2 mal die Stunde was machen willst? ]:smiley:

uwefed:
J3RE Wie machst Du das wenn Du mehr als 2 mal die Stunde was machen willst? ]:smiley:

Dann wird meine Lösung etwas zu kompliziert werden. :wink:

Dann ist die Lösung von mkl0815 in Kombination mit deinem Ansatz wahrscheinlich am sinnvollsten. :smiley:

Grüße,
J3RE

J3RE:
...

Der Nachteil zu den anderen Lösungen ist halt, dass man nach dem Einschalten auf die volle/halbe Stunde warten muss.

Grüße,
J3RE

Das ist kein für mich kein Nachteil, sondern wäre wünschenswert.. XD

J3RE:

mkl0815:

J3RE:

if((min == 0) | (min == 30)){

// dein Code
}

Bei diesem Code hast Du das Problem, das der Code vermutlich mehrmals in der gleichen Minute abgearbeitet wird, denn loop() benötigt in der Regel weniger als eine Minute zum Durchlauf. Du musst also verhindern, das in der gleichen Minute der Code nochmal ausgeführt wird.

stimmt, habe ich vergessen...:slight_smile:

Cetax:
Ma könnte das vieleicht auch so lösen:

if((min == 0 && sec == 0) | (min == 30 && sec == 0)){

// dein Code
}




Oder nicht ?

Ja aber nur wenn der Code länger als eine Sekunde benötigt. Der Nachteil zu den anderen Lösungen ist halt, dass man nach dem Einschalten auf die volle/halbe Stunde warten muss.

Grüße,
J3RE

Auch kein Problem!
Variable einfach mit etwas größer 1800 initialisieren.

Habs entweder übersehen, oder hat bisher keiner erklärt, was man bei millis() - Überlauf macht:

Ganz einfach:

const unsigned long INTERVALL=60000;  // einmal jede Minute
static unsigned long alterWert; // oder auch global deklarieren


if ( (millis() - alterWert) >= INTERVALL )
{
  alterWert = millis();
  // funktioniert selbst bei einem Überlauf, da die Differenz auch dann stimmt
}

michael_x:
Habs entweder übersehen, oder hat bisher keiner erklärt, was man bei millis() - Überlauf macht:

Ganz einfach:

const unsigned long INTERVALL=60000;  // einmal jede Minute

static unsigned long alterWert; // oder auch global deklarieren

if ( (millis() - alterWert) >= INTERVALL )
{
  alterWert = millis();
  // funktioniert selbst bei einem Überlauf, da die Differenz auch dann stimmt
}

Hi, super Danke.
Ist bestimmt untergegangen..