Aquariumcontroller: hängt sich auf / stürzt ab / friert ein - Hilfe!

Hallo Zusammen,

vorab sei gesagt, dass ich seit ca. 6 Monaten aktiv hier mitlese, und dadurch sehr viel gernt und gelöst habe.Danke euch!
Diesmal konnte aber auch die SuFu mir nicht weiterhelfen...!

Ich habe mir einen in den letzten Monaten einen Aquarium Controller entwickelt.
Hierbei kommt folgende Hardware zum Einsatz:

  • Arduino Mega 2560

Spannungsversorgung über NT mit 9v 500mAh oder USB

  • Ethernet Shield W5100 mit SD-Steckplatz
  • 2 Kanal SainSmart Relais Karte (in 2 geteilt)
  • DS18S20 1-Wire Temperatur-Sensor
  • EVG von Phillips(Artikelnummer: PH-91008030), 2x54w T5, Dimmbar, steuerung mit 3 GoldCaps via Relay
  • LCD 1602 (nicht I2C)
  • RTC DS1307 via I2C
  • 4 Taster mit vorwiderständen, an Analog

Mein Problem ist, das in unregelmäßigen abständen (meisst nach 1-3h) alles einfriert. Durch drücken auf "reset" gehts dann wieder weiter.

  • problem besteht auch wenn keine Relais & kein Lan angeschlossen sind,
  • getestet mit verschieden Spannungsversorgungen (USB, Netzteil, Batterien)
    -hatte den Speicher im Verdacht, daher alle Strings mit dem "F() syntax" in den Flash verschoben.
    Alles ohne entgültigen Erfolg....

Im Anhang findet Ihr den kompletten Code, als .txt & .ino (ist zu lang zum einfügen :blush:).
EDIT: Nur als .ino & .pdf angehängt, die .txt war fehlerhaft.
** Die .ino ist mit Arduino 1.02 geschrieben wurden.**
Hier ein Link zu einer Online Version:
AQ Arduino - Pastebin.com

Vielleicht findet Ihr ja den/die Fehler und könnt mi helfen?!
Auch über Verbesserungsvorschläge freue ich mich!

Vielen Dank & viele Grüße,

Max

AQ_Rly_Dm_lcd_lan_1_wire_18_11_12.ino (32 KB)

AQ_Rly_Dm_lcd_lan_1_wire_18_11_12.pdf (54.8 KB)

So einen fehler hatte ich beim meniem QlockTwo Coline Project. Nach 1 Woche suche habe ich mich entschieden mit eriner Wtachdog zu arbeiten (2s). Aber dafür den Bootloader rausgeworfen damit es keine Anlaufverzögerung gibt.
Ich weiß kein sinnvoller Tip zu Ursachen Lösung aber damit kann man die Auswirkungen "beheben".

Gruß
Der Dani

Hallo,

du hast geschrieben du hast die Strings mit der "F() syntax" in den Flach verschoben. Was ist das und wo findet man das in deinem Code (ich hab mir den AQ Arduino - Pastebin.com angeschaut)? Hast du mal mit Arduino Playground - AvailableMemory den verfügbaren Arbeitsspeicher ausgeben lassen? Um "Strings" in den Flash zu schieben kenne ich nur PROGMEM - Arduino Reference . Dann solltest du keine Strings verwenden sondern Char-Arrays (zumal dein LCD sowieso eine feste Zeilengröße hat).

Dann ist mir noch das hier aufgefallen:

 //Umrechnung, damit die Temperatur mit Komma via der Variable "temperaturwert übermittelt werden kann.
  int zahl0=(int) celsius;
 
  zahl0 *= 100;
 
  float zahl1= celsius *100;
 
  int zahl2 = (int) zahl1;
 
  int nachkommastellen = zahl2 - zahl0;
 
  int vorkommastellen = (int) celsius;
 
  String temperaturwert; //Erstellt Zeichenkette der Temperatur mit Kommastellen, die später in die Übertragungszeichenkette eingefügt wird.
 
  temperaturwert+="";//löscht letzten Inhalt des Strings
  temperaturwert +=vorkommastellen;
 
  temperaturwert += ",";
 
  temperaturwert +=nachkommastellen;

Das kannst du mit fprintf in einer Zeile machen.

Bezüglich F():

http://arduino.cc/playground/Main/Printf
http://arduino.cc/playground/Learning/Memory
Grüße Uwe

Zwei Sachen, die mir aufgefallen sind:

  • Du verwendest das F()-Makro nur für die lcd.print()s, bei den Serial.print()s aber nicht. Wieso? Das funktioniert bei allen Klassen, die von der Print-Klasse erben. Damit kannst Du RAM sparen.

  • Eliminiere komplett die String-Klasse. Für einen HelloWorld-Sketch mag die ganz nett sein, aber in einem Sketch, der 24/7 laufen soll, hat sie nichts, gar nichts verloren. Im besten Fall fragmentiert sie den Speicher so lange, bis keine genügend grossen Stück mehr frei sind, was zu unvorhersehbaren Zuständen führen kann. Zudem haben die aktuellen IDEs (besser: die zugehörige C-Bibliothek) einen Bug in der free()-Funktion, was zu einem Memory-Leak führt. Da die String-Klasse intensivsten Gebrauch davon macht, verlierst Du über die Zeit immer mehr RAM, bis Dein Arduino irgendwann unkontrolliert steht oder mit viel Glück neu startet.
    Schreibe den Teil mit den zwei Strings in eine Version um, wo Du nur noch char-Arrays verwendest, dann wird Dein Sketch wahrscheinlich schon viel stabiler laufen.

