Forum: Mikrocontroller und Digitale Elektronik ATmega32 zeigt undefiniertes Verhalten


von Benedikt W. (pocky)


Angehängte Dateien:

Lesenswert?

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

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

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
von EMC (Gast)


Lesenswert?

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.

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

> ... hab ich erst mal so nichts wildes gesehen.

Räusper. Äh. Hast Du die ISR gesehen? Wie bewertest Du sie?

von Karl H. (kbuchegg)


Lesenswert?

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
von Karl H. (kbuchegg)


Lesenswert?

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
von Softwareverwickler (Gast)


Lesenswert?

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

von Thomas E. (thomase)


Lesenswert?

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.

von Benedikt W. (pocky)


Lesenswert?

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
Noch kein Account? Hier anmelden.