Forum: Mikrocontroller und Digitale Elektronik kann wdt_reset() wegoptimiert werden?


von Andreas (Gast)


Lesenswert?

Hallo zusammen,

ich arbeite mit einem AT90CAN-ontroller und habe den Watchdog eingebaut. 
Dieser wird zunächst mit 2 sek initializiert und an mehreren Stellen 
reset-et.
In einer Funktion wird der Reset durch den WatchDog ausgelöst, obwohl 
dieser in der Funktionen durch wdt_reset zurückgesetzt wird. Kann es 
sein, dass diese Funktion wegoptimiert wird?

Folgendes Phänomen:
Die Funktion wird durchgeführt (mindestens ein Einschaltimpuls 
vorhanden)
Die Funktion wird teilweise nicht beendet, d.h. es werden manchmal nur 
drei Impuls durchgeführt bevor der Reset ausgelöst wird, machmal nur 
einer, ein anderes mal wird die Funktion bis zu Ende durchgeführt und es 
wird in die main zurückgesprungen.

Anbei die Funktion, die betroffen ist:
(Erklärung im Anschluss)
1
uint16_t Relais_ON (void)
2
{
3
   cli(); // Interrupts unterbrechen
4
   uint8_t puls=0;     // Schaltimpuls - Zähler
5
   uint16_t Spg_Fzg=0; // Fahrzeugspannung aus AD-Wandler
6
   // Halbbrücke vorbereiten:
7
   PORTC &= ~_K1_on    // Relaisausgang Pin Low
8
   PORTC |= _K1_off    // Relaisausgang Pin High
9
   do{
10
  wdt_reset();
11
  if (puls != 0) // Fehler beim einschalten: Erneut Auschalten zum 
12
                       // Reinigen der Kontakte
13
  {
14
    PORTC |= _K1_on     // Rel.1 an
15
    PORTC &= ~_K1_off   // Rel.1 ab
16
    Rel_Freigabe(Ausschaltdauer); // Freigabe - Impuls für sicheres Ausschalten
17
                // Ausschaltdauer = 30
18
    _delay_ms(100-Ausschaltdauer);
19
    //anschl. wieder einschalten nach mind. 100ms
20
    PORTC &= ~_K1_on    // Relaisausgang Pin Low
21
    PORTC |= _K1_off    // Relaisausgang Pin High
22
  }  // Relais hängt? / reinigen der Kontakte
23
24
  Rel_Freigabe(Einschaltdauer); // Freigabe - Impuls für 50ms: sicheres Einschalten
25
  _delay_ms(200-Einschaltdauer); //Einschaltdauer = 50
26
  // Messen ob relais geschaltet hat
27
  puls++; // Einschaltimpulszähler erhöhen
28
  if (PIND & _GND_FZ) // Pin Abfrage, ob Masse durchgeschaltet ist
29
      Spg_Fzg = ADC_Read(_ADC1,16); // reale Spannungsmessung auf Plus-Seite
30
                        // 16= Mittelwert aus 16 Einzelmessungen
31
  else
32
      Spg_Fzg = 111; // sonst "Erkennungswert" unter grenze 111 entspricht ca. 4V
33
   } while ((Spg_Fzg < U_16V) && (puls<5));
34
35
   PORTC |= 0x03; // Halbbrücke in Neutralstellung
36
   sei(); //Interrupts freigeben
37
   if (puls == 5)
38
      return(5);
39
   return (Spg_Fzg);
40
}

In dieser Funktion werden zwei Relais eingeschaltet (eins für die 
Plus-Leitung, eins für die Minusleitung)und durch Spannungsmessung 
festgestellt, ob das Relais geschaltet hat. Falls nicht, wird der 
Einschaltimpuls maximal 5-mal wiederholt, nachdem zuvor die Relais 
ausgeschaltet wurden.

Hier die Funktion Relaisfreigabe:
1
void Rel_Freigabe (uint8_t Dauer)
2
{
3
  cli();
4
  PORTG |= _Inhibit; //Freigabeimpuls am Ausgang
5
  if (Dauer == Einschaltdauer)
6
  _delay_ms(Einschaltdauer);
7
  else
8
  _delay_ms(Ausschaltdauer);
9
  PORTG &= ~_Inhibit; // Freigabeimpuls beenden
10
}