Nabend,

also vorab ein Paar Antworten;

@Dani
Eine Watchdog-Lösung habe ich mir auch schon angesehen, möchte ich aber als Notlösung reservieren.

@cicuit99
Habe eben mir eben mal die Char-Array anstelle von Strings durchgelesen und durchgedacht - werde das mal umsetzen und das Ergebniss posten!
Die Frage nach dem "F()" hat Uwe ja schon beantwortet - DANKE.

"fprintf" kannte ich nicht, habe es mir eben im Playground angesehen. Worin besteht der Vorteil dieser Funktion gegenüber der "alten" Lösung?

@pylon
Stimmt. Das F()-Makro verwende ich nur bei den LCD.print, weil ich (eigentlich) den seriellen Port nicht nutzen wollte.
Char-Arrays antelle von Strings - werde ich umsetzen und das Ergebniss posten!

  • Zusätzlich werde ich Prüfpunkte implementieren, um zu sehen wo genau alles abstürzt & die Zeiten einfach mal per Stopuhr aufnehmen...

Danke für die Zahlreichen Antworten!
Schreibt gerne weitere Vorschläge, ich poste (hoffentlich) morgen neue Fakten zum geänderten & angepassten Code.

Gute Nacht,

Max

Falls es nicht am Ram / den Strings liegt, dann ist die spannende Frage wo genau er einfriert. Dazu würde ich ein paar LEDs an die freien Pins hängen und in verschiedenen Programmteilen verschiedene Muster reinschreiben. Je nachdem welches Muster am Ende drinsteht kann man so die Ursache nach und nach eingrenzen. Wenn es immer die gleiche Stelle ist --> gut. Wenn nicht --> schlecht, Speicherproblem oder vieleicht Netzwerkproblem. Gerade Netzwerkcode ist immer verdächtig. Insbesondere auch dann wenn keine Netzwerkverbindung da ist.

Hallo,

ich werde es zeitlich nicht vor Freitag schaffen, eure Tips & Hilfestellungen zu implementieren.

Wie versprochen, melde ich mich dann aber mit Resultaten, Feedback & dem neuem Code.

Danke & Gruß,

Max

pylon:

  • Eliminiere komplett die String-Klasse. Für einen HelloWorld-Sketch mag die ganz nett sein, aber in einem Sketch, der 24/7 laufen soll, hat sie nichts, gar nichts verloren. Im besten Fall fragmentiert sie den Speicher so lange, bis keine genügend grossen Stück mehr frei sind, was zu unvorhersehbaren Zuständen führen kann. Zudem haben die aktuellen IDEs (besser: die zugehörige C-Bibliothek) einen Bug in der free()-Funktion, was zu einem Memory-Leak führt. Da die String-Klasse intensivsten Gebrauch davon macht, verlierst Du über die Zeit immer mehr RAM, bis Dein Arduino irgendwann unkontrolliert steht oder mit viel Glück neu startet.
    Schreibe den Teil mit den zwei Strings in eine Version um, wo Du nur noch char-Arrays verwendest, dann wird Dein Sketch wahrscheinlich schon viel stabiler laufen.

Puuuh, String einsetzen ist also nicht so dolle.... Ich optimiere an meinem Code seit Wochen und kriege immer wieder und nicht nachvollziehbare bzw. eingrenzbare Abstürze des Mega bzw. LCD (Über I2C gesteuert, daran hängt auch ein Keypad, abgegriffen ebenfalls über I2C). Ich habe gedacht, dass die Entfernung der beiden zum Mega das Problem ist, bei Verringerung des Takts ändert sich nichts und die unvorhersehbaren Abstürze blieben. Nun pushe ich die Daten zu Cosm und setze dabei Strings ein - eine Methode übernimmt den String als Parameter, der aus der Loop kommt.

Ich nutze die Version 0023, ist diese bitte auch von dem Bug betroffen - sodass dies die Quelle des Unheils sein könnte?

Viele Grüße
Michael

Ich nutze die Version 0023, ist diese bitte auch von dem Bug betroffen - sodass dies die Quelle des Unheils sein könnte?

Keine Ahnung, ob bei der Version 0023 der free()-Bug auch schon vorhanden war, aber eine so alte Version einzusetzen ist sowieso keine gute Idee, vor allem mit dem Ethernet-Shield nicht, da dort bis zur Version 1.0.1 auch einige Bugs enthalten waren.

Selbst wenn der free()-Bug dort nicht drin wäre, das grundsätzliche String-Problem mit dem fragmentierten Speicher bleibt bestehen, somit ist die String-Klasse für Systeme, die mehr als ein paar Durchläufe der Hauptschleife überstehen sollen, gar nicht zu empfehlen. Das Bisschen Bequemlichkeit ist den Ärger nie und nimmer wert.

