Hallo liebe Leute, ich habe vor kurzem mit einem Kumpel eine Torsteuerung für eine Werkstatt gebaut. Daher wir ziemlich µC-Begeistert sind wollten wir das auch mit einem atmega realisieren. An sich auch keine große Sache: - 3 Knöpfe (Hoch, Stop, Runter) - 2 Sensoren (Oben: Nährungssensor, Unten: Endschalter) - 1 LCD-Display (2x8 Zeichen) (- 1 Sicherheitsleiste, diese ist aber noch nicht angeschlossen) Jetzt funktioniert unser Programm wunderbar, bis auf die Tatsache das nach einer scheinbar zufälligen Zeit die Steuerung total durchdreht. - Ab und zu geht gar nichts mehr, das LCD zeigt wirres Zeug, und es reagiert nicht mehr auf Tastendrücke - Manchmal wenn das Tor in eine Endstellung kommt fährt es sofort an in die andere Richtung zu fahren. Der Sourcecode ist im Anhang. Ich kann mir das verhalten beim besten Willen nicht erklären. Ich programmiere häufig in C, kenne mich also ein wenig aus. Bei µC fehlt es mir allerdings doch noch einiges an Erfahrung. Den Code wollte ich auch noch besser aufräumen, aber zu Zwecken der Fehlersuche habe ich genau das Orginal angehängt welches gerade auf dem Atmega ist. Entprellt wird per Software. Der LCD-Treiber stammt von hier: https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung und wurde leicht modifiziert. Sollte aber keinesfalls seltsames Verhalten hervorrufen. Einen Plan für die gesamte Schaltung habe ich leider nicht. Vielleicht findet sich aber ja schon im Code ein schwerwiegender Fehler, oder jemand hatte bereits ein ähnliches Problem und kann eine Lösung vorschlagen. Ich bedanke mich schonmal für die mühen sich durch den Code zu Quälen. mfg Benedikt
Hm... Leider sehe ich schon in der ersten Datei ein ganz übles NOGO.
1 | void slide(char *s, int step) |
2 | {
|
3 | lcd_clear(); |
4 | step %= strlen(s); //irgendwann auch mal von vorne anfangen |
5 | lcd_setcursor(0, 1); |
6 | unsigned int i = 0; |
7 | |
8 | for(i = 0; i < 8; i++) |
9 | {
|
10 | {
|
11 | lcd_data(s[(i + step) % strlen(s)]); //Schriftzug als Lauftext anzeigen |
12 | }
|
13 | |
14 | }
|
15 | |
16 | //Debuginfos auf dem Display anzeigen
|
17 | lcd_setcursor(1, 2); |
18 | lcd_data('0' + SI_pin(IN, TASTE_AUF)); |
19 | lcd_data('0' + SI_pin(IN, TASTE_STOP)); |
20 | lcd_data('0' + SI_pin(IN, TASTE_ZU)); |
21 | lcd_data(' '); |
22 | lcd_data('0' + SI_pin(IN, SCHALTER_OBEN)); |
23 | lcd_data('0' + SI_pin(IN, SCHALTER_UNTEN)); |
24 | }
|
25 | |
26 | ISR (TIMER0_OVF_vect) |
27 | {
|
28 | millisecs += 10; |
29 | TCNT0 = PRELOAD; |
30 | |
31 | //Muss periodisch aufgeführt werden um Eingänge zu entprellen
|
32 | SI_check_input(); |
33 | |
34 | if(!(millisecs % 500)) //ab und zu mal das Display aktualisieren. Kleinerer wert bedeutet schnellerer Lauftext. Zu schnell wird unleserlich wegen der Trägheit des lcd-displays! |
35 | {
|
36 | if(slider) |
37 | {
|
38 | slider_step++; |
39 | slide(slider_text, slider_step); |
40 | }
|
41 | else
|
42 | {
|
43 | slider_step = 0; |
44 | }
|
45 | }
|
46 | }
|
Es darf keine komplexen Funktionsaufrufe in Interrupt-Routinen geben. Dieser doppelt gemoppelte Block in der For-Schleife ist überflüssig. Was den Stil betrifft, könnte man das erstmal ignorieren. Aber die LCD-Ausgaben im Interrupt müssen vom Verständnis her erstmal geklärt werden, denke ich. Deine Fehlerbeschreibung aber suggeriert, dass die Stromversorgung auch ein Problem haben könnte. Ein Stromlaufplan und eine Foto vom Aufbau sind also leider doch notwendig.
:
Bearbeitet durch User
Benedikt W. schrieb: > Jetzt funktioniert unser Programm wunderbar, bis auf die Tatsache das > nach einer scheinbar zufälligen Zeit die Steuerung total durchdreht. > - Ab und zu geht gar nichts mehr, das LCD zeigt wirres Zeug, und es > reagiert nicht mehr auf Tastendrücke > - Manchmal wenn das Tor in eine Endstellung kommt fährt es sofort an in > die andere Richtung zu fahren. Das liest sich, als ob die Schaltung störanfällig ist. Habt irgendwas gegen Spannungsspitzen und so getan? Der echte Schaltplan wäre wichtig.
Zu:
> ... die LCD-Ausgaben im Interrupt müssen vom Verständnis her erstmal geklärt
werden, ...
Ich habe das jetzt nicht durchgerechnet. Bin ehrlich gesagt zu faul dazu
und es ist lästig, weil einfach niemand ernsthaft komplexe
Funktionsaufrufe in Interrupt-Routinen schreibt.
Grundsätzlich ist es so, das man davon ausgeht, das Interrupt-Routinen
so kurz wie irgend möglich sind. Falls komplexere Aktionen
erforderlich sind, so erledigt man die in der Hauptschleife aufgrund
eines Flags, das in der ISR gesetzt wird. Das verhindert jegliches
Problem mit evtl. zu lange dauernden Interrupt-Routinen. Die Frage, ob
die Verarbeitung der komplexen Aktivität aufgrund des gesetzten Flags
kurz genug ist muss dann zwar dennoch beobachtet werden, aber auf jeden
Fall sind schonmal "seltsame" Fehler ausgeschlossen.
Der Code ist zwar verbesserungswürdig, aber beim Drüberlesen hab ich erst mal so nichts wildes gesehen. Konzentrieren wir uns mal auf die Hardware: Stromversorung Abblockkondensatoren Wie sind die Motoren angebunden
> ... hab ich erst mal so nichts wildes gesehen.
Räusper. Äh. Hast Du die ISR gesehen? Wie bewertest Du sie?
Hab ich gesehen. Sein Code ist nicht zeitkritisch. Es ist zwar nicht in Ordnung (ich hab ja auch gesagt, dass er verbesserungswürdig ist), aber das ist nicht die Ursache für das erratische Verhalten. Im Code gibt es noch jede Menge mehr zu bekritteln. Angefangen bei der naiven unkritischen Verwendung von int an allen Ecken und Enden bis hin dazu dass seine Entprellung keine ist. Aber das ist alles nicht die Ursache für das momentane Problem.
:
Bearbeitet durch User
Aber was anderes sehe ich noch: Im Programm sind an den Eingängen keine Pullups aktiviert. Daher kommt noch die Zusatzfrage: Wie sind die Taster bzw. die Endschalter angeschlossen?
:
Bearbeitet durch User
Vorweg: Mit dem ATmega kenn ich mich nicht aus. Wenn ich das richtig verstehe, wird die Timer ISR alle 10ms ausgelöst. Wenn alle 500 ms der lauftext aktualisiert wird, wird lcd_clear() aufgerufen:
1 | void lcd_clear( void ) |
2 | { |
3 | lcd_command( LCD_CLEAR_DISPLAY ); |
4 | _delay_ms( LCD_CLEAR_DISPLAY_MS ); |
5 | } |
wobei
1 | #define LCD_CLEAR_DISPLAY_MS 10 |
Kann es sein, dass die ISR hier gleich wieder unterbricht? Was passiert auf dem ATmega dabei mit dem stack? Schöne Grüße Stephan
Softwareverwickler schrieb: > Kann es sein, dass die ISR hier gleich wieder unterbricht? Was passiert > auf dem ATmega dabei mit dem stack? Das ist kein Problem. Während eine ISR läuft sind die Interrpts global abgeschaltet. Die nächsten IRQs müssen dann warten. mfg.
Okay, danke erstmal für die nützlichen Tipps. Auf den Plan muss ich selber noch ein wenig warten, den schieb ich sobald ich ihn hab hinterher, jetzt schreib ich erstmal das Programm so um, das die ISR keine Funktionen mehr aufruft und mach das ganze Programm etwas schöner. Karl Heinz schrieb: > ... > bis hin > dazu dass seine Entprellung keine ist. Bitte eine genauere Erklärung. Ich bin eigentlich schon der Meinung, dass das mehr oder entprellt. Funktioniert auf jedenfall wunderbar.
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.