Forum: Mikrocontroller und Digitale Elektronik STM32 Welcher Timer ?


von rowtag (Gast)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

PS: Wie lange soll der Timer maximal laufen, und was für eine zeitliche 
Auflösung brauchst du?

von rowtag (Gast)


Lesenswert?

Ich will die Zeit messen, wie lange der Gegenstand vor dem Sensor ist.

von rowtag (Gast)


Lesenswert?

brauche eine Auflösung in Millisekunden, vielleicht sogar kleiner

von Dr. Sommer (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

Eine simple Möglichkeit wäre, denn Systemtimer auf 1kHz zu stellen und 
bei den beiden Ereignissen die Systemzeit in Variablen zu kopieren.

von rowtag (Gast)


Lesenswert?

Controller und Sensor kommunizieren über I2C.
Zeitspanne ist maximal ein paar Sekunden. +
Es ist ein STM32L476RG.

von Dr. Sommer (Gast)


Lesenswert?

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.

von rowtag (Gast)


Lesenswert?

Wie kann ich den Timer manuell starten/stoppen? Ich blicke bei den 
ganzen Funktionen nicht durch.

von Dr. Sommer (Gast)


Lesenswert?

rowtag schrieb:
> Wie kann ich den Timer manuell starten/stoppen?

Durch Setzen/Löschen des CEN Bits im CR1 Register.

von Stefan F. (Gast)


Lesenswert?

> 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.

von Dr. Sommer (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

Ja Dr. Sommer, da stimme ich Dir absolut zu. Deswegen habe ich davon 
abgeraten, den Systemtimer auf weniger als 0,5ms Intervall zu stellen.

von Bastler (Gast)


Lesenswert?

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.

von Bastler (Gast)


Lesenswert?

Oder du arbeitest als Empfänger nicht mit einer Photodiode sondern mit 
einem Array, dann kann man über Triangulation messen.

von rowtag (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

Na dann hast du ja jetzt zwei brauchbare Lösungsansätze. Kommst du damit 
weiter?

von rowtag (Gast)


Lesenswert?

Noch nicht wirklich.
Ich wollte es jetzt mit einem General Purpose Timer nehmen. Ich hab aber 
noch nie mit irgendwelchen Registern gearbeitet...

von rowtag (Gast)


Lesenswert?

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?

von Dr. Sommer (Gast)


Lesenswert?

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 .

von Einer K. (Gast)


Lesenswert?

rowtag schrieb:
> Ich hab aber
> noch nie mit irgendwelchen Registern gearbeitet...

Leitsatz:
> Wir lernen, indem wir es tun!

von Stefan F. (Gast)


Lesenswert?

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.

von Ductus cochlearis (Gast)


Lesenswert?


von Stefan F. (Gast)


Lesenswert?

Der Link funktioniert nicht

von rowtag (Gast)


Lesenswert?

[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.

von Ductus cochlearis (Gast) (Gast)


Lesenswert?


von rowtag (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.