Obwohl mein Anliegen wahrscheinlich schwer zu beantworten ist, versuche ich es mal: Das Programm soll ein Thermostatventil, wie allg. üblich, nach der Temperatur regeln. Die Regelung läuft schon nach meinen Wünschen. Das als Anhang beigefügte Programm hängt sich aber manchmal teilweise auf. Ich als Programmierlaie habe folgenden Verdacht: Die in der main-Funktion vorhandene while- Schleife wird aus irgendeinem Grund "verlassen". Das macht sich dadurch bemerkbar, dass die Tasten für AUF/ZU bzw. Sollwertverstellung nicht mehr reagieren sowie der Regler nicht mehr arbeitet. Also alles, was in der while-Schleife steht ist tot. Die im TIMER_A enthaltenen Befehle, wie z.B. Messwert und Sollwert anzeigen sowie das Abspeichern auf SD-Karte läuft allerdings weiter. Meine Frage: Kann jemand erkennen, was ich programmiertechnisch falsch gemacht habe? Kann es sein, dass der Befehl break in der Funktion "void ventil_schliessen_regler(void)" auch die while-Schleife unter bestimmten Umständen in der main-Funktion abbricht? Ich danke schon mal allen, die sich das Programm ansehen und mit konkreten Hinweisen mir helfen wollen.
:
Bearbeitet durch User
Hallo, ich habe mir Dein Programm jetzt nicht im Detail angesehen. Lt. Standard verlässt ein break immer nur den "innersten" Block. Dass ein break in einer Funktion zur Unterbrechung des Aufrufers führt, sollte nicht passieren. Weil man aber nie weiß, kannst Du ans Ende von main () etwas basteln, was Dir eine Ausgabe erzeugt, wenn der Code (unerwartet) ausgeführt wird. Ich würde eher mutmaßen, dass sich Dein Programm innerhalb der Schleife aufhängt...
Und ich bin erstaunt, was man doch alles in eine ISR stopfen kann...
ich habe versucht den Code zu strukturieren, ich tippe aber ob der sehr überfrachteten ISR das der Prozzi einfach die Lust verliert wie ich. Es wird ja mehr in der IRQ abgearbeitet als vermutlich Zeit ist bis der Nächste kommt. Sollwert als Int wird immer decrementiert ohne NULL zu prüfen da kann auch ein Überlauf reinspucken.
wolle g. schrieb: > Kann es sein, dass der Befehl break in der Funktion > "void ventil_schliessen_regler(void)" > auch die while-Schleife unter bestimmten Umständen in der main-Funktion > abbricht? Nein. Aber wenn das Programm neu startet, wg Versorgungs-Problemen, Watchdog, ... oder aufgrund von Stack-Problemen auf die Nase fällt, dann wird eine while-Schleife auch mal unfreiwillig verlassen.
Nein, die while wird mit an Sicherheit grenzender Wahrscheinlichkeit nicht verlassen. Als erstes solltest du deine ISRs aufräumen. Die müssen stets so kurz wie möglich bleiben. I. A. setzt man hier nur ein Flag, das in der Hauptschleife dann geprüft wird. Wenn gesetzt, wird der Code ausgeführt der jetzt im jeweiligen Interrupt ist und dein Flag wird zurückgesetzt. Sollte dein Programm sich danach weiterhin aufhängen, sind die wahrscheinlichsten Gründe Endlosschleife oder irgendein Überlauf. Du könntest am Ende der Main eine spezielle LED schalten um zu sehen ob die while(1) verlassen wurde. Aber das habe ich noch nie gehört oder erlebt.
Leider fehlt da jede Menge Code. Wie groß ist der Zwischenspeicher definiert, der da verwendet wird? Die Zählervar t wird einmal auf 0 gesetzt und dann immer hochgezählt. Wenn die nicht irgendwo zurückgesetzt wird, geht das irgendwann mal schief... Außerdem verwendet das Zwischenspeichern unnötige Zwischenvariablen, wenn die vom Compiler nicht wegoptimiert werden, kostet das unnötig Zeit und Speicher. Das break ist unschuldig. Gruß Herby
Ich hatte mir schon gedacht, dass hier eine Ferndiagnose schwierig sein wird. Ich versuche mal, mit meinen spärlichen Programmierkenntnissen die Antworten zu "analysieren". a) der Befehl break in "void ventil_schliessen_regler(void)" hat keinen Einfluss auf die Schleife in main(). b) Peter P. Petersson schrieb: > Als erstes solltest du deine ISRs aufräumen. Die müssen stets so kurz > wie möglich bleiben. I. A. setzt man hier nur ein Flag, das in der > Hauptschleife dann geprüft wird. Wenn gesetzt, wird der Code ausgeführt > der jetzt im jeweiligen Interrupt ist und dein Flag wird zurückgesetzt. Wie muss man das machen? Was ist ein Flag? Ich dachte, mit: b=b+1; if (b >9)reglerstart=1; //beeinflusst Abtastzeit 10x4=40 in TIMER_A hätte ich die gesamte Reglerfunktion aus der ISR herausgenommen. Der Regler wird nur alle 40s (Timertakt 4s * b=10 --> 40s) aufgerufen, um dann in der while-Schleife (if (reglerstart==1)regler();) bearbeitet zu werden. M.E. ist die Zeit von 4s zwischen zwei Aufrufen für zwischenspeicher_1(); auf_SD_karte_schreiben(); sollwert_anzeigen(); usw. (alles ms-Bereich) rel. groß c) Joachim B. schrieb: > Es wird ja mehr in der IRQ abgearbeitet als vermutlich Zeit ist bis der > Nächste kommt. > > Sollwert als Int wird immer decrementiert ohne NULL zu prüfen da kann > auch ein Überlauf reinspucken. Wie sollte deshalb die Variable Sollwert deklariert werden? d) Herbert P. schrieb: > Leider fehlt da jede Menge Code. Richtig. Diesen code habe ich vor allem deshalb weggelassen, da dieser in meinem als Datenspeicher bezeichneten Programm problemlos läuft. Diesen Datenspeicher wollte ich "nur" für meine Experimente (Thermostatventilregler + Tasten+ Motoransteuerung) erweitern, indem ich weitere Funktionen hinzugefügt habe. e) Peter P. Petersson schrieb: > Nein, die while wird mit an Sicherheit grenzender Wahrscheinlichkeit > nicht verlassen. Das kann ich zwar nicht beurteilen, aber warum geht nach einem "Absturz" keine Taste mehr und der Regler regelt nicht mehr? f) Aus den Antworten würde ich zunächst entnehmen, dass ich wahrscheinlich keine Fehler gemacht habe, die sofort ins Auge fallen. Vielleicht wird aber mein Fehler doch noch gefunden.
wolle g. schrieb: >> Sollwert als Int wird immer decrementiert ohne NULL zu prüfen da kann >> auch ein Überlauf reinspucken. > Wie sollte deshalb die Variable Sollwert deklariert werden? ja was ist dein Ziel? Darf bei NULL erreichen WEITER decrementiert werden? Entweder du prüfst vorher if(sollwert<erlaubter_sollwert) sollwert=sollwert+1; if(sollwert>0) sollwert=sollwert-1; ich weiss das doch nicht was du willst! Du musst wissen in welchen Grenzen sollwert laufen DARF > f) Aus den Antworten würde ich zunächst entnehmen, dass ich > wahrscheinlich keine Fehler gemacht habe, die sofort ins Auge fallen. > Vielleicht wird aber mein Fehler doch noch gefunden. gewagte Annahme weil dein Programm nicht tut was es soll!
:
Bearbeitet durch User
wolle g. schrieb: > b) Peter P. Petersson schrieb: >> Als erstes solltest du deine ISRs aufräumen. Die müssen stets so kurz >> wie möglich bleiben. I. A. setzt man hier nur ein Flag, das in der >> Hauptschleife dann geprüft wird. Wenn gesetzt, wird der Code ausgeführt >> der jetzt im jeweiligen Interrupt ist und dein Flag wird zurückgesetzt. > Wie muss man das machen? Was ist ein Flag? Ein Flag ist eine binäre (boolsche) Variable, die nurn true (wahr) oder falsch ist. Damit steuert man Abläufe zwischen Programmteilen, hier der ISR und der Hauptschleife. Siehe Interrupt > in TIMER_A hätte ich die gesamte Reglerfunktion aus der ISR > herausgenommen. > Der Regler wird nur alle 40s (Timertakt 4s * b=10 --> 40s) aufgerufen, Wenn gleich es hier vielleicht OK sein mag, so nutzt man in den allermeisten Fällen keinen so tierisch langsamen Timer. Meistens läßt man den mit 1-100ms Periodendauer laufen und generiert für langsamere Ereignisse und Aufrufe einen Teiler in Software, sprich, man zählt einen Zähler hoch, der nur all N Durchläufe eine Aktion auslöst. Damit bleibt man flexibler und kann viele, verschieden schnelle Dinge tun bzw. steuern. > M.E. ist die Zeit von 4s zwischen zwei Aufrufen für > zwischenspeicher_1(); auf_SD_karte_schreiben(); sollwert_anzeigen(); > usw. (alles ms-Bereich) > rel. groß Kann sein, ist aber trotzdem Mist, wenn das alles im Interrupt passiert. Denn damit sind andere Interrupts während dieser Zeit ausgebremst, im Extremfall werden sogar welche verschluckt. >> Sollwert als Int wird immer decrementiert ohne NULL zu prüfen da kann >> auch ein Überlauf reinspucken. > Wie sollte deshalb die Variable Sollwert deklariert werden? Das hat mit dem Deklarieren wenig zu tun. > > d) Herbert P. schrieb: >> Leider fehlt da jede Menge Code. > > Richtig. Diesen code habe ich vor allem deshalb weggelassen, da dieser > in meinem als Datenspeicher bezeichneten Programm problemlos läuft. > Diesen Datenspeicher wollte ich "nur" für meine Experimente > (Thermostatventilregler + Tasten+ Motoransteuerung) erweitern, indem ich > weitere Funktionen hinzugefügt habe. > > e) Peter P. Petersson schrieb: >> Nein, die while wird mit an Sicherheit grenzender Wahrscheinlichkeit >> nicht verlassen. > Das kann ich zwar nicht beurteilen, aber warum geht nach einem > "Absturz" keine Taste mehr und der Regler regelt nicht mehr? > > f) Aus den Antworten würde ich zunächst entnehmen, dass ich > wahrscheinlich keine Fehler gemacht habe, die sofort ins Auge fallen. > > Vielleicht wird aber mein Fehler doch noch gefunden. Sowas hier ist totaler Anfängermüll >int >ZWI1,ZWI2,ZWI3,ZWI4,ZWI5,ZWI6,ZWI7,ZWI8,ZWI9,ZW20,ZW21,ZW22,ZW23,ZW24,Z W25 >,ZW26,ZW27,ZW28 ; Schon mal was von einem Array gehört? int buffer[28]; Dann ist nämlich der Zugriff DEUTLICH einfacher, vor allem wenn man größere Datenmengen verschieben will. Mal ganz davon abgesehen, daß diese Variabeln und deren Nutzung maximal sinnlos sind. Man merkt sofort, daß du BASCOM geschädigt bist ;-)
1 | void zwischenspeichern_1(void) //eine Zwischentabelle wird im RAM angelegt |
2 | {
|
3 | mmc_buffer[t++] = hub >> 8; |
4 | mmc_buffer[t++] = hub & 0xFF; |
5 | mmc_buffer[t++] = esum >> 8; |
6 | mmc_buffer[t++] = esum & 0xFF; |
7 | mmc_buffer[t++] = e >> 8; |
8 | mmc_buffer[t++] = e & 0XFF; |
9 | mmc_buffer[t++] = temp16 >> 8; |
10 | mmc_buffer[t++] = temp16 & 0XFF; |
11 | mmc_buffer[t++] = y >> 8; |
12 | mmc_buffer[t++] = y & 0XFF; |
13 | mmc_buffer[t++] = sollwert >> 8; |
14 | mmc_buffer[t++] = sollwert & 0XFF; |
15 | mmc_buffer[t++] = umdrehung_zu >> 8; |
16 | mmc_buffer[t++] = umdrehung_zu & 0XFF; |
17 | mmc_buffer[t++] = umdrehungen_auf >> 8; |
18 | mmc_buffer[t++] = umdrehungen_auf & 0XFF; |
19 | }
|
:
Bearbeitet durch User
Joachim B. schrieb: > ja was ist dein Ziel? > Darf bei NULL erreichen WEITER decrementiert werden? Bin ich hier auf dem Holzweg? Mit "unsigned int b,k,f,l, reglerstart,t,sollwert;" gibt es m. E. keine negativen Werte. oder? Falk B. schrieb: > Ein Flag ist eine binäre (boolsche) Variable, die nurn true (wahr) oder > falsch ist. Damit steuert man Abläufe zwischen Programmteilen, hier der > ISR und der Hauptschleife. > > Siehe Interrupt Ehrlich gesagt, das, was hier (Siehe Interrupt ) erläutert wurde, habe ich nicht so richtig kapiert. Vielleicht kann jemand meinen TIMER_A nach diesen Regeln als Beispiel mit den Flags umschreiben. Meine Vorstellungen an dieser Stelle: a) Beibehaltung der 4s für das Einsammeln (und Anzeigen) von Daten und Eintragen der (8) Werte in den Zwischenspeicher. Der Zwischenspeicher soll bei t=512 geleert und der Inhalt auf einen Sektor einer SD-Karte übertragen werden. Damit die SD-Karte ohne Datenverlust herausgenommen werden kann, muss der aktuelle Stand (ausgabe_sektorenrest();) angezeigt werden. (läuft eigentlich nach meinen Wünschen) In Abständen von z.B. 40s soll der Regler (void regler (void) ) aktiviert werden.
wolle g. schrieb: > Joachim B. schrieb: >> ja was ist dein Ziel? >> Darf bei NULL erreichen WEITER decrementiert werden? > > Bin ich hier auf dem Holzweg? > Mit "unsigned int b,k,f,l, reglerstart,t,sollwert;" gibt es m. E. keine > negativen Werte. oder? eben drum wenn ein unsigned int sollwert auf 0 ist, was passiert bei sollwert = sollwert-1? wie groß ist sollwert dann? (und darf das sein?)
:
Bearbeitet durch User
wolle g. schrieb: >> Darf bei NULL erreichen WEITER decrementiert werden? > > Bin ich hier auf dem Holzweg? Sicher. ;-) > Mit "unsigned int b,k,f,l, reglerstart,t,sollwert;" gibt es m. E. keine > negativen Werte. oder? Oder. Was passiert, wenn man von einem unsigned Wert mit 0 etwas subrahiert? a) der Wert bleibt bei Null b) es gibt einen Unterlauf und die Zahl ist plötzlich riesengroß >> Siehe Interrupt > Ehrlich gesagt, das, was hier (Siehe Interrupt ) erläutert wurde, habe > ich nicht so richtig kapiert. Dann lies es noch einmal und denk in Ruhe drüber nach. > Vielleicht kann jemand meinen TIMER_A nach diesen Regeln als Beispiel > mit den Flags umschreiben. > Meine Vorstellungen an dieser Stelle: > a) Beibehaltung der 4s für das Einsammeln (und Anzeigen) von Daten und > Eintragen der (8) Werte in den Zwischenspeicher. Kein Thema. > Der Zwischenspeicher soll bei t=512 geleert und der Inhalt auf einen > Sektor einer SD-Karte übertragen werden. Dito. > Damit die SD-Karte ohne Datenverlust herausgenommen werden kann, muss > der aktuelle Stand (ausgabe_sektorenrest();) angezeigt werden. (läuft > eigentlich nach meinen Wünschen) Vermutlich aber nicht solide, denn du bist ein Laie. > In Abständen von z.B. 40s soll der Regler (void regler (void) ) > aktiviert werden. Etwa so.
1 | volatile uint8_t flag_10ms; |
2 | |
3 | ...
|
4 | uint16_t timer_messen, timer_regler; |
5 | |
6 | while(1) { |
7 | if (flag_10ms) { |
8 | flag_10ms = 0; |
9 | |
10 | timer_messen++; |
11 | if (timer_messen == 400 ) { |
12 | timer_messen = 0; |
13 | // hier Meßwerte auslesen etc.
|
14 | }
|
15 | |
16 | timer_regler++; |
17 | if (timer_regler == 4000 ) { |
18 | timer_regler = 0; |
19 | // hier Regler aufrufen
|
20 | }
|
21 | }
|
22 | }
|
23 | |
24 | // läuft mit 10ms Periodendauer
|
25 | |
26 | Interrupt(TimerA) { |
27 | flag_10ms = 1; |
28 | }
|
Deine anderen Interrupts sind auch eher ungünstig. Sowas macht man mit einem periodischen Aufruf passender Funktion. Damit kann man nämlich auch diese sowieso zeitunkritischen Signale per Software entprellen, siehe Entprellung.
Schau dir das Codebeispiel von Falk genau an. Er setzt im Interrupt nur ein Signal, dass der Interrupt aufgetreten ist. Der Rest passiert in der while(1) der main(). Auf diese Weise wird das Hauptprogramm nur so kurz wie möglich aufgehalten. Das ist wichtig damit bei vielen vorhandenen Interrupts nicht irgendwann Situationen entstehen, in denen dein Programm nur noch im Interrupt steckt. Ob es das tut lässt sich oft schwer abschätzen. Ich war schon sehr oft in der Situation dass ich dachte "Eigentlich kann es nicht am Interrupt liegen", aber genau das tat es. Wenn du wirklich Zeitkritische Operationen ausführen willst wie z. B. Datentransfer, dann kannst du den Code dafür auch direkt im Interrupt ausführen. Aber immer so schlank und wenig wie möglich.
Hannes J. schrieb: > Schau dir das Codebeispiel von Falk genau an. Er setzt im Interrupt nur > ein Signal, dass der Interrupt aufgetreten ist. Der Rest passiert in der > while(1) der main(). Auf diese Weise wird das Hauptprogramm nur so kurz > wie möglich aufgehalten. Der Interrupt ;-)
Joachim B. schrieb: >> Mit "unsigned int b,k,f,l, reglerstart,t,sollwert;" gibt es m. E. keine >> negativen Werte. oder? > > eben drum > > wenn ein unsigned int sollwert auf 0 ist, was passiert bei sollwert = > sollwert-1? Diese Sichtweise habe ich jetzt verstanden. Da aber der Sollwert bei meiner Anwendung niemals unter 320 (20°C) eingestellt wurde, kann dies vermutlich nicht die Absturzursache gewesen sein. Werde trotzdem das Programm entsprechend ändern. Falk B. schrieb: > Etwa so. >volatile uint8_t flag_10ms; >while(1) { > if (flag_10ms) { > flag_10ms = 0; >..... Sind meine Zeilen: while(1) { if (reglerstart==1)regler(); .... } und in TIMER_A die Zeilen: {…. b=b+1; //b wird alle 4s um 1 erhöht if (b >9)reglerstart=1; // hier wird mein 40s-flag gesetzt … } nicht mit den obigen vergleichbar? Jetzt müsste ich nur noch ein 4s-flag für die weiteren Funktionen setzen. Ich möchte bei den 4s-Takt bleiben, damit man den µC evtl. ca. 4s-x schlafen legen kann. (in Zukunft Batteriebetrieb)
Zukünftig könntest du dir mal die millis()-Funktion vom Arduino anschauen und evtl übernehmen. Die benutzt im Endeffekt einen Timer um fortlaufend Millisekunden zu zählen. Denke dabei lernst du auch noch einiges. Wirklich schwer ist sie dabei nicht und besonders gut geeignet wenn du in der Hauptschleife häufig viele unterschiedliche Funktionen in bestimmten zeitlichen Abständen aufrufen willst. Dabei wird nur ein einziger Interrupt benötigt. Das ganze sieht dann in etwa so aus:
1 | unsigned long millisAlt = 0; |
2 | |
3 | ...
|
4 | |
5 | while(1) |
6 | {
|
7 | if(millis()-millisAlt > 4000) |
8 | {
|
9 | millisAlt = millis(); |
10 | // Tue etwas alle 4 Sekunden
|
11 | }
|
12 | }
|
Kann aber auch sein dass das für den Anfang etwas viel ist. Dann stelle es lieber hinten an.
:
Bearbeitet durch User
Hannes J. schrieb: > while(1) > { > if(millis()-millisAlt < 4000) > { > millisAlt = millis(); > // Tue etwas alle 4 Sekunden > } > } Ja, fast. Anders rum wirds ein Schuh. https://forum.arduino.cc/index.php?topic=503368.0 leo
wolle g. schrieb: > Sind meine Zeilen: > while(1) > { > if (reglerstart==1)regler(); > .... > } > und in TIMER_A die Zeilen: > {…. > b=b+1; //b wird alle 4s um 1 erhöht > if (b >9)reglerstart=1; // hier wird mein 40s-flag gesetzt > … > } > nicht mit den obigen vergleichbar? Nein, denn die Masse der Funktionsaufrufe liegt im Interrupt. Und währenddessen sind beim AVR alle anderen Interrupts blockiert. > Jetzt müsste ich nur noch ein 4s-flag für die weiteren Funktionen > setzen. Nein, du mußt die ganzen Funktionsaufrufe aus dem Interrupt entfernen. Ach so, du hast ja gar keinen AVR, sondern einen MSP430. Kann der verschachtelte Interrupts? Egal, das Konzept ist trotzdem ungünstig. > Ich möchte bei den 4s-Takt bleiben, damit man den µC evtl. ca. 4s-x > schlafen legen kann. (in Zukunft Batteriebetrieb) Ja und? Das kann die richtige Methode auch.
Falk B. schrieb: > Man merkt > sofort, daß du BASCOM geschädigt bist ;-) Man merkt sofort, daß Du von Bascom keinen blassen Schimmer hast.
Norbert S. schrieb: > Man merkt sofort, daß Du von Bascom keinen blassen Schimmer hast. Und du von Humor. Naja, als BASCOM-Fanboy bist du entschuldigt.
Moin, Ich bin eher nur gerade empfindlich und angefressen, nachdem ich den ach so tollen C-Code Anderer studiere und Bascom immer so belächelt wird. Da wird auch gepfuscht ohne Ende. Gruß, Norbert
Norbert S. schrieb: > Moin, > > Ich bin eher nur gerade empfindlich und angefressen, nachdem ich den ach > so tollen C-Code Anderer studiere und Bascom immer so belächelt wird. > Da wird auch gepfuscht ohne Ende. Das ist richtig, aber kein Ausgleich oder Rechtfertigung von Schwächen bzw. Begrenzungen von BASCOM. BASCOM hat seine Berechtigung und Nische.
Ich habe versucht, entsprechend den Hinweisen zu den flags, das Programm umzubauen. Leider kein Erfolg. Im Gegenteil: Das umgebaute Programm spinnt noch mehr als das Ursprungsprogramm. Z.B.: nach einer kurzen Betätigung einer Taste für ZU oder AUF läuft der Motor bis zum Anschlag. Danach werden blinkende Nullen angezeigt. Nur ein Zurücksetzen des µC setzt diesem Verhalten ein Ende. Hier kurze Ausschnitte des "neuen" Programms: while(1) { if (flag_reglerstart) { flag_reglerstart=0; b++; if (b>4) {b=0; regler(); } } if (flag_4s) { flag_4s=0; Blitz_gelb(); temp_messung_starten(); //alle angeschlossenen DS18B20 wandlung(); //gehört zu DS18B20 DS18B20_lesen_DS18B20nr16(); regelabweichung_anzeigen(); // in "DS10-g0126-LMK62-SD.h" enthalten esum_anzeigen(); sollwert_anzeigen(); hub_anzeigen(); temp_16_anzeigen(); zwischenspeichern_1(); ausgabe_sektorenrest(); auf_SD_karte_schreiben(); } if (P3IN&BIT7) //P3.7 Taste: Temp.-Sollwert hochzählen { pause1(); if (sollwert>500)sollwert=500; sollwert=sollwert+1; sollwert_anzeigen(); pause1(); } ........... interrupt (TIMERA0_VECTOR) Timer_A(void) { flag_4s=1; flag_reglerstart=1; } Im Anhang das geänderte Programm. Bestimmt habe ich neue Fehler eingebaut.
wolle g. schrieb: > interrupt (TIMERA0_VECTOR) Timer_A(void) > { > flag_4s=1; > flag_reglerstart=1; > } 1. Halte ich es für ziemlich unwahrscheinlich, das der Timer nur alle 4s überlauft. 2. Zwei Flags für ein und den selben Schei..? 3. Nur noch drei Antworten von einem ><(()°> entfernt. 4. Abreißen, 1-2T Pause machen (ein Buch etc. übers Programmieren lesen) und neu beginnen.
wolle g. schrieb: > Ich habe versucht, entsprechend den Hinweisen zu den flags, das Programm > umzubauen. Deine Formatierung ist schlecht. Die Klammerebenen und Einrückungen sind schlecht lesbar und unsinnig. Eher so! Du mußt alle Tabulatoren in Leerzeichen umwandeln, alle besseren Editoren können das auf Knopfdruck.
1 | uint8_t tmp, p3old, p2old; |
2 | |
3 | while(1) { |
4 | if (flag_reglerstart) { |
5 | flag_reglerstart=0; |
6 | b++; |
7 | if (b>4) { |
8 | b=0; |
9 | regler(); |
10 | }
|
11 | }
|
12 | |
13 | if (flag_4s) { |
14 | flag_4s=0; |
15 | Blitz_gelb(); |
16 | temp_messung_starten(); // alle angeschlossenen DS18B20 |
17 | wandlung(); // gehört zu DS18B20 |
18 | DS18B20_lesen_DS18B20nr16(); |
19 | regelabweichung_anzeigen(); // in "DS10-g0126-LMK62-SD.h" enthalten |
20 | esum_anzeigen(); |
21 | sollwert_anzeigen(); |
22 | hub_anzeigen(); |
23 | temp_16_anzeigen(); |
24 | zwischenspeichern_1(); |
25 | ausgabe_sektorenrest(); |
26 | auf_SD_karte_schreiben(); |
27 | }
|
28 | |
29 | // das hier ist falsch!
|
30 | /*
|
31 | if (P3IN&BIT7) { //P3.7 Taste: Temp.-Sollwert hochzählen
|
32 | pause1();
|
33 | if (sollwert>500)sollwert=500;
|
34 | sollwert=sollwert+1;
|
35 | sollwert_anzeigen();
|
36 | pause1();
|
37 | }
|
38 | |
39 | if (P3IN&BIT6) { //P3.6 Taste: Temp.-Sollwert abwärts zählen
|
40 | pause1();
|
41 | if (sollwert<200)sollwert=200;
|
42 | sollwert=sollwert-1;
|
43 | sollwert_anzeigen();
|
44 | pause1();
|
45 | }
|
46 | |
47 | if (P2IN&BIT0) { // P2.0 Taste: Ventil-AUF gedrückt
|
48 | AUF=1;
|
49 | P4OUT &=~BIT0; // LED rot P4.0 EIN
|
50 | P2OUT &=~BIT4; // AUF-fahren
|
51 | } else {
|
52 | AUF=0;
|
53 | P4OUT |=BIT0;
|
54 | P2OUT |=BIT4; //Halt
|
55 | }
|
56 |
|
57 | if (P2IN&BIT1) { // P2.1 Taste: Ventil-ZU wird gedrückt
|
58 | ZU=1;
|
59 | P3OUT &= ~BIT0; // ZU-fahren
|
60 | } else {
|
61 | ZU=0;
|
62 | P4OUT |= BIT1; // LED gelb P4.1 AUS
|
63 | P3OUT |= BIT0; //Halt
|
64 | }
|
65 | |
66 | */
|
67 | |
68 | // eher so mit Flankenerkennung
|
69 | |
70 | if (flag_100ms) { |
71 | flag_100ms = 0; |
72 | |
73 | tmp = P3IN; |
74 | if ((tmp & BIT7) && !(p3old & BIT7) ) { //P3.7 Taste: Temp.-Sollwert hochzählen |
75 | pause1(); |
76 | sollwert=sollwert+1; |
77 | if (sollwert>500) sollwert=500; |
78 | sollwert_anzeigen(); |
79 | pause1(); |
80 | }
|
81 | |
82 | if ((tmp & BIT6) && !(p3old & BIT6) ) { //P3.6 Taste: Temp.-Sollwert abwärts zählen |
83 | pause1(); |
84 | sollwert=sollwert-1; |
85 | if (sollwert<200) sollwert=200; |
86 | sollwert_anzeigen(); |
87 | pause1(); |
88 | }
|
89 | p3old = tmp; |
90 | |
91 | tmp = P2IN; |
92 | if ((tmp & BIT0) & !(p2old & BIT0) ) { // P2.0 Taste: Ventil-AUF gedrückt |
93 | AUF=1; |
94 | P4OUT &=~BIT0; // LED rot P4.0 EIN |
95 | P2OUT &=~BIT4; // AUF-fahren |
96 | } else { |
97 | AUF=0; |
98 | P4OUT |=BIT0; |
99 | P2OUT |=BIT4; //Halt |
100 | }
|
101 | |
102 | if ( (tmp & BIT1) !(p2old & BIT1) ) { // P2.1 Taste: Ventil-ZU wird gedrückt |
103 | ZU=1; |
104 | P3OUT &= ~BIT0; // ZU-fahren |
105 | } else { |
106 | ZU=0; |
107 | P4OUT |= BIT1; // LED gelb P4.1 AUS |
108 | P3OUT |= BIT0; //Halt |
109 | }
|
110 | p2old = tmp; |
111 | }
|
112 | }
|
> Leider kein Erfolg. Im Gegenteil: Das umgebaute Programm spinnt noch > mehr als das Ursprungsprogramm. Was zu erwarten war. Die Hinweise waren richtig, aber kein Wundermittel. Deine Tastenauswertung ist untauglich. Du hattest vorher nur Glück, daß die in einem Pin Change Interrupt versteckt war. Damit reagierten die Codeabschitte immer nur auf einen Flankenwechsel. Jetzt in der Hauptschleife ist sie das nicht mehr und der Fehler wird voll wirksam. Die Hauptschleife wird SEHR SCHNELL immer wider durchlaufen, dementsprechend rasend schnell werden dein Sollwerte hoch und runter gezählt. Da reden wir hier von mehreren Dutzend kHz! Du brauchst eine Auswertung der Flanke in Software. Siehe Artikel Entprellung. Ich hab es mal ansatzweise skizziert. > Z.B.: nach einer kurzen Betätigung einer > Taste für ZU oder AUF läuft der Motor bis zum Anschlag. Danach werden > blinkende Nullen angezeigt. Nur ein Zurücksetzen des µC setzt diesem > Verhalten ein Ende. > Hier kurze Ausschnitte des "neuen" Programms: Was soll das? Der Anhang reicht und der ist vollständig. > Im Anhang das geänderte Programm. > Bestimmt habe ich neue Fehler eingebaut. SICHER! Denn dir fehlt grundlegendes Verständnis.
Teo D. schrieb: > 1. Halte ich es für ziemlich unwahrscheinlich, das der Timer nur alle 4s > überlauft. nur dazu: siehe "void Timer_einstellen(void)" und dann nachrechnen! >(ein Buch etc. übers Programmieren lesen) >und neu beginnen. Toller Beratungshinweis! Darauf muss man erst einmal kommen. Falk B. schrieb: > Die Hauptschleife wird SEHR SCHNELL immer wider durchlaufen, > dementsprechend rasend schnell werden dein Sollwerte hoch und runter > gezählt. Da reden wir hier von mehreren Dutzend kHz! Richtig. Damit man die Sollwertänderungen auf der Anzeige verfolgen kann, wurde "pause1();" eingefügt. ---funktioniert. Mein "Tastenprogramm" fußt auf den Beiträgen im Beitrag "Taster abfragen". Jetzt habe ich das Programm für die Tasten mal nach Deinem Vorschlag umgebaut. Die Spinnerei ist zwar weg, aber nach ein paar Tastenbetätigungen hängt sich das Programm wieder auf. (reagiert nicht mehr auf eine Taste). Schade > SICHER! Denn dir fehlt grundlegendes Verständnis. Und Du meinst, diese Einschätzung hilft mir weiter.
wolle g. schrieb: > Denn dir fehlt grundlegendes Verständnis. > Und Du meinst, diese Einschätzung hilft mir weiter. Könnte sie, wenn Du sie beherzigen und erstmal kleinere Brötchen backen würdest. Du hast nicht nur ein kleines Problem sondern bist mit der Aufgabe ziemlich überfordert. Du frickelst irgendwie herum, um das zum Laufen zu bekommen, verstehst aber gar nicht, was Du da tust. "Hängt sich auf" gibt es nicht! Du schickst den µC irgendwo hin, wo er nicht mehr tut, was Du von ihm willst. Gruß, Norbert
Das hat mit dem Thema wenig zu tun: Norbert S. schrieb: > Könnte sie, wenn Du sie beherzigen und erstmal kleinere Brötchen backen > würdest. Wie groß dürften die kleineren Brötchen sein? >Du hast nicht nur ein kleines Problem sondern bist mit der Aufgabe >ziemlich überfordert. Warum sagst Du das? Wenn jemand sein Problem allein lösen könnte, dann brauchte er hier im Forum nicht zu fragen und man könnte das Forum schließen. Eigentlich wollte ich nicht derartig reagieren. Aber es kommt in letzter Zeit häufiger vor, dass jemand auf ähnliche Art angemacht wird. Obwohl sich hier im Forum viele als Hobby mit Elektronik (auch µC) beschäftigen, kommen sie doch aus den verschiedensten Fachrichtungen.
:
Bearbeitet durch User
wolle g. schrieb: > Die Spinnerei ist zwar weg, aber nach ein paar Tastenbetätigungen hängt > sich das Programm wieder auf Wenn sich das reproduzieren lässt könnte man ja mal mit dem Debugger schauen wo man landet, wenn nicht mehr auf Tasten reagiert wird. Wenn es z.B. ein Hardfault Handler ist dann schauen welche Flags gesetzt sind usw.
Falk B. schrieb: > SICHER! Denn dir fehlt grundlegendes Verständnis. wolle g. schrieb: > Norbert S. schrieb: >> Könnte sie, wenn Du sie beherzigen und erstmal kleinere Brötchen backen >> würdest. > Wie groß dürften die kleineren Brötchen sein? > >>Du hast nicht nur ein kleines Problem sondern bist mit der Aufgabe >>ziemlich überfordert. > Warum sagst Du das? deswgen? Falk B. schrieb: > // das hier ist falsch! > /* > if (P3IN&BIT7) { //P3.7 Taste: Temp.-Sollwert hochzählen > pause1(); > if (sollwert>500)sollwert=500; > sollwert=sollwert+1; > sollwert_anzeigen(); > pause1(); > } das hatten wir doch schon mal besprochen! wenn der sollwert 500 nicht übersteigen soll: if (sollwert>500)sollwert=500; warum inkrementierst du NACH der Abfrage? sollwert=sollwert+1; es hört sich böse an, aber du durchdenkst dein Programm nicht. Ist wie beim Backen, Backzeit 50 Minuten, du schaust auf die Uhr, die 50 Minuten sind um und statt zu stoppen gibst du noch mehr Backzeit dazu.....
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.