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.