Schläft Arduino ein ??

Hallo ich habe ein Problem und versuche nun rauszubekommen woran es liegt.

Ich benutze einen Uno als Ein- und Ausschaltverzögerung im Verbund mit einer Heizung. Von der Heizungssteuerung wird das Brennersignal abgegriffen auf einem Relais welches mir dann einen Eingang mit 5V schaltet und die Zeiten anlaufen lässt. Funktioniert soweit gut, nur morgens nach der Nachtabsenkung von ca. 6Std ( und keinem Signal ) läuft die Verzögerung nicht an.

Kann es sein, das der Arduino einschläft ( ist immer an Spannung ) ?

Vielen Dank für Tipps

Gruß olmuk

Das kann eigentlich nicht sein. Für genauere Aussagen bräuchten wir den Sketch und die Schaltung. Kannst du denn das Signal nach der Nachtabsenkung messen? Also ist es tatsächlich genauso vorhanden wie im regulären Betrieb?

olmuk: Kann es sein, das der Arduino einschläft ( ist immer an Spannung ) ?

Nein, es gibt zwar Energiespar-Betriebsarten, die als Sleepmode bezeichnet werden, aber diese müssen speziell angesteuert werden.

Viel wahrscheinlicher sind Programmfehler in der Software und Schaltungsfehler in der Hardware.

http://de.wikipedia.org/wiki/Elektromagnetische_Vertr%C3%A4glichkeit

Wenn eine Variable überläuft kann das ähnliche Symptome hervorrufen, wie ein Absturz oder Einschlafen.

Lass doch mal über Nacht den seriellen Monitor mit Laptop mitlaufen. jede Minute ein Wert sollte reichen. Dann kannst du rausfinden, was er zuletzt gemacht hat.

Hallo, danke für die Antworten.
Anbei die Schaltung und der code - ich würde das geren zu Ende führen wobei ich mittlerweile glaube
das es von Seiten der hiezung kommt.
Gruß olmuk

const int buttonPin = 2;     // Eingang 2 für Brenner
const int ledPin =  13;      // Relais

int buttonState = 0;        
int Einschalt = 0;
int Ausschalt = 0;
void setup() {

pinMode(ledPin, OUTPUT);      
pinMode(buttonPin, INPUT);     
}

void loop(){
  
buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH && Einschalt == 0) { 
  Einschalt = 1;
  delay(15000);
  digitalWrite(ledPin, HIGH);
} 
  if (buttonState == LOW && Einschalt == 1) { 
  delay(120000);
  Einschalt = 0;
  digitalWrite(ledPin, LOW); 
}

}

Schaltung.png

olmuk: delay(15000); ... delay(120000);