von Daniel V. (danvet)


Lesenswert?

Schau in das Listing des entsprechenden Files, dann siehst du, ob die 
Funktion wegoptimiert wurde (was ich nicht glaube).
Wie immer liegt das Problem im kompletten Code verborgen. Deine vielen 
Delays machen mich misstrauisch. Bei einem Watchdog von 2sec hast du mit 
deinen Delays die Zeit schnell ereicht.

von Andreas (Gast)


Lesenswert?

Daniel V. schrieb:
> Bei einem Watchdog von 2sec hast du mit
> deinen Delays die Zeit schnell ereicht.

Das schon, aber der wdt_reset ist in der do...while Schleife enthalten 
und dieser Durchlauf müsste maximal 100ms + 200ms + ADC_Read < 400ms 
sein, wobei die ADC Messung keine 100ms dauert.

Wie komme ichan die Listings?

von der_Wachhund (Gast)


Lesenswert?

> Dieser wird zunächst mit 2 sek initializiert und an mehreren Stellen
> reset-et.

Ganz schlechte Idee. Ein Watchdog sollte genau nur an einer Stelle,
vorzugsweise in main() resettet werden.

der_Wachhund

von Daniel V. (danvet)


Lesenswert?

Andreas schrieb:
> Daniel V. schrieb:
>> Bei einem Watchdog von 2sec hast du mit
>> deinen Delays die Zeit schnell ereicht.
>
> Das schon, aber der wdt_reset ist in der do...while Schleife enthalten
> und dieser Durchlauf müsste maximal 100ms + 200ms + ADC_Read < 400ms
> sein, wobei die ADC Messung keine 100ms dauert.
>
> Wie komme ichan die Listings?

1.) Ich sehe kein "do...while"
2.) Der Compiler erzeugt deine Listings. In den Compileroptionen 
nachschauen. Meist heisst die datei *.lst und kann mit einem Texteditor 
angeschaut werden.
Edit:
3.) eventuell solltest du dich mal mit Timern beschäftigen ;-)

von Andreas (Gast)


Lesenswert?

Daniel V. schrieb:
> 1.) Ich sehe kein "do...while"

Ich schon
Funktion Relais_ON
Zeile 9: do
Zeile 32: while

von Peter D. (peda)


Lesenswert?

Andreas schrieb:
> ich arbeite mit einem AT90CAN-ontroller und habe den Watchdog eingebaut.
> Dieser wird zunächst mit 2 sek initializiert und an mehreren Stellen
> reset-et.

Wozu diese Umstände?
Laß ihn einfach disabled, das bewirkt exakt das selbe.

Ein Watchdog mit mehreren Triggern ist vollkommen sinnlos, da 
wirkungslos.

von Karl H. (kbuchegg)


Lesenswert?

.... schrieb im Beitrag #3142430:
> immer konzentriert euch darauf.... macht 1000 sinnlose beiträge... immer
> zu!
>
> dass er _deleay_ms() mit variablen argument nutzt


... ist deine Interpretation dessen, dass er die Argumente klein 
geschrieben hat. Das können Variablen sein, können aber auch Makros 
sein.

Wie schon geschrieben: Rein aus diesem Code alleine sind noch zu viele 
Fragen offen.

