Go Down

Topic: Eine if Schleife nur alle 5 Minuten durchlaufen (Read 819 times) previous topic - next topic

Rudi01

Hallo

ich möchte die unten gezeigte Schleife nur alle 5 Minuten 1X abarbeiten. Währen der restlichen Zeit sollte der Sketch aber auch abgearbeitet werden ein Delay scheidet als aus.
Weiß jemand eine Funktion mit der ich das bewerkstellen kann?


Code: [Select]

  //Stufe1 wird berechnet
  if ((tempS1 <= TempSpeicher47) && (tempS2 <= TempSpeicher35))
  {
    (Stufe = 1);
  }


  //Stufe2 wird berechnet
  if ((tempS1 > TempSpeicher47) && (tempS2 <= TempSpeicher35))
  {
    (Stufe = 2);
  }

  //Stufe3 wird berechnet
  if (((tempS1 > TempSpeicher47) && (tempS1 <= TempSpeicher50)) && ((tempS2 > TempSpeicher35) && (tempS2 <= TempSpeicher50)))
  {
    (Stufe = 3);
  }

  //Stufe4 wird berechnet
  if (((tempS1 > TempSpeicher50) && (tempS1 <= TempSpeicher75)) && ((tempS2 > TempSpeicher35) && (tempS2 <= TempSpeicher50)))
  {
    (Stufe = 4);
  }

  //Stufe5 wird berechnet
  if (((tempS1 > TempSpeicher50) && (tempS1 <= TempSpeicher75)) && ((tempS2 > TempSpeicher50) && (tempS2 <= TempSpeicher75)))
  {
    (Stufe = 5);
  }

  //Stufe6 wird berechnet
  if ((tempS1 > TempSpeicher75) && ((tempS2 > TempSpeicher50) && (tempS2 <= TempSpeicher75)))
  {
    (Stufe = 6);
  }

  //Stufe7 wird berechnet
  if ((tempS1 > TempSpeicher85) && (tempS2 > TempSpeicher75))
  {
    (Stufe = 7);
  }


den gesammten Code hänge ich noch an

Vielen Dank Rudi

jurs


ich möchte die unten gezeigte Schleife nur alle 5 Minuten 1X abarbeiten. Währen der restlichen Zeit sollte der Sketch aber auch abgearbeitet werden ein Delay scheidet als aus.
Weiß jemand eine Funktion mit der ich das bewerkstellen kann?


Mit millis() aus dem Arduino-Takt, ohne Echtzeit-Uhr?

Code: [Select]
unsigned long SecondsRunning()
// Liefert die Sekunden seit Programmstart zurück
// Diese Funktion muss in der loop laufend aufgerufen werden
{ // Sekundenzähler
  static unsigned long secondsCounted=0;
  static unsigned long prevMillis=0;
  while( millis() - prevMillis >= 1000){     
    secondsCounted++;
    prevMillis += 1000;
  }
  return secondsCounted;
}


void setup() {
  Serial.begin(9600);
}

unsigned long lastSeconds, thisSeconds;
int intervall=300; // Intervalldauer in Sekunden
void loop() {
  thisSeconds=SecondsRunning();
  if (thisSeconds>=lastSeconds+intervall)
  {
    lastSeconds+=intervall;
    Serial.print(intervall);Serial.println(" Sekunden sind um!");
  } 
}

jn-wp

Hi Rudi!

Also für mich hört sich das nach dem klassischen "blink without delay"-Fall an. Gugg mal das Beispiel hier an, danach sollte es klar sein:

http://arduino.cc/en/Tutorial/BlinkWithoutDelay

Viel Erfolg!

uwefed

Dei loop() funktion wirst Du nicht alle 5 Minuten aufrufen können ( das würde mit 15 mal dealy(20000) passieren),
Sondern Du kannst wie beim "blink without delay" um loop() immer wieder kontrollieren ob die 5 Minuten vorbei sind und die Funktionen ausführen oder die Funktion aufrufen die Du alle 5 Minuten haben willst. Nebenbei kannst Du im loop() nioch alles mögliche kontrollieren.

grüße Uwe

Rudi01

Hallo zusammen

es hat geklappt vielen Dank für die Hilfe.
Einen kleinen Schönheitsfehler har der Sketch noch - nach einem Reset dauert es die 5Min bis die Stufen bildung das erste mal gemacht wird . Dies bedeutet dass nach einer Neuprogramierung oder einem Stromausfall diese 5Min keine Ladung stattfindet.
Was dazuführen kann dass der Solarkollektor in Stagnation (Abschaltung wegen Übertemperatur) geht und dann bis zur Abkühlung (meist erst abends) nicht mehr in Betrieb genommen werden kann.
Eine Lösung währe also nicht schlecht.
Eventuell hat ja jemand eine Lösung.

