Arduino stoppt nach ca. 5 minuten im Schlaf

Guten Morgen,
folgender Code:

while(sleep==true){
      u8g.firstPage();  
      do {
        drawSleep();
      } while( u8g.nextPage() );
      LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
      adjustTime(1);
      }

aktualisiert jede sekunde das display um 1 sekunde. Jedoch stellte ich fest, dass nach ca 4-5 Minuten das Programm auf unerklärliche weise stoppt. Ist das ein bug? wie kann ich ihn beheben? Wird vielleicht irgend ein speicher voll geschrieben?
Danke für die Antworten.
LG Tim

EDIT(LÖSUNG): Wenn man die RTC als syncProvider eingestellt hat, wird standartmäßig nach 300 sekunden die Zeit automatisch abgefragt. Sollte hierbei das RTC aus sein, so wie bei mir, da ich es via Pin einschaten wollte, stockt das Program. Also zum manuellen Update setTime(RTC.get()); benutzen

Wenn dein Programm ein unerwartetes Verhalten zeigt, dann ist das ein Bug.
Vermutlich ein Bug in deinem Programm.

Ob Speicher (über)voll geschrieben wird?
KA...

Beheben?
Erstmal Finden!

Programm reduzieren!

Der arduino stoppt, nachdem er 5 min dieser Schleife ist. Ich habe auch über prüft, die Schleife wird nicht beendet und an der LowPower library liegt es auch nicht, denn ich habe diese mal kurz durch delay(1000) ersetzt.

denn ich habe diese mal kurz durch delay(1000) ersetzt.

MasterTim17:
denn ich habe diese mal kurz durch delay(1000) ersetzt.

Und, ist das Problem dann weg, oder bleibt dein Arduino dann auch stehen?

Ums mal klar zu sagen:
Offensichtlich willst du nicht den ganzen Code zeigen!
Offensichtlich willst du den Code nicht reduzieren.
Du stellst keine testbare Version zur Verfügung.

Und jetzt soll ich (oder ein anderer) dir sagen, was schief läuft?

Kann ich machen:
Das größte Problem befindet sich meist vor dem Monitor.

Es tut mir leid, wenn das jetzt etwas grob war....
Aber wie soll ich dir sonst klar machen, dass so keine Hilfe möglich ist....?

Vergleichbar mit:
Frage: "Hilfe mein Auto springt nicht an!"

Gegenfragen:
Was für ein Auto?
Dreht der Anlasser?

Antwort:
"Ein Auto! Mit 4 Rädern halt, wie alle!"

Wie soll das was werden?

MasterTim17:
Guten Morgen,
folgender Code:

while(sleep==true){

u8g.firstPage(); 
      do {
        drawSleep();
      } while( u8g.nextPage() );
      LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
      adjustTime(1);
      }



aktualisiert jede sekunde das display um 1 sekunde. 
LG Tim

Der Code fängt mit folgenden Fehlern an:
-Die Variable sleep ist undefiniert
-Falls sie je irgendwo geändert wird, jedenfalls nicht in deinem Code.
-u8g ist undefiniert. ( sollen wir raten, was das sein könnte ? )
-drawSleep() Definition fehlt

  • ...

Um einen Sketch zu schreiben, der super läuft, aber nach 32,678 oder nach 65 Sekunden hängen bleibt, braucht es ganz wenig. 5 Minuten sollte aber auch machbar sein.

Warum schreibst du übrigens eine eigene Schleife, wenn eine Schleife (loop) so ungefähr das wichtigste ist, was das Arduino System bietet?

Der Code stammt aus einem programm.
Ich habe das wichtigste zusammengefasst:

#include <LowPower.h>
#include <Time.h>
#include <U8glib.h>
U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9, 8);  // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
boolean sleep = true;
unsigned long prevTime = 0;


void setup() {
  // put your setup code here, to run once:
  u8g.setFont(u8g_font_6x12);
  pinMode(2,INPUT_PULLUP);
}

void strDraw(int x,int y,String text){
  u8g.setPrintPos(x,y);
  u8g.print(text);
}

