Arduino startet manchmal bei Tastendruck neu

Hallo, ich hoffe, ihr könnt mir hier weiterhelfen. Aktuell bin ich an einem Spaßprojekt, einem Art "Bombenkoffer". Ist für ein Spiel, eine Seite muss diesen vor Ablauf des Timers finden. Andernfalls geht eine Sirene los.

Bedienung wie folgt:
Es gibt einen Hauptschalter. Anschließend ist der Arduino mit Spannung versorgt. Wird nun ein Taster für mehrere Sekunden gedrückt gehalten, wird ein externer Timer mit Spannung versorgt. Dieser hat einen Relaisausgang, welcher wiederum auf einen Eingang des Arduino geht (Hinweis: invertierter Eingang, da während der Timerlaufzeit das Relais geschlossen ist und erst bei Zeitablauf öffnet). Über diesen Eingang wird wiederum ein Ausgang angesteuert (die Sirene).
Vor Ablauf der Zeit kann mit dem gleichen Taster "entschärft" werden - der Timer wird ausgeschaltet.

Nun habe ich folgendes Fehlerbild:
Ab und zu (ich weiß auch nicht warum!) wird der Timer zwar aktiviert, aber auch sofort wieder ausgeschaltet, weil der Arduino neustartet.
Ich habe keine Ahnung, warum das so ist und komme leider mit dem Debugging nicht weiter.

//Arduino Nano Atmega 328P

//Ausgänge definieren
int DO_LED = 13;
int DO_Selbsthaltung = 12;
int DO_Pieper = 6;
int DO_Beleuchtung = 5;
int DO_Sirene = 4;
int DO_Timer = 2;
//Eingänge definieren
int DI_Taster = 8;
int DI_TimerRelais = 7;
//Varbiablen von Eingängen definieren
int TimerRelais = HIGH; //wenn Timersignal anliegt, Active=LOW
int Taster = LOW;
//Variablen definieren
int piepsen = LOW; //für Pieper
int blinken = LOW; //für LED-Beleuchtung blinkend 
int flackern = LOW; //für Flackern
static int scharf = LOW; //ist die Bombe scharf oder nicht
static int Ausloesung = LOW; //Hat Bombe ausgelöst?
long t_haltedauer = 1000; //Statische Hilfsvariable, notwendige Dauer für scharfmachen / entschärfen - Standard 10000
long t_fused = 0; //Hilfsvariable, damit Taster nicht direkt wieder scharfstellt/entschärft, wenn länger gehalten wird
long t_defused = -5000; //Hilfsvariable (-5000?), damit Taster nicht direkt wieder scharfstellt/entschärft, wenn länger gehalten wird
long t_ausloesung = 0; //Hilfsvariable, Zeitpunkt wann Auslösung war

