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
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.
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
P.S. Habe mir http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmieren_mit_Interrupts 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
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
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
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
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.