Forum: Mikrocontroller und Digitale Elektronik Timingfehler sichten


von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Hi,

ich habe leider immer noch ein sporadisches Problem in meinem Code auf 
dem 93% gefülltem Atmega16 bei 8Mhz, dass sich erst nach minutenlangem 
Lauf zeigt.

ich versuche hier einige Vermutungen mit Codeschnipsel zu hinterfragen, 
in der Hoffnung dass euch etwas auffällt, dass mir endlich weiter hilft.

Basisproblem: das Programm bleibt hängen! (Und hat am Ausgang einen 
Zustand der niemals dort verweilen darf.)
Also "emergencyStop();" [setzt die richtigen Pinne auf 0] wird nicht 
mehr ausgeführt, wenn "isSecure()==false" [auch nur ein EingangsPin]

Teilprobleme:
1. Ich verwende die "countdown.h" von hier 
http://www.gjlay.de/software/c-code/countdown.html (Dachte eigentlich 
die Sourcen hier aus dem Forum zu haben, kann den Beitrag jedoch leider 
nicht finden)

Ist es möglich, dass ich damit bereits ein deadlock produziere,
indem man diese counter zu viel verwendet
bzw. dessen Pausen zu klein definiert?


Folgnder ISR, ist von mir nicht abgeändert worden:
1
ISR(TIMER2_COMP_vect)
2
        {
3
                static uint16_t irqs_10ms;
4
5
                wdt_reset();
6
7
                ////////////////////////////////////////////////////////////
8
                // 10 ms-Takt für Jobs: countdown-Zähler, Tasten-Entprellung, DCF, ...
9
                irqs_10ms = 1 + irqs_10ms;
10
11
                // Sind 10 ms voll?
12
                // IRQS wird im Makefile definiert, es gibt die Anzahl der
13
                // IRQs pro Sekunde an.
14
                // Um 10ms zu erhalten, teilen wir also durch 100
15
                if (irqs_10ms >= IRQS / 100)
16
                irqs_10ms = 0;
17
18
                // Führe nicht alle Jobs gleichzeitig aus, damit eine ISR nicht
19
                // zu lange dauert. Stattdessen staffeln wir die Aufrufe: es gibt
20
                // nur einen je 10ms, aber immer einen anderen (oder garkeinen).
21
22
                if (0 == irqs_10ms)   job_countdown();
23
                // if (1 == irqs_10ms)   mach_was_alle_10ms();
24
                // if (2 == irqs_10ms)   mach_nochwas_alle_10ms();
25
        }

2. Ich verwende den WATCHDOG:
Tue ich dies wirklich richtig? "ISR(TIMER2_COMP_vect)" macht ja auch 
bereits einen reset:
1
#include <avr/wdt.h>
2
#include ...
3
4
int main() {
5
        wdt_reset();//needet before reset on this MCU?
6
        wdt_disable();//sometimes need reset first...
7
        loadEEValues();
8
        inits();
9
        emergencyStop();//to be sure!
10
        initBuffers();
11
12
        view_boot();//hier steht etwas falsches im Display
13
14
        while (!sensorWormUp()){;}
15
16
        bool anyKeyInput = false;
17
        wdt_enable(WDTO_250MS);
18
        while (1) {
19
                temperatureCheck();
20
                if (isSecure()) {
21
                        anyKeyInput = scanButtons();
22
                        processing();//0,2Sek mit countdown.h
23
                        interpretButtons();//0,2Sek  mit countdown.h
24
                } else {
25
                        emergencyStop();
26
                }
27
                view(anyKeyInput);//0,2Sek - 1,5Sek  mit countdown.h
28
                wdt_reset();
29
        }
30
}

