mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zustandsautomat "verschluckt Zustände"/läuft nicht


Autor: Hans Maier (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe vor kurzem mit AVRs angefangen und würde nun gerne eine
Fernsteuerung für ein (Gargagen-)Tor bauen. Die Hardware habe ich
soweit fertig und die läuft meiner Meinung nach auch. Die vorhandene
Handsteuerung habe ich "entdrahtet", die Leitungen zum Motor dann auf
Schütze/Relais gelegt und die ursprünglichen Taster der Handsteuerung
auf Eingänge des uC (AVR ATMega8). Außerdem habe ich noch eine alte
1-Kanal Fernbedienung angeschlossen. Was ich nun wollte, war ein
Zustandsautomat in den uC zu laden. Wenn jemand eine Taste (auf, stop,
zu) drückt hat das Vorrang vor allem anderen. Wenn sich der Zustand
(schaltet bei jedem druck zwischen high und low um) des
Fernbedienungsempfänger ändert, soll das Tor auf -> stop -> zu -> stop
-> auf... gehen. Das Tor hat elektromechanische Endschalter und stoppt
von alleine, es genügt also einfach ein Schütz/Relais für eine gewisse
Zeit anziehen zu lassen.
Irgendwie hängt sich das ganze jedoch oft komplett auf: teilweise
werden Zustände verschluckt bzw. gar nicht durchlaufen. Schlimmer noch:
es passiert sogar, dass der uC in einem Zustand "hängt" und noch nicht
einmal auf einen Tastendruck reagiert!
könnte sich evtl. mal jemand den angehängten Code ansehen (habe mich
bemüht überall Kommentare einzufügen) und mir Tipps geben wo es hängt?
Ach ja, programmiere in C und habe mir erst einmal die 45-Tage
Testversion von Imagecraft installiert.

Schönes Wochenende und weiterhin viele Tore :=)

Hans

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh jee... Dein Code ist voll mit Race-Condtitions.

Als erstes must Du alle Variablen, die von einem Interrupt und dem
Hauptprogramm verändert werden, als "volatile" deklarieren. Also:

  volatile int count = 0;
  volatile unsigned char zustand = 1;
  volatile unsigned char alterfunkzustand = 1;

Dann hast Du im Hauptprogramm noch oft Konstruktionen wie:

  if ( zustand == xyz )
  {
    // mach was
  }
  else if (zustand == abc)
  {
    // mach was anderes
  }

Überlegt Dir mal, was passiert wenn der Timer-Interrupt auftritt und
genau zwischen die beiden if-Anweisung fällt. Dann kann (je nach Code)
Deine State-Maschine nämlich kräftig aus dem Tritt kommen.

Du musst cli() und sei() benutzen um Interrupts an der entsprechende
Stelle zu sperren um saubere State-Maschine-Übergänge zu erhalten.

Ich habe Deinen Code nur oberflächlich angeschaut. Ob weitere Fehler
drinn sind, keine Ahnung, aber ich vermute es.

Autor: Hans Maier (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke für die Rückmeldung. Deine Einwände leuchten mir soweit ein.
Wenn ich die Interrupts im main komplett vor der Abfrage der Tasten
sperre und erst am Ende des main wieder freigebe, würde das gehen? Also
merkt sich der uC wenn ein Interrupt aufgetreten ist und arbeitet ihn
halt nur ab wenn sie freigegeben sind? Es würde ja schon genügen, wenn
in meinem Programm nur an einer einzigen Stelle im main mal die
Interrupts abgefragt würden, denn der Mensch drückt wohl länger als ein
Durchlauf des mains auf eine Taste.
Ansonsten: wie baut man einen Zustandsautomaten der auch zeitgesteuert
den Zustand wechselt "richtig" auf?

Hans

Autor: Hans Maier (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P.S. Habe mir
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...
durchgelsen und verstehe jetzt die Problematik. Bei einem "einfachem"
Zustandautomaten wäre mir die Lösung soweit auch klar, nur nicht wenn
das ganze auch zeitgesteuert laufen soll.

Hans

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuche mal, das Ganze als switch() Anweisung umzuschreiben, die ist
eigentlich genau für Zustandsautomaten gedacht.

Dann wird alles viel übersichtlicher.

Und den default-Zweig nicht vergessen !

Nicht davon ausgehen, daß bestimmte Zustände nie auftreten können.


Peter

Autor: Hans Maier (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

anbei die nächste Version mit switch Konstrukten und abschalten der
Interrupts während der Abarbeitung. Werde das ganze nachher mal
ausprobieren. Muss jetzt erst im Garten helfen :=(

Auf jeden Fall: Danke!

Hans

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

>Du musst cli() und sei() benutzen um Interrupts an der entsprechende
>Stelle zu sperren um saubere State-Maschine-Übergänge zu erhalten.

Es ist nicht zwingend notwendig, wenn man weiss wann seine Interrupts
ausgeloest werden.

Bei mir bekommt die State Maschine einen eigenen Takt der per Interrupt
erzeugt wird. Der gleiche Timer wird auch dafuer benutzt weitere
Taktquellen fuer andere Routinen zuerzeugen.

Gruß,
Dirk

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.