Nochmals vielen Dank Rudi

Serenifly

Lagere den Code den du ausführen willst in eine eigene Funktion aus und Rufe diese Funktion am Ende von setup() auf. Dann wird sie einmal beim Start ausgeführt und danach zeitgesteuert.

Gibt es keinen Timer-Interrupt beim Arduino Uno?
Geht nicht, gibt es nicht!

Serenifly

Natürlich, aber eine 5-Minuten Funktion in einem Interrupt auszuführen ist Unsinn. Das macht man eher für ganz schnelle Sachen.

Auf dem Arduino läuft im Hintergrund schon auf Timer0 ein Zähler mit einem Interrupt. Und dessen Stand kann man eben mit millis() abfragen.

michael_x


Gibt es keinen Timer-Interrupt beim Arduino Uno?
Beim atmega Controller schon.
Beim "Arduino Uno" werden Timer bei Bedarf von diversen Libraries verwendet, die sich dann in die Quere kommen ;)

Aber was hat das hiermit zu tun ?

Code: [Select]
const unsigned long INTERVAL = 1000L*60* 5; // 5 Minuten
unsigned long lastRun = 0 - INTERVAL;  // damit es gleich beim Start losgeht
void loop ()
{
 if ( millis() - lastRun >= INTERVAL )
 {
   Meine5MinutenFunktion();
   lastRun += INTERVAL;
 }
}

Einfacher gehts mit Hardware-Timern nicht.

...Was wäre aber wenn der Programmcode unter der Funktion zB "void loop ()" relativ lang ist?
Würde es nicht die Gefahr bergen, dass nicht exakt bei der gwünschten Zeit (in diesemBbeispiel zb 5min) die Funktion "Meine5MinutenFunktion()" aufgerufen wird?
Geht nicht, gibt es nicht!

Serenifly

Wenn du nicht garantieren kannst, dass loop() alle 5 Minuten durchläuft ist mit deinem Design etwas völlig falsch gelaufen und du solltest den Ablauf generell überdenken.

Dann ist die Frage ob das bei 5 Minuten wirklich auf ein paar ms genau ausgeführt werden muss, oder ob es egal ist ob es vielleicht mal um 100ms schwankt.

michael_x


...Was wäre aber wenn der Programmcode unter der Funktion zB "void loop ()" relativ lang ist?
Würde es nicht die Gefahr bergen, dass nicht exakt bei der gwünschten Zeit (in diesemBbeispiel zb 5min) die Funktion "Meine5MinutenFunktion()" aufgerufen wird?

Vielen Dank für deine Vorlage, Hubert ;)

Wenn du Probleme damit hast, loop innerhalb von sagen wir mal 10 bis 50 ms durchlaufen zu lassen,
dann lass um Himmels willen die Finger von Timer-Interrupts. Die müssen nämlich in nullkommanix fertig werden, und können/dürfen daher viele Arduino-Funktionen gar nicht verwenden. Das wird dir also vermutlich nicht helfen.

Übrigens, selbst wenn sich mal was verzögert:
In meinem vorigen Beispielcode ist sichergestellt, dass Meine5MinutenFunktion() in 24 Stunden 288 Mal drankommt, und dass sich eventuelle Verzögerungen nicht aufsummieren.

Aber: Beim normalen Arduino ist die Zeit übrigens nur auf ca  0.1 %  genau, 5 Minuten können also von daher schonmal hunderte ms daneben liegen.


rudirabbit

Code: [Select]

const unsigned long INTERVAL = 1000L*60* 5; // 5 Minuten
unsigned long lastRun = 0 - INTERVAL;  // damit es gleich beim Start losgeht

Hier wird meiner Meinung nach einer unsigned Variable ein negativer Wert  (-300000) zugewiesen.
Für den Compiler wäre das dann  4294667294   (ULONG_MAX  - INTERVAL+1)

Kann aber auch sein, das dies eine C  Schreibweise ist die ich wieder mal nicht verstehe.
Also keine Kritik sondern eher eine Frage  ;)  
Arduino UNO,MEGA  Fremdgänger mit dem  Nucleo L152RE   
Dunkel die andere Seite ist. - Klappe, Yoda, und iss deinen Toast :-)

uwefed

#13
Mar 10, 2014, 07:50 pm Last Edit: Mar 10, 2014, 09:21 pm by uwefed Reason: 1
Bei einem Variablentyp ohne Vorzeichen gibt es keine negativen Werte. Da wird vom max möglichen Wert der wegzuzählende Wert subtrahiert.
Grüße Uwe

Serenifly

Die Variable läuft über. Das aber hier gewollt. Das hat den Effekt dass die Funktion gleich am Anfang ausgeführt wird, da der Wert eben > INTERVAL ist. Danach wird INTERVAL wieder dazu addiert und sie steht wieder auf 0


Go Up