3. Lesen und schreiben in den eeMem.
Hier der nahezu volle Code, da ja evtl. der kleinste Fehler reichen 
kann:
1
#define DEFAULT_WT 500
2
#define DEFAULT_MT 900
3
#define DEFAULT_AA 0
4
#define DEFAULT_DIM 6
5
#define DEFAULT_HOLD 2
6
#define DEFAULT_TTC 0
7
uint16_t EEMEM eeTemperatureWork = DEFAULT_WT;
8
uint16_t EEMEM eeTemperatureMelting = DEFAULT_MT;
9
uint8_t EEMEM eeAlarmActive = DEFAULT_AA;
10
uint8_t EEMEM eeDisplayDimming = DEFAULT_DIM;
11
uint8_t EEMEM eeHoldingMelt = DEFAULT_HOLD;
12
uint8_t EEMEM eeTankCorrection = DEFAULT_TTC;
13
14
15
/* saved in EEPROM */
16
uint16_t volatile temperatureWork;
17
uint16_t volatile temperatureMelting;
18
bool volatile alarmActive;
19
uint8_t volatile displayDimming;
20
uint8_t volatile holdingMeltingPeak;
21
uint8_t volatile tankCorrection;
22
/* END of saved in EEPROM */
23
24
#define temperatureWork_Min 400UL
25
#define temperatureWork_Max 600UL
26
27
#define temperatureMelting_Min 800UL
28
#define temperatureMelting_Max 990UL
29
30
#define temperature_Step 10
31
32
#define displayDimming_MAX 15
33
#define holdingMeltingPeak_MAX 10
34
35
#define tanKCorrection_MIN 0
36
#define tanKCorrection_MAX 10
37
38
void get_WT() {
39
        uint16_t e = eeprom_read_word(&eeTemperatureWork);
40
        //Not sure why eeprom could be destroyed or *.eep is not flashed
41
        if (e >= temperatureWork_Min && e <= temperatureWork_Max) {
42
                temperatureWork = e;
43
        } else {
44
                temperatureWork = DEFAULT_WT;
45
                save_WT();
46
        }
47
}
48
49
void get_MT() {
50
        uint16_t e = eeprom_read_word(&eeTemperatureMelting);
51
        //Not sure why eeprom could be destroyed or *.eep is not flashed
52
        if (e >= temperatureMelting_Min && e <= temperatureMelting_Max) {
53
                temperatureMelting = e;
54
        } else {
55
                temperatureMelting = DEFAULT_MT;
56
                save_MT();
57
        }
58
}
59
60
void get_AA() {
61
        alarmActive = eeprom_read_byte(&eeAlarmActive) > 0;
62
}
63
64
void get_DIM() {
65
        uint8_t e = eeprom_read_byte(&eeDisplayDimming);
66
        //Not sure why eeprom could be destroyed or *.eep is not flashed
67
        if (e <= displayDimming_MAX) {
68
                displayDimming = e;
69
        } else {
70
                displayDimming = DEFAULT_DIM;
71
                save_DIM();
72
        }
73
}
74
75
void get_Hold() {
76
        uint8_t e = eeprom_read_byte(&eeHoldingMelt);
77
        //Not sure why eeprom could be destroyed or *.eep is not flashed
78
        if (e <= holdingMeltingPeak_MAX) {
79
                holdingMeltingPeak = e;
80
        } else {
81
                holdingMeltingPeak = DEFAULT_HOLD;
82
                save_Hold();
83
        }
84
}
85
86
void get_TTC() {
87
        uint8_t e = eeprom_read_byte(&eeTankCorrection);
88
        //Not sure why eeprom could be destroyed or *.eep is not flashed
89
        if (e >= tanKCorrection_MIN && e <= tanKCorrection_MAX) {
90
                tankCorrection = e;
91
        } else {
92
                tankCorrection = DEFAULT_TTC;
93
                save_TTC();
94
        }
95
}
96
97
void loadEEValues() {
98
    get_WT();
99
    get_MT();
100
    get_AA();
101
    get_DIM();
102
    get_Hold();
103
    get_TTC();
104
}
105
106
void save_WT() {
107
#ifndef GCC
108
        eeprom_update_word(&eeTemperatureWork, temperatureWork);
109
#endif
110
}
111
112
void save_MT() {
113
#ifndef GCC
114
        eeprom_update_word(&eeTemperatureMelting, temperatureMelting);
115
#endif
116
}
117
118
void save_DIM() {
119
#ifndef GCC
120
        eeprom_update_byte(&eeDisplayDimming, displayDimming);
121
#endif
122
}
123
124
void save_Hold() {
125
#ifndef GCC
126
        eeprom_update_byte(&eeHoldingMelt, holdingMeltingPeak);
127
#endif
128
}
129
130
void save_TTC() {
131
#ifndef GCC
132
        eeprom_update_byte(&eeTankCorrection, tankCorrection);
133
#endif
134
}
135
136
void autosave() {
137
        if (count.ms10_16.volatilePrg == 0) {
138
                /*
139
                 * all use  eeprom_update_
140
                 * So we dont care about non changing values
141
                 */
142
                save_WT();
143
                save_MT();
144
                save_TTC();
145
                save_Hold();
146
                save_DIM();
147
                dot7seg_ON = false;
148
        }
149
}