void drawSleep(){
  
  String hours = (hour()<10)?"0"+String(hour()):String(hour());
  String minutes = (minute()<10)?"0"+String(minute()):String(minute());
  String seconds = (second()<10)?"0"+String(second()):String(second());
  
  u8g.setFont(u8g_font_fur17n);
  strDraw(0,35,hours+":"+minutes+":"+seconds);
}

void interrupt (){
  sleep=false;
}

void loop() {
  // put your main code here, to run repeatedly:
  if(millis() - prevTime > (long)(2000) ){
    attachInterrupt(0, interrupt, LOW);
    sleep=true;
    
      while(sleep==true){
      u8g.firstPage();  
      do {
        drawSleep();
      } while( u8g.nextPage() );
      LowPower.powerDown(SLEEP_120MS, ADC_OFF, BOD_OFF);
      adjustTime(1);
      }

      detachInterrupt(0);
      sleep=false;
      prevTime = millis();
      delay(100);

  }
}

Jedoch funktioniert dieser Code. Ich werde nun in meinem eigentlichen Sketch nach Fehlern suchen, finde aktuell keine, da beim schlafen die schleife nicht verlassen wird. Und auch während dem Schlafen keine variable verändert wird :frowning:

EDIT: es ist hinzuzufügen dass das program nicht nach 5 minuten stoppt, sondern nach 5*60 sekunden = 300 (eine zählvariable hat ein ergebnis von 270 gebracht)durchgängen stoppt. denn ich habe den watchdog timer auf 120ms verringern und festgestellt, dass das programm nach angezeigten "5 minuten" stoppt - auf unerklärliche weise. Suche gerade vergebens nach einer lösung

sleep muss als volatile deklariert werden:
https://www.arduino.cc/en/Reference/Volatile

Wird aber nicht wirklich die Lösung hier sein

Ich werde nun in meinem eigentlichen Sketch nach Fehlern suchen, finde aktuell keine,

Ich sehe da schon einen!
Zumindest habe ich eine starke Vermutung..

Die Verwendung von (lokalen) String Objekten.
String Objekte haben schon so manchen Arduino ins straucheln gebracht.

du meinst in der drawSleep(); Funktion?

Jedoch funktioniert dieser Code

Dann kann ein Arduino inzwischen wohl auch diese String-Orgie überleben.

Und wie sieht nun der Code aus, der nicht funktioniert ?

Dann kann ein Arduino inzwischen wohl auch diese String-Orgie überleben.

Es gab da mal ein Speicherleck, aber das wurde schon vor langer Zeit ausgebessert.

Aber wenn man weiß was da gemacht wird, wird einem immer noch schlecht. Wenn Strings wenigstens halbwegs vernünftig verwendet wären...
Also erst mal mit reserve() Speicher reservieren und danach erst konkatenieren. Aber das macht niemand. Und auch denn werden noch temporäre Objekte angelegt und gleich wieder zerstört.

Besser:

char buffer[10];
snprintf_P(buffer, sizeof(buffer), PSTR("%02d:%02d:%02d"), hour(), minute(), second());

Danach hast du die Zeit in buffer stehen

Auch sowas ist Blödsinn:

void strDraw(int x,int y,String text)

Objekte übergibt man mit einer Referenz damit das ganze nicht nochmal kopiert wird. Das Problem fällt auch weg wenn man char Arrays hat, da man dann automatisch einen char* als Parameter hat (oder besser einen const char*)

Aber das wird Kosmetik sein. Es ist hier überhaupt nicht klar was der Unterschied ist zwischen dem Programm das funktioniert und dem das den Fehler produziert!

könnte das hier: https://learn.adafruit.com/system/assets/assets/000/010/353/medium800/learn_arduino_Stack_Operation.gif?1396903775 in meinem script der fall sein?

und ein string ist einfach ein eindimensionales char array? also kann ich so alle strings abändern?

Wenn das alles ist solltest du eigentlich keine Probleme mit dem RAM haben. String Objekte können durch die exzessive Verwendung von dynamischem Speicher den Heap fragmentieren, aber dadurch sollte es eigentlich auch nicht gleich abstürzen.

MasterTim17:
und ein string ist einfach ein eindimensionales char array? also kann ich so alle strings abändern?

