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_tRelais_ON(void)
2
{
3
cli();// Interrupts unterbrechen
4
uint8_tpuls=0;// Schaltimpuls - Zähler
5
uint16_tSpg_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
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:
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.
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?
> 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
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 ;-)
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.
.... 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.
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?
.... 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?
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...
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!
>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!)
.... 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.
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.
.... 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.
@....
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.
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
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
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
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...
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