Und zu guter letzt, was ich eigentlich beobachte und mich dazu treibt, 
dass ich denke irgendwas von obigen Teilproblemen ist schuld an meinem 
Disaster:

"process()" läuft einige Tage ohne Auffälligkeiten durch. Dann Hängt das 
Programm Plötzlich und ich nur noch durch Trennen vom Strom zu 
"re(se)tten".
(Dahher habe ich den watchdog doch mit eingebaut.)

Nach einem Reset ist jedoch ein wert aus/im Eprom falsch.
Dies erkenne ich bereits während des "bootens" bei der Displayanzeige: 
"view_boot();" (Dort werden normalerweilse zwei Werte angezeigt. Temp 
A=50 und Temp B=90)

Nun zeigt er jedoch Fehlerhaft 2x "50" an :(
Ohne Watchdog blieb er in diesem Zustand ewig und nur ein neues flashen 
brachte den Wert Ablauf zurück.
Mit Watchdog und meinen neuen gettern, verweilt er dort 250ms, resettet 
sich und hat dann die korrekten Werte aus meiner Notfallroutine.

Was mich am Meisten irritiert ist, dass er HIER dann vor der 
Hauptschleife bereits aussteigt und sich resettet jedoch im Langzeittest 
irgendwo in der Hauptschleife stecken MUSS (sonst würde man es ja sofort 
sehen)

Hat irgendwer einen Hinweis, was dort oben in den Schnipseln unsachgemäß 
ist oder ob ich noch weitere Details posten soll, damit wir dem Rätsel 
auf die Spur kommen?

Vielen Dank für eure Unterstützung. Ich hoffe diesmal präzise genug zu 
sein.

Grüße David

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Normalerweise ist es keine gute Idee, den WD in einer Timer ISR 
zurückzusetzen, denn die ISR kann leicht noch ausgeführt werden, auch 
wenn das Hauptprogramm schon im Nirvana ist.
Der sinnvollste Platz für den WD Reset ist also die Hauptschleife.

von Oliver S. (oliverso)


Lesenswert?

Sich unbeabsichtigt ändernde Werte im Eeprom könne durch eine nicht 
gesetzte Brown-out Fuse kommen. Da diese Unterspannung der Versorgung 
abfängt, steckt damit ein Hardwareproblem dahinter.

Oliver

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Oliver S. schrieb:
> Brown-out Fuse / Unterspannung
> ... Hardwareproblem dahinter.
>
Ich verwende ein fertiges WideRande Open-Frame Netzteil mit 1A.

Gehe ich etwas falsch in der Annahme,  dass dieses mehr als genug für:
Atmega16
3x OK
1x Summer
1x RTC
1x HT16K33
4x 7-Segmentabzeige
2x LED
..Hundefutter

Sind?

Genaue Bauteilbezeichnubg kann ich nachliefern,  wenn Zweifel sich 
erhärten.

von D a v i d K. (oekel) Benutzerseite


Angehängte Dateien:

Lesenswert?

Oliver S. schrieb:
> Sich unbeabsichtigt ändernde Werte im Eeprom könne durch eine nicht
> gesetzte Brown-out Fuse kommen.

Ich habe mir gerade:
https://www.mikrocontroller.net/articles/Brownout
durchgelesen und tatsächlich festgestellt, dass ich diesen 
Sicherheitsmechanismus nicht verwende. (Siehe Screenshot 1)

Ich verwende zudem folgendes Netzteil:
https://www.ebay.de/itm/1A-1000mA-Power-Supply-AC-DC-5V-Buck-Converter-Step-Down-Modul-Small-Size/172258848263

Kann es sein, dass die Schaltstufen (Siehe Anhang GELB 230V) beim 
Anlaufen (Motor, Lüfter, Heizung) so viel Strom ziehen, dass der Trafo 
kurzzeitig versagt und keine 5V liefern kann?

Wirklich jeglicher Hinweis zum Testen bzw. retten der Schaltung hilft 
mir gerade weiter!

: Bearbeitet durch User
von глупний форентроль (Gast)


Lesenswert?

Beginn damit den Watchdog nicht zu benutzen. Damit kann man Fehler 
kaschieren, die man besser finden sollte.

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.