void setup() {
pinMode(DO_LED, OUTPUT); //Test-LED
pinMode(DO_Selbsthaltung, OUTPUT);
pinMode(DO_Pieper, OUTPUT); 
pinMode(DO_Beleuchtung, OUTPUT); 
pinMode(DO_Sirene, OUTPUT); 
pinMode(DO_Timer, OUTPUT); 
pinMode(DI_Taster, INPUT); 
pinMode(DI_TimerRelais, INPUT); 
Serial.begin(9600); //Debug-Ausgang
Serial.print("Neustart\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
}

void loop() {  
  TimerRelais = !digitalRead(DI_TimerRelais); //Variable TimerRelais mit Zustand des DI füllen
  Taster = digitalRead(DI_Taster); //Variable Taster mit Zustand des DI füllen
  Tasterabfrage(); //Scharfmachen muss durch Taster erfolgen, diese Funktion wird hier eingebunden
  Bumm(); //Subfunktion, setzt Variable "Ausloesung"

  if (scharf == LOW) { //Grundzustand
    digitalWrite(DO_Timer, LOW);
    digitalWrite(DO_Sirene, LOW);
    digitalWrite(DO_Pieper, LOW);
    digitalWrite(DO_Beleuchtung, LOW);
    digitalWrite(DO_Beleuchtung, HIGH);
    digitalWrite(DO_Selbsthaltung, LOW);
    digitalWrite(DO_LED, LOW); //kann später weg
//    Serial.println("scharf == LOW");
  } 
  if (scharf == HIGH && Ausloesung == LOW) { //Timer läuft
    digitalWrite(DO_Timer, HIGH);
    digitalWrite(DO_Beleuchtung, HIGH);
    digitalWrite(DO_Selbsthaltung, HIGH);
    Piepser();
    digitalWrite(DO_LED, HIGH); //kann später weg
//    Serial.println("scharf == HIGH && Ausloesung == LOW");
  }
  if (Ausloesung == HIGH) { //Auslösung, Sirene an, Pieper aus
    digitalWrite(DO_Timer, HIGH);
    digitalWrite(DO_Sirene, HIGH);
    digitalWrite(DO_Selbsthaltung, HIGH);
    digitalWrite(DO_Pieper, LOW);
    LED_blinken();
    flackerLED();
//    Serial.println("Ausloesung == HIGH");
  }
 
//TODO: Beim erneuten scharf stellen klackert Timer oder stürzt das Board ab. Keine Ahnung, was da los ist... 
    
} //Ende loop()

void Tasterabfrage() {   // Idee von hier https://forum.arduino.cc/t/zeitverzogerung-und-gleichzeitig-weitere-abfragen-mit-arduino-uno/182638/13
  static boolean TasterLetzterZustand=LOW;
  static long TasterEinschaltzeitpunkt;
  if (TasterLetzterZustand==LOW && Taster==HIGH) {
    TasterEinschaltzeitpunkt=millis();
    Serial.println("Tastendruck Anfang");
  }
  TasterLetzterZustand = Taster;  
    if (Taster == HIGH 
        && millis() - TasterEinschaltzeitpunkt  > t_haltedauer 
        && scharf == LOW 
        && millis() - t_defused > 5000) //2500 ms, damit durch längeren Tastendruck nicht direkt wieder entschärft wird
    {
      scharf = HIGH;
      t_fused = millis(); //Merker, damit durch längeren Tastendruck nicht direkt wieder entschärft wird
      //Debug_scharfmachen(); //später entfernen
    }
    if (Taster == HIGH 
             && millis() - TasterEinschaltzeitpunkt  > t_haltedauer 
             && scharf == HIGH 
             && millis() - t_fused > 5000) //5000 ms, damit durch längeren Tastendruck nicht direkt wieder scharfgestellt wird
    {
      scharf = LOW;
      t_defused = millis(); //Merker, damit durch längeren Tastendruck nicht direkt wieder scharfgestellt wird
      //Debug_entschaerfen(); //später entfernen
    }  
}

void Bumm() {   // Liegt Signal des Timers länger als 500 ms an? Wenn ja, dann Variable Ausloesung auf HIGH
  static boolean TimerLetzterZustand=LOW;
  static unsigned long TimerEinschaltzeitpunkt;
  if (TimerLetzterZustand==LOW && TimerRelais==HIGH) 
  {
    TimerEinschaltzeitpunkt=millis();
  }
  TimerLetzterZustand = TimerRelais;  
  if (TimerRelais == HIGH 
      && millis() - TimerEinschaltzeitpunkt  > 500 //Signal muss min 500 ms anstehen
      && TimerEinschaltzeitpunkt > 1000
      && scharf == HIGH )
  {
    Ausloesung = HIGH;
    t_ausloesung = millis(); //Merker, damit nach Auslösung die Scharfstellung wieder aufgehoben wird
  }
  else if (t_ausloesung > 5000){
    Ausloesung = LOW;
    scharf = LOW; //Soll Piepen nach Auslösung abschalten
    t_ausloesung = 0; //Sonst kein erneutes scharfmachen möglich
  }
}

void Piepser() { //sorgt für piepen
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= 500) //500 ms Intervall
  {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    // if the LED is off turn it on and vice-versa:
    if (piepsen == LOW) {
      piepsen = HIGH;
    } else {
      piepsen = LOW;
    }
    // set the LED with the ledState of the variable:
    digitalWrite(DO_Pieper, piepsen);
  }
}

void LED_blinken() { //sorgt für blinkende LED
  static unsigned long previousMillisLED = 0;
  unsigned long currentMillisLED = millis();
  if (currentMillisLED - previousMillisLED >= 250) //250 ms Intervall
  {
    // save the last time you blinked the LED
    previousMillisLED = currentMillisLED;
    // if the LED is off turn it on and vice-versa:
    if (blinken == LOW) {
      blinken = HIGH;
    } else {
      blinken = LOW;
    }
    // set the LED with the ledState of the variable:
    digitalWrite(DO_Beleuchtung, blinken);
  }
}