pylon:
Selbst wenn der free()-Bug dort nicht drin wäre, das grundsätzliche String-Problem mit dem fragmentierten Speicher bleibt bestehen, somit ist die String-Klasse für Systeme, die mehr als ein paar Durchläufe der Hauptschleife überstehen sollen, gar nicht zu empfehlen. Das Bisschen Bequemlichkeit ist den Ärger nie und nimmer wert.

Guten Abend,

danke für die Anregung, auf eine aktuelle IDE-Version umzusteigen. Als ich mein Projekt begann, gab es für meinen I2C-LCD noch keine passende Library für 1.0 oder 1.0.1. Daher habe ich die 0023 eingesetzt. Jetzt bin ich nach einem Tag herumsuchen mit meinen Nerven am Ende - aber unter 1.0.2 es scheint alles wieder wie vorher zu laufen. Vielleicht läuft mein Sketch jetzt stabil - ich hoffe zuerst, auch mit unter Einsatz der String-Klasse. Und wenn nicht, ist diese als nächste dran. (Und ich dachte zuerst "Never touch a running system" - aber eigentlich war es kein "running system", insoweit danke für die Anregung :wink:

Viele Grüße
Michael

pylon:
Selbst wenn der free()-Bug dort nicht drin wäre, das grundsätzliche String-Problem mit dem fragmentierten Speicher bleibt bestehen, somit ist die String-Klasse für Systeme, die mehr als ein paar Durchläufe der Hauptschleife überstehen sollen, gar nicht zu empfehlen. Das Bisschen Bequemlichkeit ist den Ärger nie und nimmer wert.

Guten Abend,

bin gerade dabei, alle Strings aus meinem Sketch zu beseitigen - habe bitte eine Frage:
Die Stringinstanz habe ich rausgeworfen und arbeite mit Chararrays, wie empfohlen.
Aber wenn ich Strings an meinen LCD schicke, lcd.print("blablabla"), bastelt der Arduino da nicht auch "irgendwie" mit Strings herum? Oder schiebe ich nur unnötig Panik ;-), denn dieses Zeug aus dem Sketch zu tilgen, wäre ein richtiger "Act" ?

Grüße
Michael

Danke!!!

Es läuft alles wie nie zuvor! Dank euerer Hilfe habe ich mein Problem lösen können.
Der Sketch / der Code läuft seit gestern ohne probleme. Auch die Übertragung zu Google klappt super. Genial!

Die Ursache war, wie bereits von mehreren Leuten vermutet; die Lösung "Char-Arrays" anstelle von Strings einzusetzen, als snsprintf Variante.

Mit Hilfe von Prüfpunkten, wurde der Fehler schnell lokalisiert, und der Code angepasst.

HIER der Link für den funktionierenden Code:

http://pastebin.com/eFW7ys4t

PS: Ein kleines Problem bleibt jedoch, die RTC läuft irgendwie nicht weiter wenn ich die Spannungsversorgung trenne. Sie merkt sich nur die Uhrzeit, wann ich das letzte mal die Uhr eingestellt habe, und startet dann wieder mit dieser Uhrzeit.
Aber dafür finde ich/wir bestimmt auch noch eine Lösung.

Noch mal an dieser Stelle:

DANKE für eure unermüdliche Hilfe, eure Tips und Ratschläge!

Max

handyfreak:
PS: Ein kleines Problem bleibt jedoch, die RTC läuft irgendwie nicht weiter wenn ich die Spannungsversorgung trenne. Sie merkt sich nur die Uhrzeit, wann ich das letzte mal die Uhr eingestellt habe, und startet dann wieder mit dieser Uhrzeit.

Ist die Buffer-Batterie fast leer?

Grüße Uwe

Ich würde mal vermuten das es an folgender Zeile in Deinem setup() liegt:

   RTC.begin(DateTime(__DATE__, __TIME__));

DATE und TIME sind Konstanten, die der Compiler (genauer gesagt der Präprozessor ... da ist er wieder, mein Perfektionismus) zum Zeitpunkt an dem das Programm übersetzt wird durch reale Werte ersetzt.
Damit wird bei jedem Start des Arduino die Zeit wieder auf diese Werte gesetzt, weil be jedem Neustart auch wieder die setup() Funktion aufgerufen wird.

Aber wenn ich Strings an meinen LCD schicke, lcd.print("blablabla"), bastelt der Arduino da nicht auch "irgendwie" mit Strings herum?

Nein: "blablabla" ist kein String, sondern ein const char [10].

void setup()
{
  int len = sizeof("blablabla");
  len = sizeof("blablabla"+"puuup");
}
void loop() {}

gibt endlich mal eine ordentliche Fehlermeldung:

invalid operands of types 'const char [10]' and 'const char [6]' to binary 'operator+'

michael_x:
Nein: "blablabla" ist kein String, sondern ein const char [10].

Michael, alles klar, danke!

Grüße
Michael