von Andreas (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
>> dass er _deleay_ms() mit variablen argument nutzt
>
>
> ... ist deine Interpretation dessen, dass er die Argumente klein

zu den delays:
_delay_ms(Einschaltdauer);
Einschaltdauer wurde in den defines definiert, damit ich diese an einer 
Stelle ändern kann.
#define Einschaltdauer 50

_delay_ms(Einschaltdauer);

Somit sollte das OK sein.

Peter Dannegger schrieb:
> Wozu diese Umstände?
> Laß ihn einfach disabled, das bewirkt exakt das selbe.

Aber ich brauche den Watchdog, falls sich das Programm mal aufhängt, im 
Moment habe ich das Problem, dass er auslöst, wo er nicht sollte.
Da ist ein Bug im Code und ich weiß nicht wo.

Was muss ich noch liefern, dass es klarer wird?

von Daniel V. (danvet)


Lesenswert?

.... schrieb im Beitrag #3142430:
> immer konzentriert euch darauf.... macht 1000 sinnlose beiträge... immer
> zu!
>
> dass er _deleay_ms() mit variablen argument nutzt und daduach massive
> Wait-Zeiten bekommt, ist mal wieder zu viel fürs Experten-- ääähhh
> Spammerforum..

Woher weisst du denn wie seine Delay-Funktion aussieht?

von Daniel V. (danvet)


Lesenswert?

Peter Dannegger schrieb:
> Andreas schrieb:
>> ich arbeite mit einem AT90CAN-ontroller und habe den Watchdog eingebaut.
>> Dieser wird zunächst mit 2 sek initializiert und an mehreren Stellen
>> reset-et.
>
> Wozu diese Umstände?
> Laß ihn einfach disabled, das bewirkt exakt das selbe.
>
> Ein Watchdog mit mehreren Triggern ist vollkommen sinnlos, da
> wirkungslos.

Da hat Peter Recht.
Im Idealfall wird der Watchdog in der Mainschleife 1x gtriggert. Alle 
anderen Funktionen wissen nichts von einem Watchdog.
Überleg mal, was das dann für deinen Programmaufbau heisst und was es 
dann mit Delays und "do while" auf sich hat...

von Peter D. (peda)


Lesenswert?

Andreas schrieb:
> Moment habe ich das Problem, dass er auslöst, wo er nicht sollte.

Damit hast Du doch die Antwort, daß der Watchdog überhaupt nicht 
geeignet ist, Softwarefehler zu finden. Im  Gegenteil, er kann sie 
verstecken und sie richten später umso mehr Schaden an.


Andreas schrieb:
> Da ist ein Bug im Code und ich weiß nicht wo.

Dann mußt Du eben debuggen.
Der Watchdog hilft dabei in keinster Weise. Nach dem Watchdogreset sind 
ja alle Informationen verloren, die den Fehler eingrenzen könnten.

Den Watchdog implementiert man erst, wenn das Programm in allen 
Funktionen bereits fehlerfrei läuft. Und dann natürlich mit nur einem 
Trigger, der nicht ein Interrupt sein darf!

von .... (Gast)


Lesenswert?

>tolle Kommentare!!!
toller codestil... defines in normalschreibung -.-
dass du dich traust damit öffentlich zu gehen^^

und ja, sich über einen nick-name aufzuregen, ist erst recht ganz großes 
Kino, ich nenne mich ab sofort GayDeerLover... haste davon was? :-O
Anmelden wär sinnvoll.. aber is ja nich (pssst: das issn hassthema 
hier!)

von Karl H. (kbuchegg)


Lesenswert?

.... schrieb:
>>tolle Kommentare!!!
> toller codestil... defines in normalschreibung -.-


Ist zwar im Prinzip richtig.
Trotzdem sag ich nur: wie man in den Wald hineinruft ....
Also beschwer dich nicht.
Du hättest ja auch erst mal nachfragen können, wie seine Zeiten 
definiert sind, anstatt ihn gleich als 'Depp' zu titulieren.

von .... (Gast)


Lesenswert?

Ei ei, sir :-)
Zum glück ist ein Wald ein guter Schall absorber ;-)


