Terraduino Bug (power shutdown)

Ich habe ja immer noch meinen Bug nicht behoben, der Terraduino stirbt regelmäßig.

Rein zufällig, weil mich jemand danach gefragt hatte, habe ich mir mal den Stromverbrauch des von mir benutzten 8-Kanal-Solid-State-Relais angeschaut: 160mA. Der Ethernetshield verbraucht 150 mA. Und wenn man zu viel Strom am Arduino verbraucht, passiert das:

External power is limited by the on-board regulator's over current and over temperature automatic shutdown protection circuits. How much heat dissipation for the regulator is determined by the actual current being drawn and the voltage drop across the regulator (that is DC input voltage - 5.0 X current).[emphasized by me]

Und dann habe ich das hier gefunden:

ATMEL ATMEGA2560-1280-640(MEGA) Current Specifications:

Absolute Maximum ratings:

DC Current per I/O Pin .............. 40.0 mA

DC Current VCC and GND Pins......... 200.0 mA

This apparently is saying you get 800mA to play with as there are 4 Vcc and 4 Gnd pins

Also 200 mA PRO DC Current VCC Anschluss. Und ich habe an einem Anschluss hängen:

Das erklärt auch, warum der Controller am Aquarium mit nur 2 Lampen super funktioniert: die Relaiskarte verbraucht natürlich dann nur 40 mA anstatt der 140 mA wenn er am Terrarium hängt (ich verwende 7 Kanäle: 6 Lampen und der Trafo für den Lüfter). Dass das knapp werden muss, ist ja klar. Die Lösung ist auch klar: ich muss die Relaiskarte von einem anderen VCC+GND aus mit Strom versorgen, dann sollte alles passen.

Böse Falle!

Update 2012-09-29:

Wie sich herausgestellt hat, hat das auch nichts gebracht, er ist trotzdem ausgegangen. Inzwischen habe ich L:
The 8-relay board shown here gives you a choice of powering the relay drive circuits from the same supply as Arduino, or isolating Arduino by removing the jumper over at the right. In that case you need to have some separate +5V supply connected to GND and the "JD-VCC" pin.
Ich habe auch nochmal das Datenblatt konsultiert. Die Relaiskarte hat tatsächlich 3 Stromkreise: den Laststromkreis, an den man die 220V Verbraucher hängt, den Steuerstromkreis, mit dem man via Arduino die Relais schaltet und den Stromkreis für die Optokoppler. Letzterer wird per Default vom Arduino mitversorgt, was passiert, wenn der erwähnte Jumper auf VCC und VCC-JD steckt. Dieser Stromkreis verbrät selber nochmal 400 mA bei allen geschalteten Kanälen!

Da ich im Terraduino bereits einen 5V Trafo verbaut habe (eigentlich für den Betrieb des Lüfters), habe ich das jetzt umbauen können. Ich habe den Trafo-Input direkt auf den 220V Bus gelegt, der hat nun also immer Strom und das Output (5V und GND) auf den erwähnten 3-Pin-Steckplatz der Relaiskarte.

Tatsächlich ist es mit dieser Verkabelung nun so, dass die Relaiskarte bei Anschluss des Arduino Netzteils zwar in Betrieb geht, die roten Status-LEDs gehen an und beim Schalten eines einzelnen Relais hört man auch das typische Klickgeräusch. ABER: ohne 220V Stromversorgung geht die angeschlossene Lampe nicht an. Die Karte holt sich also keinen Strom für die Optokoppler vom Arduino. Erst wenn ich die 220V Versorgung auch anschliesse - und damit dem Trafo Strom gebe - funktioniert alles. Nun habe ich zwar keinen Lüfter mehr und mein komplettes Klimaregelungsfeature ist für den Arsch - aber zumindest sollte der Arduino jetzt ohne Murren durchlaufen. Ich teste trotzdem weiter am Aquarium, denn so recht trauen tue ich dem Zeug in zwischen nicht mehr wirklich. Mal sehen also...

Update 2012-11-18:

Inzwischen habe ich herausgefunden, dass das Problem zu sein scheint, dass die Ethernetlibrary, bzw der 5100 Chip mit Retries nicht klarkommt. Per Default macht er 3 Retries mit einem recht langen Timeoutwert. Wenn sich mein Internet verabschiedet, ist er eine geraume Zeit in diesem Loop gefangen. Und irgendwo dort scheint es einen Bug zu geben. Ich habe jetzt den Retry auf 1 gesetzt (also nur 1 Versuch, dann Ende) und den Timeout auf 500 ms. Dazu habe ich in L das folgende hinzugefügt:

