Watch dog hängt sich auf?

Ich habe folgendes Problem:

Pro mini clone
Step down auf 5,3V mit 5A Modul
Starkes Servo (3.5A Blockierstrom)
Billiges Relaismodul
12V 5A Netzteil

Der uC steuert das Servo zwischen 2 Positionen, je nach Zustand eines Digitaleingangs, welcher per potenialfreiem Relaiskontakt einer SPS gesteuert wird.

Das ganze funktioniert weitestgehend wie es soll, ist auch nichts zeitkritisches, aber dennoch wichtig.
Befindet sich in kritischer EMV Umgebung (starke 230V Pumpen, DC Elektrolyse, Elektromagnetische Impulspumpe), uC hing sich immer wieder auf.

Hab dann einen Watchdog reingebaut, auf mehrere Sekunden. Jetzt hängt er nur noch ganz selten.

Daher die Frage, kann sich der uC so aufhängen, dass ihn nicht mal mehr der Watchdog wach bekommt?
Strom weg und wieder dran, dann funktioniert alles wieder.

Sketch kommt später

leider nur halbwissen: Kommt mir eingenartig vor dass der WD versagt.

was mir noch einfallen würde: wenn EMV dann alles in ein gut geschirmtes Metallgehäuse?

In gleicher Umgebung läuft ein Mega und ein ESP8266 weitgehend problemlos. D.h., dort funktioniert der Watchdog wenigstens, und löst so gut wie nie aus.

Bei dem pro mini habe ich leider keine Netzanbindung um das zu loggen

Hab schon gedacht, einen externen Hardware Watchdog zu bauen, diskret, ohne uC

Der Mega und der Nano hatte ein WDT Problem!
Diese kommen nicht aus dem WDT Reset loop raus.

Evtl hilft es den UNO Bootloader auf den Mini zu brennen.

ist kein Bootloader drauf, hab mit usbasp geflasht. Fuses vielleicht?

Habe es gerade nochmal nachgebaut, um die Originalschaltung nicht auszubauen.
mit
while (!digitalRead(10)); // watchdog manuell auslösen
löst der Watschdog perfekt aus, wenn ich Pin 10 auf GND setze.

hier noch der Sketch:

#include <MobaTools.h>
#include <INTERVAL.h>
#include <Streaming.h>
#include <avr/wdt.h>

Servo8 myservo;

enum {offen_anschlag, offen, geschlossen_anschlag, geschlossen, start};
uint16_t servowerte[] = {2145, 2030, 800, 900};   // in us
byte state;
bool auf;
uint16_t servo_us;
const byte relaisPin = 3;
const byte signalPin = 4;
const byte servoPin = 9;
const uint16_t nachlaufzeit = 2000;

void setup() {
  pinMode(10, INPUT_PULLUP);  // hardcoded test für watchdog auslösen
  myservo.attach(servoPin);
  Serial.begin(115200);
  Serial.println(servowerte[offen_anschlag]);
  Serial.println(servowerte[offen]);
  Serial.println(servowerte[geschlossen_anschlag]);
  Serial.println(servowerte[geschlossen]);
  wdt_enable(WDTO_2S);   // Watchdog auf 1 s stellen

  myservo.setSpeed( 20 );
  pinMode(relaisPin, OUTPUT);

  pinMode(signalPin, INPUT_PULLUP);
  Serial << "State: " << state << "\tPot: " << auf << endl;
  digitalWrite(relaisPin, LOW); // Strom auf Servo geben

  if (!digitalRead(signalPin))  // wenn beim Start/Reset, dann Servo in Position bringen
  {
    servo_us = servowerte[offen_anschlag];
    myservo.write(servowerte[offen_anschlag]);
    state = offen_anschlag;
    delay(1500);

  }
  else
  {
    servo_us = servowerte[geschlossen_anschlag];
    myservo.write(servowerte[geschlossen_anschlag]);
    state = geschlossen_anschlag;
    delay(1500);
  }
  digitalWrite(relaisPin, HIGH); // Strom vom Servo nehmen


}


