Hallo, ich möchte eine Art Lichtschranke mit einem STM32-Nucleo und einem Entfernungsmesser bauen. Wenn die Entfernung kleiner wird, also etwas die Lichtschranke durchfährt, soll ein Timer starten, und wenn die Entfernung wieder normal ist soll der Timer stoppen. ich weiß nur nicht was für eine Art von Timer da richtig ist.
Brauchst du den Timer jetzt um die Entfernung aus der Lichtschranke auszuwerten oder für was anderes? Wie kommt das Signal der Lichtschranke auf den Controller? Soll der Timer auch was anderes können als Starten/Stoppen? Vielleicht die Zeit messen? Nach Ablauf einer Zeit was tun? Wenn du wie beschrieben nur Starten&Stoppen willst nutze einfach gar keinen Timer und stell dir vor als würde da ein Timer laufen.
PS: Wie lange soll der Timer maximal laufen, und was für eine zeitliche Auflösung brauchst du?
Und Dr. Sommer schrieb: > Wie kommt das Signal der Lichtschranke > auf den Controller? Dr. Sommer schrieb: > Wie lange soll der Timer maximal laufen? Welcher STM32 ist es genau? Da gibt es einige Unterschiede.
Eine simple Möglichkeit wäre, denn Systemtimer auf 1kHz zu stellen und bei den beiden Ereignissen die Systemzeit in Variablen zu kopieren.
Controller und Sensor kommunizieren über I2C. Zeitspanne ist maximal ein paar Sekunden. + Es ist ein STM32L476RG.
Dann nimm einen der General Purpose 16bit Timer, stelle den Prescaler so ein dass der Timer mit 10kHz läuft, und starte/stoppe den Timer manuell über das CEN Bit. So kommst du auf eine 100us Auflösung und Max 6,5 Sekunden. Am Besten das Update Event abfangen um Überläufe zu erkennen.
Wie kann ich den Timer manuell starten/stoppen? Ich blicke bei den ganzen Funktionen nicht durch.
rowtag schrieb: > Wie kann ich den Timer manuell starten/stoppen? Durch Setzen/Löschen des CEN Bits im CR1 Register.
> Controller und Sensor kommunizieren über I2C. Heisst das, dass der Mikrocontroller den Sensor regelmäßig pollen muss? Falls du damit wirklich Abweichungen unter 1ms erreichen willst, wird das knapp. > Wie kann ich den Timer manuell starten/stoppen? Falls sich die Frage auf den Systemtimer bezieht: Ich weiß nicht ob man ihn stoppen kann, aber das sollte man auf jeden Fall tunlichst unterlassen. Du hältst ja auch nicht die Wanduhr an, wenn du ein Ei kochen willst. Die Idee des Systemtimer ist, dass da eine Variable fortlaufend regelmäßig hochgezählt wird. Typischerweise ein 32bit Integer im 1ms Intervall. Das hat auch jeder PC und jedes Smartphone so. Bei ARM kann man auch andere Intervalle festlegen, zum Beispiel 0.5ms. Aber übertreibe es nicht, denn sonst ist der µC übermäßig mit Interrupts beschäftigt. Falls du weniger als 0,5ms brauchst, würde ich doch einen anderen Timer verwenden. Bedenke, dass der Timer genug Bits haben muss. Ein 32bit Timer im 1ms Intervall kann fast 50 Tage erfassen. Ein 16bit Timer im 0,1ms Intervall kann aber nur 6,5 Sekunden erfassen. Reicht das für deine Anwendung? Wenn du es mit dem Systemtimer machst, dann ungefähr so:
1 | int warte_auf_start=1; |
2 | uint32_t start_zeitpunkt; |
3 | uint32_t ende_zeitpunkt; |
4 | uint32_t zeitspanne; |
5 | |
6 | while (1) // endlos-schleife |
7 | {
|
8 | if (warte_auf_start && messe_entfernung() < 100) // Beginn der Messung |
9 | {
|
10 | warte_auf_start=0; |
11 | start_zeitpunkt=systick_count; // oder wie auch immer dein systemtimer heisst |
12 | }
|
13 | if (!warte_auf_start && messe_entfernung() > 120) // Ende der Messung |
14 | {
|
15 | warte_auf_start=1; |
16 | ende_zeitpunkt=systick_count; |
17 | zeitspanne=ende_zeitpunkt-start_zeitpunkt; |
18 | }
|
19 | }
|
Die selbe Methode kannst (nicht musst) du auch mit einem schnelleren Hardware-Timer anwenden. Den lässt du einfach frei durchlaufen (nicht starten und stoppen). Auch damit kannst du die beiden Zeitpunkte (start/ende) erfassen und deren Differenz berechnen. Wichtig ist dabei, dass die verwendeten Variablen (start_zeitpunkt und ende_zeitpunkt) den selben Typ haben, wie der Zähler. Denn dann darf der Timer zwischendurch sogar einmal (nicht öfter) überlaufen, und das Ergebnis bleibt dennoch richtig. Den Timer durchlaufen zu lassen hat den Vorteil, dass du ihn gleichzeitig auch für andere Messungen verwenden kannst. Zum Beispiel, wenn du mehrere solcher Sensoren mit einem einzigen µC verwenden willst.
Stefanus F. schrieb: > Die Idee des Systemtimer ist, dass da eine Variable fortlaufend > regelmäßig hochgezählt wird. Der Vorteil eines Hardware Timers ist, dass keine ständigen Interrupts nötig sind, welche zudem mit etwas Pech nicht zur richtigen Zeit abgearbeitet werden. Beim Hardware Timer fragt man einfach zum fraglichen Zeitpunkt den Zähler ab und hat direkt den exakten Wert.
Ja Dr. Sommer, da stimme ich Dir absolut zu. Deswegen habe ich davon abgeraten, den Systemtimer auf weniger als 0,5ms Intervall zu stellen.
Bei einer Lichtschranke muss man doch nur erkennen ob das Signal da ist oder weg. Was du meinst ist ein Lichtlaufzeitsensor. Das ist nicht so einfach. Überleg dir mal wie lange das Licht benötigt um einen Meter zurückzulegen.
Oder du arbeitest als Empfänger nicht mit einer Photodiode sondern mit einem Array, dann kann man über Triangulation messen.
Meine "Lichtschranke" ist ein vl53l0x Entfernungsmesser, der ständig die Entfernung zum Boden misst und an den µC sendet. Wenn der Abstand kleiner wird als die Normalhöhe, soll der Timer gestartet werden. Wenn der Abstand dann wieder normal ist soll der Timer stoppen. Danach soll aus der Zeit (und der bekannten Länge des Gegenstandes) die Geschwindigkeit berechnet werden.
Na dann hast du ja jetzt zwei brauchbare Lösungsansätze. Kommst du damit weiter?
Noch nicht wirklich. Ich wollte es jetzt mit einem General Purpose Timer nehmen. Ich hab aber noch nie mit irgendwelchen Registern gearbeitet...
Kennt sich zufällig jemand mit den HAL Bibliotheken aus und kann mir sagen ob es da auch irgendwelche Funktionen gibt um Timer zu sarten/stoppen?
rowtag schrieb: > kann mir > sagen ob es da auch irgendwelche Funktionen gibt um Timer zu > sarten/stoppen? Ja gibt es. Sonst wäre die ja komplett nutzlos. Versuch's mal mit HAL_TIM_Base_Start und HAL_TIM_Base_Stop. Vorher natürlich mit HAL_TIM_Base_Init initialisieren. Takt Einschalten (__HAL_RCC_TIM?_CLK_ENABLE) nicht vergessen. Timerstand abfragen mit __HAL_TIM_GET_COUNTER .
rowtag schrieb: > Ich hab aber > noch nie mit irgendwelchen Registern gearbeitet... Leitsatz: > Wir lernen, indem wir es tun!
Ich würde Dir raten, das Referenzhandbuch des µC zu lesen, sowie meine Notizen: http://stefanfrings.de/stm32/index.html Vergiss die HAL, die macht es nicht wirklich einfacher.
Das Timer-Kochbuch ist hier die sinnvolle Quelle: http://www.st.com/content/ccc/resource/technical/document/application_note/group0/91/01/84/3f/7c/67/41/3f/DM00236305/files/DM00236305.pdf
[c] while (1) { HAL_TIM_Base_Start(&htim6); //TIM6->CR1 |= TIM_CR1_CEN; HAL_Delay(200); HAL_TIM_Base_Stop(&htim6); time=__HAL_TIM_GET_COUNTER(&htim6); test=time; } [\c] ich hab es jetzt so weit. Jetzt weiß ich nur nicht wie man den Timer zurücksetzt.
1 | |
2 | while (1) |
3 | {
|
4 | HAL_TIM_Base_Start(&htim6); |
5 | //TIM6->CR1 |= TIM_CR1_CEN;
|
6 | start=__HAL_TIM_GET_COUNTER(&htim6); |
7 | HAL_Delay(200); |
8 | |
9 | HAL_TIM_Base_Stop(&htim6); |
10 | |
11 | stop=__HAL_TIM_GET_COUNTER(&htim6); |
12 | time=stop-start; |
13 | TIM6->SR = 0; |
14 | }
|
jetzt hab ich es so gelöst. Für Time kommt aber immer 55772 raus. Also gehe ich mal davon aus der Timer ist nicht richtig eingestellt. Wie berechne ich den Prescaler richtig. Der µC ha einen Takt von 80Mhz.
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.