W5100.setRetransmissionCount(1);
W5100.setRetransmissionTime(500);

Ich hatte vorher den Timeout auf 50 gehabt, das war aber zu kurz und er ist gar nicht erst rausgekommen. Immerhin hat das aber gezeigt, dass er anscheinend klaglos weiterläuft, sobald der Timeout zuschlägt. Auf 500 hab ich erst seit jetzt. Mal sehen, wie er sich damit macht...

Update 2012-10-23:

Hm, es wird immer spannender. Gestern abend hatte ich beschlossen, das RAM Reporting zu entfernen, weil der Speicherverbrauch sowieso immer konstant ist. Zwar habe ich eine stabile Funktion gefunden, siehe vorheriges Update, aber wirklich brauchen tue ich es nicht. Allerdings hatte ich dann das Problem, dass sich meine modifizierte Ethernetlibrary nicht mehr compilieren liess. Ich hatte keine Zeit, der Sache auf den Grund zu gehen und bin daher wieder auf die originale Lib zurück gegangen. Und you know what? Um 22:23 ist es wieder abgestürzt. Obwohl der freie Speicher gar nicht mehr abgefragt wird. Anscheinend ist die Ethernetlibrary doch beteiligt. Ausserdem faszinierend ist, dass er auch - manchmal - abstürzt, wenn Django gerade "kaputt" ist. Konkret hatte ich im Reporting die Zeiten für Sonnenauf- und Untergang mit eingebaut und diverse Fehler im Pythoncode eingebaut. Zugriffe aufs Django gingen in der Zeit nicht (man bekam 503 Errors mit Stacktrace usw). Das scheint der Controller nicht zu vertragen. Wobei er das mit meiner modifizierten Ethernetlibrary vertragen hatte.

Update 2012-10-21:

Es scheint, als ob ich dem Fehler auf die Schliche gekommen bin. Und zwar habe ich ja den Code so umgeschrieben, dass er die Daten zu meinem Server postet bzw sich von dort die geänderte Config abholt. Inzwischen habe ich sogar die Ethernet Library umgeschrieben, so dass sie feste globale Variablen verwendet, weil ich vermutete, dass beim dynamischen Allozieren Probleme auftreten. Manchmal lief das so ein paar Stunden durch, manchmal nur ein paar Minuten.

Eben bin ich beim Debuggen mal auf die Idee gekommen, den Post-Intervall auf 3 Sekunden zu senken, damit der Fehler häufiger auftritt und ich nicht jedesmal so lange warten muss. Und tatsächlich ist er auf diese Weise immer recht schnell abgeraucht. Irgendwann hab ich mal in der seriellen Console den "m" Befehl eingegeben (dabei wird der gerade freie RAM ausgegeben). Prompt ist er gestorben. Das liess sich auch mehrmals reproduzieren. Das liess mich stutzig werden. Zwecks der Gaudi habe ich mal in der Funktion check_report(), die die URL zum Posten der Statusdaten erzeugt, den Aufruf zu freeMemory() auskommentiert. Und siehe da, er lief durch!

Und solang ich das nicht auch manuell in der Console aufgerufen habe, blieb es dabei. Ich hab mich also auf die Suche nach einer anderen Funktion gemacht, um den freien RAM herauszufinden. Bisher verwende ich ja L. Jetzt habe ich die mal ersetzt durch L, die eigentlich ziemlich ähnlich aber doch subtil anders funktioniert. Sie verwendet nur die avr-libc internen Variablen __brkval und __heap_start. Und was soll ich sagen - damit läuft er durch. Kein Crash mehr (jedenfalls bis jetzt, aber er läuft auch die ganze Zeit immer noch mit dem übertrieben hektischen 3s Intervall).

Wenn er damit durchhält, fress ich echt einen Besen.

Ach ja, inzwischen verwende ich nicht mehr die Arduino IDE. Das Teil hat mich vielleicht genervt. Allein der Editor in dem Teil, was für ein Mist. Ich verwende jetzt ein L. Dadurch kann ich im Emacs arbeiten und DAS ist herrlich. Welche Erleichterung :) Ausserdem habe ich nun einen besseren Überblick bei Compilerfehlern. Und auf die serielle Console komme ich mit:
screen /dev/cu.usbmodem411 9600
(und mit CTRL-k wieder raus).

Die Django-App habe ich inzwischen auch soweit fertig, L. Programme ändert man einfach im Django Adminbackend. Die Graphen erzeugt wie gewohnt MRTG. Die Django-App habe ich jetzt auch im L.