void loop() {
  wdt_reset();
  while (!digitalRead(10)); // watchdog manuell auslösen

  static uint32_t altmillis;
  auf = !digitalRead(signalPin);

  INTERVAL(5000)
  {
    //  auf=!auf;
  }

  if (myservo.moving())  // das Servo wird über Relais vom Strom getrennt, 
  {
    altmillis = millis();
    digitalWrite(relaisPin, LOW);  // LOW aktiv
  }

  if (millis() - altmillis > nachlaufzeit)  // das Servo wird über Relais vom Strom getrennt, 
  {
    digitalWrite(relaisPin, HIGH);  // LOW aktiv
  }

  if (auf && state == geschlossen && !myservo.moving())
  {
    servo_us = servowerte[offen_anschlag];
    myservo.write(servowerte[offen_anschlag]);
    state = offen_anschlag;
  }

  if (auf && state == offen_anschlag && !myservo.moving())
  {
    servo_us = servowerte[offen];
    myservo.write(servowerte[offen]);
    state = offen;
  }

  if (auf && state == geschlossen_anschlag && !myservo.moving())
  {
    servo_us = servowerte[offen_anschlag];
    myservo.write(servowerte[offen_anschlag]);
    state = offen_anschlag;
  }

  if (!auf && state == offen && !myservo.moving())
  {
    servo_us = servowerte[geschlossen_anschlag];
    myservo.write(servowerte[geschlossen_anschlag]);
    state = geschlossen_anschlag;
  }

  if (!auf && state == geschlossen_anschlag && !myservo.moving())
  {
    servo_us = servowerte[geschlossen];
    myservo.write(servowerte[geschlossen]);
    state = geschlossen;
  }

  if (!auf && state == offen_anschlag && !myservo.moving())
  {
    servo_us = servowerte[geschlossen_anschlag];
    myservo.write(servowerte[geschlossen_anschlag]);
    state = geschlossen_anschlag;
  }

  INTERVAL(1000) {
    Serial << "State: " << state << "\tPot: " << auf << "\tServo uS: " << servo_us << endl;
  }

}

wdt_enable(WDTO_2S); // Watchdog auf 1 s stellen

Da ist eine Kleinigkeit faul...
Vielleicht nicht wichtig, stört aber beim lesen.

Leider hat du meine Ansage:

Diese kommen nicht aus dem WDT Reset loop raus.
Nicht richtig wahr genommen.
Zumindest den Grund für den ResetLoop nicht akzeptiert.

Sicher, dass der Grund hier bei dir nicht zutrifft?
Denn irgend eine Vorsichtsmaßnahme, dagegen, sehe ich bei dir nicht.

Note that for newer devices (ATmega88 and newer, effectively any AVR that has the option to also generate interrupts), the watchdog timer remains active even after a system reset (except a power-on condition), using the fastest prescaler value (approximately 15 ms). It is therefore required to turn off the watchdog early during program startup

Quelle

Hi combie, ich versuche mal deine Angaben zu interpretieren und umzusetzen.

Der uC ist ein 328 smd, wie auf dem Uno
Die 2 Sekunden Watchdog und 1S im Kommentar stören den Ablauf nicht und beim rumtesten aktualisiere ich die Kommentare nur wenns wichtig ist

Ich ging bisher davon aus, dass der Watchdog zuverlässig bei allem geht, wenn er in der while(1) auslöst.

Oder muss ich noch wdt_disable(); an den Anfang vom setup() machen, um den Bug zu umgehen?

Der uC ist ein 328 smd, wie auf dem Uno

Auf dem UNO ist ein 328P
Ja gut... ist vielleicht ein bisschen pingelig.... von mir.

Die 2 Sekunden Watchdog und 1S im Kommentar stören den Ablauf nicht und beim rumtesten aktualisiere ich die Kommentare nur wenns wichtig ist

Meine Sicht sagt: Besser kein Kommentar, als ein falscher.
OK, vielleicht ist das auch ein wenig pingelig....

Oder muss ich noch wdt_disable(); an den Anfang vom setup() machen, um den Bug zu umgehen?

Hinter meinem Link findet sich doch ein Beispiel, wie man das abhandeln kann....
Ebenso im Datenblatt des µC.
Was gefällt dir daran nicht?

Übrigens:

ist kein Bootloader drauf, hab mit usbasp geflasht. Fuses vielleicht?

Woher soll ich wissen, ob du die Fuses für den Betrieb ohne Bootloader passend geändert hast?
Das weißt nur du.

Hi

Wenn der Wachhund nach einer Sekunde zubeißt, aber alleine schon 2 Sekunden im Bootloader gewartet wird, hilft Dir ein wdt_disable() in setup() wohl nicht mehr - da bist Du bereits im nächsten Reset in der 2 Sekunden-Pause des Bootloader.
Ohne Bootloader auch keine 2 Sekunden Boot-Loader-Wartezeit ...

MfG

Nochmal zu meinen Annahmen, bitte um Klarstellung, ab wo ich einen Denkfehler habe:
Bezugnahme auf obigen Sketch, ohne Änderung
Sketch läuft und tut was er soll
Wurde per usbasp geflasht
Fuses wurden nicht geändert (kenne mich noch nich wirklich damit aus)
Durch grounden von pin 10 bleibt der Sketch in der while(digitalRead(10) gefangen
Dies löst zuverlässig (am seriellen Monitor überwachten) Reset aus.
Bleibt der Taster gedrückt, geht das alle 2 Sekunden so
Meine Schlussfolgerung: Watchdog hat keinen Bug.
Deaktiviere ich den Watchdog am Anfang und die EMV schlägt zu, bevor er wieder aktiviert ist, habe ich evtl. ein Problem

Nun, wo ist meine Denke/Annahme falsch?