Forum: Mikrocontroller und Digitale Elektronik Programmablauf / Modellauto Steuerung


von Franki C. (Gast)


Lesenswert?

Hallo Leute!

Habe seit geraumer Zeit ein Projekt mit einem Modellauto das von mir 
über einen Touchscreen und über Funk gesteuert wird.
Nun möchte ich noch die Geschwindigkeit des Fahrzeugs messen.
Dazu hatte ich an einen Hall Sensor gedacht und mir schon kleine Magnete 
besorgt. Um fein zu messen kommen 8 Magneten an die Innenseite eines 
Reifens.
So, nr. 1 : Könnt Ihr irgend einen Hall Sensor empfehlen oder gibt es 
eine Seite die mir da auch weiterhilft?

Nr. 2: Auf dem Modellauto sitzt ein Atmega8 der Daten Empfängt und den 
Wagen steuert. Ich hatte mir den Programmablauf ungefähr so gedacht:

- Daten Empfangen

- Motoren steuern

- Timer starten für 20 ms

- Interrupt für den ICR1 freischalten

-> Die Interruptroutine reagiert bei jeder Highflanke und zählt dort 
über      eine Variable wie oft eine Highflanke innerhalb dieser 20 ms 
kommt.

-> Nach 20 ms kommt der Interrupt vom Timer und sperrt den Interrupt von 
ICR1

- Die Daten werden dann ausgewertet und versendet


Ist das so ok? Ich bin mir über den Ablauf nicht ganz sicher.
Könnte man doch bloß Threads programmieren, das würde mir viel 
erleichtern!

von Karl H. (kbuchegg)


Lesenswert?

Franki C. schrieb:

> Ist das so ok?

Du denkst zu seriell

> Ich bin mir über den Ablauf nicht ganz sicher.
> Könnte man doch bloß Threads programmieren, das würde mir viel
> erleichtern!

Du kannst Threads programmieren auch wenn sie nicht Threads heissen.
Deine 'Threadsteuerung' heißt: Timer!

zb die Drehzahl messen. Du kannst zb den Input Capture Eingang des 
Timers1 benutzen. Bei jeder Flanke an diesem Eingang speichert der Timer 
seinen aktuellen Zählerstand weg und du kannst auch einen Interrupt 
aufrufen lassen. Durch Vergleich mit dem Zählerstand vom letzten Capture 
Event (einfach voneinander abziehen) hast du ein Mass für die Zeit 
zwischen den beiden Pulsen und damit auch für die Frequenz und damit 
über die Drehzahl des Rades und damit über die Geschwindigkeit.

D.h. Drehzahlmessung eines Rades geschieht nebenher. Das macht ein Timer 
mit einer zusätzlichen Interrupt Service Routine eigenständig.

Timer sind deine Threadsteuerung! Nutze sie.


Du musst weg vom seriellen Denken, hin zu ereignisgesteuertem 
Programmieren. Nicht länger: Ich mach das, dann das, dann wird gewartet 
und dann passiert noch das.

Hin zu:
In der Hauptschleife werden regelmässig alle möglichen Ereignisse 
abgeklappert und nachgesehen ob sie eingetreten sind. Wenn ja, werden 
sie (mit kurzem Code!) bearbeitet. Ereignisse können alles mögliche 
sein, zb auch selbst generierte, die einfach nur eine Variable auf 1 
setzen und in der Hauptschleife wird abgefragt, ob diese Variable auf 1 
steht und wenn ja die entsprechende Aktion ausgeführt.

Ein 'Thread' der zb eine LED regelmässig blinken lässt führt wieder über 
einen Timer. (Wann immer es etwas mit Zeitsteuerung zu tun gibt, musst 
du sofort Timer denken, und nicht delay)