Ein C String ist ein Null-terminiertes char Array. Ein Puffer muss daher mindestens 1 größer als der sichtbare String sein. C Strings sind aber was anderes. Da kannst du nicht einfach Teil-Strings mit + zusammenfügen, oder direkt einen int konvertieren.

Wie gesagt, macht mal den Unterschied zwischen den zwei Versionen klar. Du sagst eins geht, aber das andere nicht. Die sehen aber gleich aus.

Manchmal findet man die Fehler an der ungewöhnlichesten Stelle O.o
Ich habe in meinem Projekt noch ein DS3231 Chip verbaut (und an I2C angeschlossen), welchen ich über pin 7 an und ausschalte:

pinMode(rtcPin,OUTPUT);

...

void getTime(){
digitalWrite(rtcPin,HIGH);
setSyncProvider(RTC.get);
digitalWrite(rtcPin,LOW);
}

diese funktion getTime() rufe ich im setup auf und dies bringt meinen arduino dazu nach 280 schleifendurchläufen anzuhalten. Dabei bringe ich doch nur die Zeit auf aktuellen Stand :open_mouth:

ein string ist einfach ein eindimensionales char array? also kann ich so alle strings abändern?

Ja, nur würde ich zur Vermeidung einer Verwechslung mit einem String - Objekt (was nicht geändert werden kann und den Heap fragmentiert), das "gute" char Array nennen.

In deinem Fall brauchst du nicht mal dynamisch die ':' einzusetzen.

void DrawTime() {
  static char ttext[9] = "12:34:56"
  u8g.setFont(u8g_font_fur17n);
  setDec(ttext+0, hour);
  setDec(ttext+3, minute);
  setDec(ttext+6, second); 
  strDraw(0,35,ttext); 
}


void setDec(char* target, byte x) {
// put 2 bytes "00" .. "99" to location target and target+1
  byte hi = x/10;
  byte lo = x%10;
  *target++ = hi + '0';
  *target = lo + '0';
}

(und schau dir mal die Code-Größe an ohne String Objekte )

Das ergibt auch keinen Sinn. setSynchProvider() gibt nur nur die Funktion an mit der sich der µC mit der RTC synchronisiert. Wenn man dann hour(), minute(), etc. macht und die Sync Zeit ist abgelaufen wird automatisch RTC.get() aufgerufen um die lokale Zeit mit der RTC abzugleichen.

Du kannst das ganze noch vereinfachen (oder übertreiben), indem du deine RTC direkt mit Wire.h ausliest.
Da sind die Werte schon "ausgabefertig" als BCD-bytes vorhanden und du kannst dir sogar das /10 teilen sparen ( >>4 ist nämlich erheblich einfacher ) :wink:

Komplexe Time-Libraries (setSyncProvider) sind fast so schlimm wie String-Objekte, finde ich.
Anfänger freuen sich, "mächtige" Werkzeuge zur Verfügung zu haben, und oft geht es auch gut.
Aber wenn man nicht weiss, was da passiert, braucht man eben Glück, dass der Beispielcode zum Rest passt.

Das ist das problem! Die time Library versucht zu synchronisieren,aber wegen nicht angeschaltetem RTC funktioniert es nicht. Würde auch mit der Zeit/Schleifendurchläufe passen, denn die syncTime liegt standartmäßig bei 300 :smiley:
Wie kann ich die Time library weiterhin verwenden und manuell die Zeit updaten, also ohne syncProvider?

Eine weitere Frage wegen u8glib: in der dortigen drawStr anweisung ist ein char pointer hinterlegt.
wie kann ich zum beispiel jetzt folgendes umschreiben:
u8g.drawStr(0,10,"hallo"+"s");
Da dies nicht funktioniert habe ich meine strDraw funktion geschrieben.

setSynchProvider() gibt nur nur die Funktion an .... wird automatisch RTC.get()

Das funktioniert?
So einfach ist das mit "Methoden als Callback", wohl nicht!

wie kann ich zum beispiel jetzt folgendes umschreiben:
u8g.drawStr(0,10,"hallo"+"s");

Wie kommst du darauf, dass "hallo"+"s" das gleiche wie "hallos" sei ?

"hallo" + 1 ist übrigens "allo" :wink:

In schweren Fällen, wenn du es tatsächlich so brauchst, gibt es strcat(), strcpy, usw.