Ohauahauaha. =(

Wenn Du den Arduino ständig für 15 oder 120 Sekunden mit delay() schlafen legst, dann macht der Arduino in diesen 15 oder 120 Sekunden GAR NICHTS. Insbesondere nicht den Button abfragen.

In interaktiven Programmen, bei denen Du eine Taste (kürzer als zwei Minuten) drücken möchtest und daraufhin soll etwas passieren, ist die delay() Anweisung so ziemlich das Unbrauchbarste, was Du ins Programm einbauen kannst.

jurs:

olmuk: delay(15000); ... delay(120000);

Ohauahauaha. =(

Wenn Du den Arduino ständig für 15 oder 120 Sekunden mit delay() schlafen legst, dann macht der Arduino in diesen 15 oder 120 Sekunden GAR NICHTS. Insbesondere nicht den Button abfragen.

In interaktiven Programmen, bei denen Du eine Taste (kürzer als zwei Minuten) drücken möchtest und daraufhin soll etwas passieren, ist die delay() Anweisung so ziemlich das Unbrauchbarste, was Du ins Programm einbauen kannst.

Da es sich dabei aber nicht um einen Tastendruck handelt, sondern um die Heizung, die während 6h "auf den Button drückt", was einfach verzögert weiter gegeben werden soll, denke ich nicht, dass das hier das Problem ist. Viel mehr vermute ich, dass K2 anders beschaltet werden müsste. Zum einen empfehle ich dir sehr, eine Freilaufdiode antiparallel zur Spule zu schalten, da beim Abschalten des Relais das Magnetfeld zusammenbricht und ziemlich hohe Spannungen verursachen kann, was deinen uC komplett plätten kann. Ausserdem würde ich das Relais über einen Transistor schalten. Welches Relais verwendest du? Solltest du ein bistabiles Relais verwenden, müsste die Polung umgedreht werden und dann war da noch irgendwas mit Entregen der Spule... denke aber mal, dass du ein monostabiles verwendest. Möglicherweise müsste auch die Last beachtet werden, die du zu schalten gedenkst. Am besten liest du dir mal diesen Artikel durch: http://www.mikrocontroller.net/articles/Relais_mit_Logik_ansteuern

Vielleicht kannst du noch überprüfen, ob K1 tatsächlich schaltet, indem du den Buttonstate protokollierst oder früh aufstehst und auf ein Klicken wartest :)

Hitsuji:
Da es sich dabei aber nicht um einen Tastendruck handelt, sondern um die Heizung, die während 6h “auf den Button drückt”, was einfach verzögert weiter gegeben werden soll, denke ich nicht, dass das hier das Problem ist.

Stimmt, das ist ja gar kein interaktives Programm mit manueller Tastenbetätigung - mein Fehler!

Die Delays im Sketch würden allenfalls zu dem Effekt führen, dass wenn der “buttonPin” für weniger als die Einschaltverzögerung geschaltet wird, statt “kein Schaltvorgang” die Schaltfolge “Einschalten nach Ablauf der Einschaltverzögerung - eingeschaltet sein während der Ausschaltverzögerung - Ausschalten nach Ablauf der Ausschaltverzögerung” abläuft.

Hitsuji:
Viel mehr vermute ich, dass K2 anders beschaltet werden müsste.
Zum einen empfehle ich dir sehr, eine Freilaufdiode antiparallel zur Spule zu schalten, da beim Abschalten des Relais das Magnetfeld zusammenbricht und ziemlich hohe Spannungen verursachen kann, was deinen uC komplett plätten kann. Ausserdem würde ich das Relais über einen Transistor schalten.

Ich würde ihm zum Schalten von Wechselstrom für seinen Brenner zu einem “SSR Relais” am Arduino raten.

Mein Hinweis in Reply #2 auf http://de.wikipedia.org/wiki/Elektromagnetische_Verträglichkeit hat ihm ja offenbar überhaupt nichts gebracht, wenn er danach ein (viel zu großes) Schaltbild zeigt, in dem ein nacktes Spulenrelais hängt, das den vollen Spulenstrom über einen Arduino-Pin führt und die Freilaufdiode an der Relaispule fehlt. Es wäre schon ein ziemlicher Glücksfall, wenn er den µC dabei nicht schon “komplett geplättet” hat durch die auftretende Überspannung an der Relaisspule beim Abschalten des Spulenstroms. Darüberhinaus ziehen fast alle 5V-Spulenrelais mehr als die 40 mA, die ein Arduino-Pin im Maximalfall unter bestimmten Umständen noch gerade so verkraftet.

Hmmm, ohne Freilaufdiode zu schaffen hätte nicht passieren dürfen - danke für den Hinweis. Ist ein sehr kleines printrelais das aber auch eine Induktivität aufweist.

Der Eingang kommt nur wenn der Brenner anläuft und ist während der Nachtabsenkung ständig low. Deswegen meine Überlegung ob dann Arduino einschläft..

Trotz der unschönen delay Lösung dürfte ich aber durch die > 5 min Brenndauer immer aus dem delay rauslaufen, oder ? Weiterhin tritt es nur am Morgen nach dem "Neustart" der Heizung auf. Mir ist allerdings noch gestern aufgefallen das der L der Pumpe von der Hz- Reglung geschaltet wird ( und dann nicht rechtzeitig kommt wg Vorragschaltung usw. ).

Danke Euch - ich werde auf millis umstellen, hatte halt die Befürchtung irgendwann einen Überlauf zu erzeugen.

Gruss olmuk

werde auf millis umstellen, hatte halt die Befürchtung irgendwann einen Überlauf zu erzeugen

Da man bei millis() immer nur mit der Differenz zu einem älteren gespeicherten millis() rechnet, ist ein Überlauf kein Problem, wenn diese Differenz nicht größer als 49 Tage wird.

Am vereinfachten Beispiel byte ( 0 .. 255 ):

byte Alt = 250;
byte Neu =  1;
Serial.println(Neu - Alt, DEC); // ergibt 7, ohne dass man sich um einen Überlauf kümmern müsste

Es geht um nicht um den Überlauf der Berechnung alt / neu , sondern das die millis() halt 365 Tage x 24 h laufen. Ich versuche mal zu rechnen : 3.600.000 mS x 24 x 365= 31.536.9990.000 millis() Wenn ich richtig rechne habe ich dann nach 1,6 Monaten einen Dint Überlauf ( 31.536 E12 / 4.294 E12). Die millis() des Überlaufes sind zu vernachlässigen - stimmt der Ansatz ? Da ich aus der SPS Ecke komme, sind mir Überläufe ein Grauen und haben leider schon viel kaputt gemacht.

Was ist denn dann der korrekte ( saubere? ) Ansatz ? Was ist den arduino danach zu reseten, bzw. kann man die millis () rücksetzen ?

Gruss olmuk

olmuk: Was ist denn dann der korrekte ( saubere? ) Ansatz ?

Der richtige Ansatz zum Berechnen von Differenzen über einen Überlauf hinweg ist von michael_x dargestellt worden, allerdings am Beispiel von byte.

Für den millis() Timer brauchst Du nur nach diesem Rezept vorgehen:

  1. Den Stand des millis() Timers immer in eine "unsigned long" Variable auslesen
  2. Danach immer die Differenz aus den aktuellen millis() und dem vorher ausgelesenen Wert bilden
  3. Diese Differenz ist immer korrekt, auch über Timerüberläufe des millis-Zählers hinaus Voraussetzung: Es dürfen nicht mehr als 49 Tage vergangen sein, zwischen Auslesen des Timers und Differenzbildung

Beispielcode:

unsigned long timerMerker; // immer "unsigned long"
timerMerker=millis();  // Timer auslesen und an eine "unsigned long" Variable zuweisen
...
if (millis()-timerMerker>120000)   // Diese Abfrage klappt auch bei zwischenzeitlichem Timer-Überlauf
...

Einzige Voraussetzung: Zwischen dem Auslesen des aktuellen Timers und dem vorher gemerkten Timer dürfen nicht mehr als 49 Tage liegen. Diese Voraussetzung bei Schaltverzögerungen unter 49 Tagen immer gegeben. Nur wenn eine Schaltverzögerung über 49 Tage betragen soll, also jetzt den Button drücken und erst in zwei Monaten soll etwas geschaltet werden, müßtest Du anders vorgehen.

Wenn die Kontrolle wie beschrieben gemacht wird, ist der Zeitintervall auch wenn ein Überlauf (rollover) stattfindet korrekt. Einzige Beschrenkung ist daß keine Intervalle größer als 49, irgendwas Tage sein können da es, wie beschrieben, nicht möglich ist zu kontrollieren, ob bereits ein Überlauf erfolgt ist oder nicht. Aber auch für das gibt es Lösungen: Millis Police http://www.faludi.com/2007/12/18/arduino-millis-rollover-handling/

Grüße Uwe