aktion Uhr-Modul-gesteuert soll nur ein Mal starten und nicht die ganze Minute

Hallo zusammen,

ich finde keine Lösung für folgendes Problem:

bei Uhrzeit1 soll die Pumpe 1 nur ein mal ein- und ausgeschaltet werden
bei Uhrzeit2 soll die Pumpe 2 nur ein mal ein- und ausgeschaltet werden
bei Uhrzeit3 soll die Pumpe 3 nur ein mal ein- und ausgeschaltet werden

außerdem soll die aktuelle Uhrzeit, sowie die Uhrzeit der nächste Messung am Display angezeigt werden.

Das funktioniert bestens, allerdings die ganze Minute lang, d.h.: die Pumpe geht die ganze Minute an und aus.
Es sollte allerdings, beim erreichen der Uhrzeit, die jeweilige Pumpe nur ein Mal ein- und ausgeschaltet werden.

Da den Rest des Sketches von einige Sekunden bis über mehreren Minuten laufen kann, kann ich die Uhrzeit nicht auf die Sekunde einschränken.
In Wirklichkeit hätten die Zeitspannen zwischen den Uhrzeiten mehreren Stunden.

Ich wusste nicht wo ich ein Merker setzen könnte, oder wo ich es wieder wegnehmen sollte, damit die anderen Uhrzeiten auch ein Mal laufen....

Hat jemand eine Ahnung wie ich es zum laufen bringen soll?