void flackerLED() { //sorgt für flackernde LED auf Board
  static unsigned long previousMillisFLACKER = 0;
  unsigned long currentMillisFLACKER = millis();
  if (currentMillisFLACKER - previousMillisFLACKER >= 100) //100 ms Intervall
  {
    // save the last time you blinked the LED
    previousMillisFLACKER = currentMillisFLACKER;
    // if the LED is off turn it on and vice-versa:
    if (flackern == LOW) {
      flackern = HIGH;
    } else {
      flackern = LOW;
    }
    // set the LED with the ledState of the variable:
    digitalWrite(DO_LED, flackern);
  }
}

void Debug_scharfmachen() {
      Serial.print("Zeitstempel: ");
      Serial.println(millis());
      Serial.println("Scharfmachen");
      Serial.print("scharf = ");
      Serial.println(scharf);
      Serial.print("Ausloesung = ");
      Serial.println(Ausloesung);
      Serial.print("t_defused = ");
      Serial.println(t_defused);
      Serial.print("t_fused = ");
      Serial.println(t_fused);
      Serial.print("t_ausloesung = ");
      Serial.println(t_ausloesung);
      Serial.println(" ");
}

void Debug_entschaerfen() {
      Serial.print("Zeitstempel: ");
      Serial.println(millis());
      Serial.println("Entschaerfen");
      Serial.print("scharf = ");
      Serial.println(scharf);
      Serial.print("Ausloesung = ");
      Serial.println(Ausloesung);
      Serial.print("t_defused = ");
      Serial.println(t_defused);
      Serial.print("t_fused = ");
      Serial.println(t_fused);
      Serial.print("t_ausloesung = ");
      Serial.println(t_ausloesung);
      Serial.println(" ");
}

PS: Es gibt noch ein paar Zusatzfunktionen, die ich oben nicht beschrieben habe, da sie wahrscheinlich nichts mit dem Problem zutun haben:
Eine Selbsthaltung - während der Timer läuft, wird der Hauptschalter mit einem Relais überbrückt (Ausgang 12). Es gibt neben der Sirene auch einen Pieper, dieser ist auf 6, extra Beleuchtung auf 5.

Ich tippe auf zu hohen Stromverbrauch oder zuviel RAM-Verbrauch.

Verwende das F() makro:

Serial.print("Zeitstempel: ");

wird

Serial.print(F("Zeitstempel: "));

Das spart RAM.

Grüße Uwe

1 Like

Wenn der Neustart genau beim Schalten auftritt, deutet das auf ein EMV Problem hin. Zeigen mal ein Schaltbild und den Aufbau.

Daran habe ich auch schon gedacht. Überlege auch gerade, es alles noch mal sauber neu zu löten. Verwendet wurde eine Punktkettenreihenplatine. Leider habe ich nur eine handschriftliche Zeichnung der Bestückung zur Hand, habe es in Fritzing noch nicht gezeichnet mangels passender Bauteile. Das will ich noch nachholen.
Der Widerstand hinter Taster und Timer für die Eingänge hat nur einen 1000 Ohm Pulldown, habe ich vorhin festgestellt - besser wäre wohl 10 kOhm gewesen.


Die Punktketten sind immer 3 Stück senkrecht im Kästchenpapier. Die Begrenzung habe ich mit den waagerechten Linien dargestellt.

Das ist auch gut so. Fritzing ist auch kein Schaltplan, sondern ein Verdrahtungsplan. Auf dem erkennt man fast nix. Ein Schaltplan dient zum erkennen der Funktion. Das geht leider auch mit deiner Zeichnung nicht.

Auch wenn man nicht sehr viel auf deiner Zeichnung erkennen kann, die Relais vermute ich aber zu erkennen.
Was sind das für Relais (Bitte Link posten) und wie steuerst du diese an ? Eine Freilaufdiode kann ich nicht erkennen. Wo ist die eingesetzt ?

So, ich hab mich mal rangesetzt und einen Plan gezeichnet. Ist vereinfacht, nicht alle Funktionen sind abgebildet - aber m.E. die wesentlichen Funktionen für das Problem sind drin.