Update 2012-10-10:

Allerdings habe ich mittlerweile beschlossen, das alles umzubauen. Ich kriege das Crashproblem nicht gefixed. Daher werd ich zukünftig alles intern über den Trafo versorgen. Zusätzlich werd ich aber eine Failsafe-Platine einbauen, die unabhängig versorgt ist. Die wird dann den Arduino überwachen und wenn der weg ist, ihn resetten (d.h. Spannung weg, Spannung an). Und damit während des Resets die Lampen weiter leuchten, wird er als Proxy für die Relaisteuerung fungieren. Ich werd das mit einem Attiny85 machen, den hab ich noch da, und einem Schieberegister. Der Arduino wird mit einer Output-Pin am Attiny angeschlossen und einer Steuerpin. Solang der läuft, reicht der Attiny die Steuersignale nur durch (mit I2C, dafür schreibe ich den Arduino-Code also auch um, so dass der nicht mehr pro Kanal eine Pin ansteuert, sondern I2C Bits setzt und die zum Attiny schickt). Und wenn am Kontrolpin kein Signal mehr reinkommt, bleiben die Relay-Pins weiter gesetzt, weil die ja am Schieberegister und nicht am Arduino hängen. Somit wird er sich dann selber booten, wenn er crasht und sonst wird nix passieren.

Update 2012-10-04:

Tja, es ist aufgetaucht, das Problem. Er ist heute nacht wieder ausgegangen, zweimal sogar. Langsam hab ich ja schon die Nase voll. Um wirklich sicher zu sein, hab ich jetzt das Ethernetkabel gezogen (und resettet) und fahre den Controller jetzt ohne GUI und MRTG. Mal sehen wie lang er da hält. Denn so wie es aussieht, verursacht der Ethernet-Shield den Shutdown und die Frage, die mich noch interessiert, ist ob er das auch tut, wenn er gar nichts zu tun hat.

Update 2012-10-03:

So, heute habe ich den Controller mal komplett zerlegt und wirklich alles durchgemessen. Die eigentliche Ursache für das Shutdownproblem habe ich allerdings noch nicht gefunden. Aber ich weiss jetzt, warum das System läuft, auch wenn man GND entfernt: er verwendet dann das OUTPUT PIN des Speakers als GND! Und wie sich herausstellt, ist das ein Feature. Ein PIN im OUTPUT Mode im Status LOW kann Strom ableiten ("sink current" auf englisch). Allerdings tut er das NUR, wenn es sonst keinen anderen Weg gibt. Wenn ich also GND auf dem Arduino connecte, läuft über die Speaker-PIN kein Strom - immerhin.

Was das andere Problem betrifft, ist noch ein spannendes Detail zu Tage getreten: er resettet sich NUR, wenn ich die GUI über den Firmenproxy via Internet aufrufe (ich habe die IP des Terraduinos auf meinem Router reingenattet und verwende dort Dyndns, so dass ich den Controller auch von Aussen ansprechen kann). Wenn ich die GUI aber vom LAN aus anspreche, passiert gar nichts. Und die Abschaltung erfolgt unmittelbar. In einem Test habe ich alles abkühlen lassen, unmittelbar, nachdem er oben war, die GUI aufgerufen und Zack! war er weg. Mit einer Überhitzung durch zu viel Strom kann es also nicht zusammenhängen. Langer Rede, kurzer Sinn: ich denke inzwischen, dass es sich um einen Hardwarefehler im Ethernetshield oder einen Bug in der Ethernet-Library (der womöglich einen Hardwarefehler auslöst, sic) handeln muss. An meiner Platine habe ich keinen Fehler gefunden, alle Verbindungen sind sauber, keine Kurzschlüsse, keine Spannungsspitzen, keine sonstigen Dinge, die irgendwie "komisch" wären.

Also ich werd ihn jetzt ein paar Wochen laufen lassen. Womöglich hat sich durch das Umstecken des Speaker-PINs das Problem bereits erledigt, dass er sich nach ein paar Tagen oder Wochen selber abschaltet. Vom Speaker abgesehen habe ich auch die PINs 15, 16, 18 und 19 umgezogen auf 29-33. Diese PINs sind auf dem Arduino mit TX1 oder RX2 beschriftet. Ob man die so einfach benutzen kann oder Kollisionen auslöst, wenn man es tut, habe ich zwar nicht herausfinden können. Ich hab sie aber trotzdem umgesteckt. Am Mega ist ja genug Platz.

