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