Und jaaa.. "ei" schreibt man anders -.- sonst noch was?
Thema is ja nun durch, das Problem war nie das Problem... und.. aaach 
herje.
Armes forum. :-( Müsste man sich anmelden, würde man es sich länger 
überlegen, ob man sich als Threadersteller so entblößt.. da hätte man 
vllt mal verschiedene Optimierungsstufen durchprobiert und mehr code 
auskommentiert, vllt eine minimalvariante des Problems zusammengestellt 
und nebenbei rausgefunden, dass es am Stack liegt.

von Daniel V. (danvet)


Lesenswert?

.... schrieb:
> Ei ei, sir :-)
> Zum glück ist ein Wald ein guter Schall absorber ;-)
>
>
> Und jaaa.. "ei" schreibt man anders -.- sonst noch was?
> Thema is ja nun durch, das Problem war nie das Problem... und.. aaach
> herje.
> Armes forum. :-( Müsste man sich anmelden, würde man es sich länger
> überlegen, ob man sich als Threadersteller so entblößt.. da hätte man
> vllt mal verschiedene Optimierungsstufen durchprobiert und mehr code
> auskommentiert, vllt eine minimalvariante des Problems zusammengestellt
> und nebenbei rausgefunden, dass es am Stack liegt.

Hätte man sich angemeldet, hätte man sich überlegt ob man zum Thema 
beiträgt oder es einfach bleiben lässt...
Immerhin hat der TO einen sinnvollen Namen, im Gegensatz zu dir.

von Andreas (Gast)


Lesenswert?

@....

tut mir leid, dass ich kein µC-Gott bin, wie du

wenn ich Profi wäre, würde ich nicht fragen,
_______
@ alle anderen:
dass ein reset reicht weiß ich auch, aber mich hat gewundert, dass der 
WD einen reset auslöst. Aber ich konnte den fehler nicht eingrenzen und 
hatte vermutet, dass es an den delays in dieser Funktion liegt.
Doch nachdem der reset in der Funktion eingebaut ist, hat es mich noch 
mehr gewundert, dass der WDT einen reset durchführt, weil die 
eigentliche Funktion nicht so lange für einen Durchlauf brauchen sollte

Wenn der Fehler gefunden ist, kommt der wdt_reset direkt nach beginn der 
Programmschleife.

zu delays und defines:
Wie kann man das eleganter lösen? ich möchte nicht bei jedem delay eine 
zahl hineinschreiben um bei einer Änderung alle delays zu kontrollieren 
und nachzubessern, daher habe ich das über defines erledigt.
Was spricht dagegen? (das ist ernst gemeint)- Ich bin kein Profi, ich 
möchte ja auch lernen
die delay-Funktion nutze ich von der delay.h, ist also nichts selber 
gestricktes.

von Karl H. (kbuchegg)


Lesenswert?

Andreas schrieb

> dass ein reset reicht weiß ich auch, aber mich hat gewundert, dass der
> WD einen reset auslöst. Aber ich konnte den fehler nicht eingrenzen und
> hatte vermutet,

vermuten ist immer schlecht.
Du brauchst belastbare Zahlen.

> mehr gewundert, dass der WDT einen reset durchführt, weil die
> eigentliche Funktion nicht so lange für einen Durchlauf brauchen sollte

Schalt am Anfang der Funktion (Schleife) eine LED ein, und am Ende 
wieder aus. Dann hängst du ein Oszi an (oder da es sich um eine LED 
handelt, beobachtest du diese), dann weißt du was Sache ist.


> zu delays und defines:
> Wie kann man das eleganter lösen?

Das passt schon.
Es ist nur eine übliche C-Konvention, dass Makronamen ausschliesslich in 
Grossbuchstaben geschrieben werden.

#define EINSCHALT_ZEIT   50
#define AUSSCHALT_ZEIT  100

dann steht im Code

   _delay_ms( EINSCHALT_ZEIT );

und man sieht auf einen Blick, dass es sich hier um ein Makro handelt. 
IN manchen Fällen ist diese Kenntnis nämlich wichtig, ob man es mit 
einem Makro oder zb mit einer echten Funktion zu tun hat

    k = MAX( i++, j++ )

kann etwas anderes sein als

    k = max( i++, j++ )

das erste ist ein Makro (erkennbar an der Grossschreibung) und da heisst 
es dann vorsichtig sein! Ist das Makro so definiert

#define MAX(a,b)   (a)>(b) ? (a) : (b)

dann kriegst du nicht ganz das Ergebnis, das du dir vorgestellt hast.

Gewöhn dich einfach daran, dass Makros ausschliesslich in 
Grossbuchstaben geschrieben werden und umgekehrt eine Schreibweise mit 
lauter Grossbuchstaben ausschliesslich für Makros reserviert ist, und du 
bist auf der Konvention, die Millionen C Programmierer weltweit 
verwenden und gut damit fahren.

PS: Den Optimizer hast du ja hoffentlich eingeschaltet. Das ist der 
zweite Stolperstein bei _delay_ms

von maveric00 (Gast)


Lesenswert?

Hallo,

Daniel V. schrieb:
> Immerhin hat der TO einen sinnvollen Namen, im Gegensatz zu dir

Kann ich nicht bestätigen, seine Beiträge in diesem Thread entsprechen 
seinem Nick komplett (lauter Auslassungspunkte, also kein Inhalt).

@Andreas:
Es mag eine blöde Frage sein, aber bist Du sicher, dass der Reset durch 
den Watchdog ausgelöst wird (also erst 2 Sekunden nach dem ersten 
Einschaltpuls)? Nicht, dass das Schalten der Relais die Spannung am µC 
so einbrechen lässt, dass dadurch der Reset ausgelöst wird. Dafür würde 
auch das eher zufällige Verhalten passen.

Schöne Grüße,
Martin

von Andreas (Gast)


Lesenswert?

maveric00 schrieb:
> @Andreas:
> Es mag eine blöde Frage sein, aber bist Du sicher, dass der Reset durch
> den Watchdog ausgelöst wird (also erst 2 Sekunden nach dem ersten
> Einschaltpuls)? Nicht, dass das Schalten der Relais die Spannung am µC
> so einbrechen lässt, dass dadurch der Reset ausgelöst wird. Dafür würde
> auch das eher zufällige Verhalten passen.

Das war ein guter Tipp! Ich seh den Wald vor lauter Bäumen nicht. Ich 
hatte mich so auf die Funktion eingeschossen, dass ich weder rechts noch 
links geschaut habe.
Der Reset wird tatsächlich nicht vom WDT ausgelöst, aber die Funktion 
ist der Auslöser.
Meine 5V Spannungsversorgung sind stabil, aber der Spannungsregler gibt 
den Reset Impuls aus. Da muss ich mir die EIngangsspannung mal genauer 
ansehen.

Danke für den Hinweis...
Melde mich später nochmal

von Andreas (Gast)


Lesenswert?

So, habe noch mal mit dem Oszilloskop die Eingangsspannung gemessen.
Es gibt tatsächlich einen Spannungseinbruch, an der Versorgung nicht so 
groß, wie am Eingang des Spannungsreglers.
Ich sollte den Eingangskondensator vergrößern, um den Einbruch zu 
kompensieren.
Danke noch mal an alle, die mir mit konstruktivenm Vorschlägen und Ideen 
geholfen haben.
Auch die allgemeinen Sachen, wie Großschreibung der Makros

Karl Heinz Buchegger schrieb:
> Es ist nur eine übliche C-Konvention, dass Makronamen ausschliesslich in
> Grossbuchstaben geschrieben werden.

Ich wünsche ein schönes WE
ich werde mich dann mal mit der Eingangsbeschaltung auseinandersetzen 
und die Makronamen überarbeiten...

von maveric00 (Gast)


Lesenswert?

Hallo,

freut mich, dass es geholfen hat - ich hatte ein ähnliches Problem bei 
einer Platine, die 6 mid-Power und 1 High-Power RGB(W)-LEDs per PWM 
ansteuert. Auch hier kam es sporadisch zu Resets, zuerst nur während der 
CAN-Kommunikation (erhöhte Stromaufnahme), weswegen ich auch zuerst in 
diesen Routinen gesucht habe.

Hier war neben der (leichten) Vergrößerung des Kondensators am Eingang 
noch ein Entkoppel-Widerstand (bei mir 5.6 Ohm) vor eben jenem 
Kondensator (zwecks Bildung eines Tiefpassfilters mit in dem Fall rund 
60 Hz) sehr hilfreich. Beides muss natürlich nach dem Abzweig der 
Leistungsversorgung angeordnet sein.

Ebenso ein schönes Wochenende.

Schöne Grüße,
Martin

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.