hier mein Sketch: (ich weiß... der ist nicht sparsam programmiert....

#include <SPI.h>
#include <Wire.h>
#include <DS3231.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);
DS3231 rtc(SDA, SCL);
int Pumpe[3] = {3,5,7};
int ZAELER = 0;
int NM=0;
//char Bescheid=("mach");
int Flag=1;
int i=0;
//++++++++++++++++++++++++++++++
char* UhrzeitStart[]={"21:45", "21:46", "21:47"}; // Die Uhrzeiten wo die Pumpen starten sollen
#define NUMSTRINGS (sizeof(UhrzeitStart)/sizeof(UhrzeitStart[0]))


//++++++++++++++++++++++++++++++

void setup() {
 // put your setup code here, to run once:
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
rtc.begin(); 
display.clearDisplay();
//Setze Pins outputs
 for (int i = 0; i < 3; i++)
 {
 pinMode (Pumpe[i], OUTPUT);
 digitalWrite (Pumpe[i], LOW);   
}
NaechsteMessung(NM);
}
void NaechsteMessung(int NM){ 
 display.fillRect(50,19,30,8, BLACK); // Füllen Rechteck  X,Y,Breite,Hohe,Farbe zum Löschen
   display.display();
 display.setTextColor(WHITE);
 display.setTextSize(1);
 display.setCursor(50,19);
 display.println(UhrzeitStart[NM]); // Schreibe Uhrzeit der Nächste Messung
 display.display();
}
void Duhrzeit(){ 
 display.fillRect(1,0,30,8, BLACK); // Füllen Rechteck  X,Y,Breite,Hohe,Farbe zum Löschen
   display.display();
 display.setTextColor(WHITE);
 display.setTextSize(1);
 display.setCursor(1,0);
 display.println(rtc.getTimeStr(FORMAT_SHORT));// Uhrzeit schreiben
 display.display();
}
void pumpen(int i,int NM){

 digitalWrite(Pumpe[i], HIGH); // Spannung an Pumpe X
   delay(1000); //  warte eine Sekunde
   digitalWrite(Pumpe[i], LOW); // Pumpe X ausschalten

}
//void vergleichen(int Flagge){
void vergleichen(){
  
for (int i=0;i<NUMSTRINGS;i++)
 
  if (strcmp(UhrzeitStart[i], rtc.getTimeStr(FORMAT_SHORT))==0)
   {
    pumpen(i,NM);
    int NM=i+1;
         NaechsteMessung(NM);
    if (NM==(NUMSTRINGS)) { // Anzahl de verschiedene Start-Uhrzeiten
     int NM=0;
     NaechsteMessung(NM); //Wenn 3. Uhrzeit vorbei ist, dann wieder von vorne
           
    }
    
    }
      
}
void loop() {
 Duhrzeit();
 delay(1000);
 vergleichen();
      }

Setze Deinen Sketch bitte in Codetags (</> oben linkls im Forumseditor) damit ihn jeder lesen kann, auch auf mobilen Devices.

Was meinst Du mit:

bei Uhrzeit1 soll die Pumpe 1 nur ein mal ein- und ausgeschaltet werden

Wenn ich sie ein und gleich wieder aus schalte, hat das wohl keinen sinnvollen Effekt. Hier musst Du Deine Beschreibung etwas genauer formulieren. Beschreibe doch mal, was das werden soll.

Gruß Tommy

cateyes:
... ich finde keine Lösung für folgendes Problem: ...

Ich habe Deinen Sketch nicht gelesen (nicht mal „quer“). Wenn er in Code-Tags stünde, wäre das anders.

Was Du beschreibst, lässt mich sofort an einen „endlichen Automaten“ denken. Was mir dazu eingefallen ist, habe ich hier ins Netz gekippt. Beachte ggf. auch die Folgeseite.

HTH

Gregor

Hallo zusammen,

erstmal vielen Dank an alle für eure Mühe.
Ich teste immer ein neues Vorgang in ein neuen Sketch, bevor ich dieser im eigentlichen Sketch integriere, so kann ich schneller die Fehler finden. Deshalb scheint eine Pumpe die nur ein Mal an uns aus geht, sinnfrei oder "ominös", wie kulturbereicherer sie nennt. :wink:

@ Tommy56:

hab mein Code in Codetags gesetzt. Jetzt sieht es auch übersichtlicher aus. Sorry an alle, dass den Code mobil nicht lesbar war.

Das ganze wird eine (von viele) Bewässerungsanlagen werden. Das Pumpen simuliert den ganzen Vorgang (messen, ggf. pumpen, warten auf versickern, messen, Level Tank anzeigen, ggf. nachpumpen......)
Der ganze Vorgang wird also unterschiedlich lang werden, deshalb kann die Uhrzeit nicht sekundengenau sein.

@ gregorss:

ich glaube die ist die einzige Lösung, der Code muss immer laufen, dann kann eine Uhrzeit sekundengenau erfolgen.
Ich habe viel darüber gelesen, aber nie wirklich verstanden wie es funktioniert... Deine Erklärung finde ich allerdings sehr verständlich erklärt. Kompliment! :slight_smile:
So wie ich verstehe, brauche ich allerdings eine Variable pro gezeiteter Schaltvorgang. Ich habe in mein kompletten Sketch sehr viele Schaltvorgänge mit Delay. Dann werde ich sehr viele Variablen brauchen und das ganzen muss getimed werden. >> ANGST <<
Ich werde aber doch versuchen, eventuelle Fragen werde ich in ein anderen Thread stellen, sonst wird es OT hier. Oder ?

@ kulturbereicherer:

Genauso... Du hast es verstanden was ich meine.
Sekundengenau scheidet aus (s.o.)
die 2. Möglichkeit habe ich ausprobiert, aber da eine for-Schleife alle Pumpen und die Uhrzeiten steuert, hat es nicht funktioniert: die erste Pumpe ging an und aus, die anderen blieben aus.
Achtung: der Sketch soll (und tut) bei der erste Uhrzeit die Pumpe 1 steuern, bei der 2. Uhrzeit die Pumpe 2 steuern....usw.

Die 3. Möglichkeit ist auch eine Lösung die ich für machbar halte, aber sehr, sehr unsauber. Wenn mit milli() scheitern sollte wird das mein "Notausgang" sein.

WoW! Das ist eine nette Bibliothek!!!

Hätte ich vor ein paar Tagen gerne gehabt! Ich dachte zuerst, dass eine Zeit gesteuerte Aufgabe zu programmieren trivial sei. Da lag ich wohl total daneben, wenn Profis für Laien eine Bibliothek dafür schreiben.

Der Verzicht auf Delay wäre das Beste, denn es ist nicht nur für diesen Projekt eine Lösung, sondern auch für alle Projekte.

In diese Bibliothek ist der Befehl Alarm.delay auch sehr interessant. Zwar scheint es genauso zu funktionieren wie die delay Funktion, aber er schaut auf die Alarme währenddessen.
Selbst in einer while Schleife kann man durch den Einbau in der Schleife von alarm.delay(0), eine zeitverzögerungsfreie Kontrolle der Alarme.

Eigentlich... Perfekt! (Wenn es funktioniert)

Dieser Thread war für mich eine echte Bereicherung.

Dank Tommy56 werde ich meine codetags immer setzen, damit mein Code auch mobil gelesen werden kann, Dank gregorss habe ich endlich die Benutzung von millis() verstanden und werde in meine zukünftige Projekte benutzen, dank dir habe ich eine perfekte Bibliothek gefunden, die mir viel Zeit erspart und wahrscheinlich mein Problem löst.

Liebe Grüße an alle und guten Rutsch ins neue Jahr!!!

Also, dank der Alarmbibliothek konnte ich tatsächlich mein Problem lösen!
Danke nochmal an kulturbereicherer.
nicht nur das... Durch den Befehl alarm.delay habe ich das Programm so geändert, dass es praktisch immer läuft, "fast" wie bei milli....Aber nur fast...
Ehrlich gesagt, war mir zu kompliziert die ganze Programmarchitektur zu ändern damit das Program völlig verzögerungsfrei läuft.
So habe ich mehr erreicht als ich wollte und eine Menge dazu gelernt.
Also... Fall Dank euch GELÖST!!