Der Timer wird so aufgesetzt, dass er ein regelmässiges Signal in Form 
eines Interrupt aufrufs generiert. ZB alle 1 Millisekunde wird die ISR 
aufgerufen.
Dann zählst du in der ISR eine Variable hoch und wenn diese 1000 
erreicht hat (oder von 1000 auf 0 runtergezählt hat), dann setzt du eine 
Variable (das Jobflag) auf 1.
In der Hauptschleife wird natürlich unter anderem geprüft, ob das Flag 
auf 1 steht und wenn ja wird die LED umgeschaltet und das Flag wieder 
zurückgesetzt.

Gewartet wird nicht mehr. Auf nichts und niemand. Ausser vielleicht wenn 
es sich um eine Wartezeit im µs Bereich handelt. Aber ansonsten wird 
nicht gewartet. Stattdessen wird in der Hauptschleife weitergemacht und 
reihum alle anderen möglichen Ereignisse geprüft. Solange bis dann das 
Ereignis 'Zeit abgelaufen' eingetreten ist.

Auch Zustandsmaschinen kann man hier nutzbringend einsetzen. Sie passen 
wunderbar in das Konzept der ereignisgesteuerten Programmierung. Ein 
Zustandswechsel ist nichts anderes als eine Reaktion auf ein Ereignis. 
Was auch immer das Ereignis sein möge.


Und ja: In den meisten Programmen stellt man einen Timer explizit dafür 
ab einen Basiszeittakt in Form eines ISR Aufrufs zu generieren. Das 
können 1 Millisekunden Intervalle sein oder auch mehr, je nachdem welche 
kleinste Zeiteinheit sinnvoll ist. Davon kann man dann immer längere 
Zeiteinheiten ableiten. Denn 100 mal 1 Millisekunde abgezählt, ergibt 
auch einen Zeitraum von 100 Millisekunden. In diesem Zusammenhang sind 
auch oft rückwärts zählende Variablen brauchbar einzusetzen, die als 
eine Art Stoppuhr fungieren. Die Variable wird in der ISR regelmässig 
runtergezählt. Ist sie ungleich 0, dann läuft die Zeit noch. Ist die 
Variable zu 0 geworden, so ist die zuvor eingestellte (durch Zuweisung) 
Zeit abgelaufen --- wieder ein Ereignis, auf das man reagieren kann.

Und natürlich kannst du im Grunde auch das Abzählen der Impulse vom 
Hallsensor in so ein Schema, so wie du dir das ursprünglich gedacht hast 
einbauen ... wenn dir die Timer ausgehen. Einfacher ist es mit nur einem 
Timer, möglich ist es auch so wie du das angedacht hast.
Aber was du auch immer tust: Sieh zu, dass du mindestens 1 Timer für 
eine allgemeine Zeitbasis freihältst.

von Franki C. (Gast)


Lesenswert?

Hallo und vielen Dank für die Hilfe!
Ich finde es echt super das man sich hier so viel Mühe gibt den Leuten 
zu helfen.

Ich werde das mit dem Timer mal ausprobieren, muss mal schauen wie ich 
das anstelle, habe nämlich den 16bit Timer für den Servo bei 20 ms 
laufen und den 8 bit Timer für den DC Motor. Nun muss ich mal gucken wie 
ich die 20ms vom 16 bit Timer ausnutze..

von Karl H. (kbuchegg)


Lesenswert?

Franki C. schrieb:

> Ich werde das mit dem Timer mal ausprobieren, muss mal schauen wie ich
> das anstelle, habe nämlich den 16bit Timer für den Servo bei 20 ms
> laufen

Brauchst du nicht.
Also: den Timer brauchst du schon. Aber du brauchst ihn nicht auf 20ms 
einstellen. Mit einem durchlaufenden Timer kann man wunderbar locker 10 
oder mehr Servos ansteuern, ohne dass man den Timer in seiner 
Bewegungsfreiheit in irgendeiner Form einschränken muss.

> und den 8 bit Timer für den DC Motor.

PWM?

> Nun muss ich mal gucken wie
> ich die 20ms vom 16 bit Timer ausnutze..

von Franki C. (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe das Programm zum testen wie im Anhang geschrieben.

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.