Und falls das Problem doch noch auftaucht, werde ich mir überlegen, ob ich den Ethernetshield nicht durch einen WiFi-Shield|https://www.sparkfun.com/products/11287> ersetze.

Update 2012-10-02:

Also die getrennte Stromversorgung für die Optopkoppler der Relaiskarte hat nichts gebracht. Statt dessen ist es eigentlich noch schlimmer. Ich habe das Teil gestern auseinandergebaut und systematisch durchgemessen. Dabei habe ich zwei seltsame Dinge herausgefunden: ich habe 2 Stromversorgungen, die vom Arduino weggehen: eine geht auf meine Leiterplatine, von wo aus die LEDs, Schalter, Sensor, RTC usw versorgt werden und eine weitere geht zum Relais für die Steuerspannung. Wenn ich beide GND Kabel am Arduino abziehe, funktioniert immer noch alles. Eigentlich sollte gar nichts mehr gehen, weil überhaupt kein funktionierender Stromkreis mehr da ist. Das ist aber nicht so, alles geht. Gleichzeitig bin ich beim Fummeln an den Stecker vom Speaker gekommen, der sitzt etwas locker. Dabei ist das Gerät mehrfach aus- und angegangen. Wobei sich herausstellt, dass das exakt das beobachtete Verhalten ist: vorn sind alle LEDs aus und die Relais sind abgeschaltet, d.h. die Lampen sind aus. Innen jedoch sind die LEDs auf dem Arduino und dem Ethernetshield noch an und auf der Relaiskarte leuchten noch 4 der roten Kontrol-LEDs. So wie es also aussieht, war mein Bug nicht, dass der Controller wegen zu hohem Stromverbrauch ausgeht, sondern es war dieser "Wackler". Offenbar kriegt die Leiterkarte auch Strom wenn die beiden GNDs nicht angeschlossen sind und irgendwie muss das mit dem Speaker Anschluss zusammenhängen.

Aber es wird noch wilder: nun hab ich den + vom Speaker (das heisst der Anschluss, den ich vom Arduino aus mit PWM ansteuere) mal umgesteckt von Pin 23 auf 37. Und nun wirds richtig spannend. Wenn ich jetzt die GNDs abziehe, verhält er sich wie erwartet - nichts geht. Wenn ich sie anschliesse, läuft alles. Und ich kann am Speaker-Stecker wackeln wie ich mag, da passiert gar nichts. ABER: sobald ich die GUI aufrufe (und also auf dem Ethernetshield Aktivität auslöse), geht er aus (und zwar wie oben beschrieben: Lampen aus, LEDs aussen aus, LEDs innen weiter an und keine Reaktion mehr am Ethernet).

Tja. Ich bin momentan etwas ratlos, aber so wie es aussieht, habe ich wohl auf meiner Leiterplatine irgendeinen Fehler. Oder einen Kurzen. Keine Ahnung. Ich bin ja auch nur Amateur. Ich werde also heute einen Schritt tiefer einsteigen und die Leiterplatte ausbauen und da jede einzelne Lötstelle durchmessen müssen. Ich weiss nicht mal, wie ich das machen soll. Die Messkontakte meines Multimeters sind viel zu grob für solchen Kleinkram. Ein echter Scheiss.

Update 2012-10-01:

Nein, die letzte Maßnahme hat die Situation verschlimmbessert. Der Controller ist innerhalb von 12 Stunden gleich zweimal ausgegangen (vorher nur einmal alle 1-2 Wochen). Da ist also irgenwas wirklich richtig faul. Mir wird also nichts übrigbleiben, als es nochmal zu zerlegen und jeden Kabelstrang durchzumessen um zu wissen, wo dem Arduino soviel Strom entzogen wird. Langsam wird es jedenfalls lästig.

Update 2012-09-26:

So, ich hab heute den Controller zerlegt und nachgeschaut. Es war wie ich es mir dachte. Die Spannungsversorgung für die Peripherie hatte ich am 5V Pin des Ethernetshields angeschlossen. Somit hingen ALLE Komponenten einschliesslich des Ethernetshields an EINEM 5V Pin, der wie erwähnt ja nur 200 mA schafft. Nun habe ich die Spannungsversorgung der Relaiskarte abgezwickt und auf die extra 5V und GND Pins direkt auf dem Mega gesteckt (vor PIN 22 und nach PIN 54). Er läuft jetzt im Testbetrieb, alle Kanäle sind geschaltet. Mal sehen.

#terrarium

↷ 25.09.2012