Freilaufdiode habe ich tatsächlich nicht drin. Brauche ich diese zwingend?
Als Relais kommen diese hier zum Einsatz:
AFE BJ-SS-105LM Printrelais 5 V/DC 10 A 1 Schließer 1 St.
1405623 - 62 bei Conrad

Das muss ja schief gehen.

  1. Bei Induktivitäten brauchst du immer eine Freilaufdiode
  2. Die Relais brauchen zu viel Strom (40 mA). Der Pin sollte max. mit 20 mA belastet werden. Da musst du Transistoren zur Ansteuerung vor schalten. Oder Relais verwenden, die max. 20mA ziehen.
  3. Die Led braucht einen Vorwiderstand. Wenn das eine "einfache" Led ist, kannst du die auch direkt (mit Widerstand) vom Controller ansteuern.

Edit:
Dann hast du bisher Glück gehabt, dass der Nano nicht gestorben ist.
Die Spannungen (ohne Diode ) an den Pins können den Pin zerstören.

2 Likes

LED1 ist falsch gepolt.

Tipps zur besseren Übersicht: Relais, Widerstände und Piezo Summer um 90° drehen.
Widerstände nach unten schieben


1 Like

Die 9Volt an die Basis des Transistors irritieren da.
Der Widerstand kommt bestimmt auf einen Ausgangspin des Controller.

Da steht IN1. Das ist der PullDown

Das ist ein schnell kopiertes Beispiel: +9V ist mit dem µC-Ausgangspin zu ersetzten. Es ging hauptsächlich um die Freilaufdiode und Ansteuerung mit Transistor. Und das Zeichen von Oben nach unten.

IN1 steht am Draht zum Taster. Ich meinte den zum Transistor.

Nur wird ein Anfänger da leicht Probleme haben.

Warum?
Man muss nicht immer alles genau hinschreiben, ist ja nur Beispiel wie man das macht, ein wenig soll der TO mitdenken.

Echt jetzt ?
Das glaub ich jetzt nicht.

Vielen Dank für die Hinweise!
Dass die Leistung der Arduino-Ausgänge so begrenzt ist, hatte ich nicht auf dem Schirm. Hätte ich das gewusst, hätte ich gleich komplett auf 12 V-Relais gesetzt. Wäre wohl einfacher gewesen. Da ich nun die 5 V-Relais weiter nutzen will, ist mein Plan, 5 V-kompatible Transistoren davor zu setzen (wie von euch empfohlen). Habt ihr für diese und die dazu passenden Dioden Produktempfehlungen?
Wie ihr dem Plan entnehmen könnt, will ich die Relais weiterhin mit 5 V anziehen, allerdings die 5 V aus der Versorgung des Arduino verwenden. Geht das, oder komme ich da auch in eine Leistungsgrenze?

Ich habe den Fehler mit der LED (fehlender Vorwiderstand, falsch rum) korrigiert - hatte ich einfach nur vergessen einzuzeichnen.
Ansonsten habe ich die Ansteuerung via Transistor für das erste Relais eingezeichnet, Nr. 2 und 3 sind noch alt.
Passt das so?

Die Typenbezeichnung für die Diode und dem Transistor kannst du dem Schaltbild von wwerner entnehmen. Warum du allerdings die Led mit einem Relais schalten willst, kann ich nicht erraten.

Und nein, die Relais solltest du besser nicht aus den 5Volt des Arduino speisen. Das ist der Regler schnell an seiner Grenze.

1 Like

Bitte drehe doch die Bauteile so, das der Strom von oben nach unten fließt.

so ist es gruselig

1 Like

Die LED habe ich nur als Ersatzdarstellung genommen. In echt kommt da später ein ganzer LED-Leuchtstreifen mit 12V hin. Deshalb hatte ich auch keinen Widerstand eingezeichnet :slight_smile:

Beim nächsten Wurf :slight_smile:

Beschreibe doch erst dein Projekt und kauf dann ein :slight_smile:
z.B. Relay 4 Kanal Relais Modul - 5V günstig online kaufen | Funduinoshop
Und dann hast Du sogar eine Galvanische Trennung
Sowas gibt es auch noch bei anderen Händlern auch noch Preisgünstiger.
Aber Achtung solche Angaben wie 250V da würde ich Abstand von nehmen. Im Niedervoltbereich ist das so aber völlig OK.

1 Like