Hallo, ich will mit einem ATMega32U4 mit 16MHz-Quarz, Vorteiler 8, eine Frequenzmessung mit dem Timer1 realisieren, bzw. erst einmal eine Periodendauermessung mit der Pseudoeinheit "Timer Ticks". Ich bekomme von einem Drehzahlsensor 48 TTL-Impulse pro Umdrehung. Die Drehzahlmessung soll in einem Bereich von ca. 10 bis 1000 Umdrehungen pro Minute funktionieren, was einer Frequenz von 8 Hz bis 800 Hz entspricht. Ich habe da was programmiert. Beschreibung: Ich verwende die Input Capture-Funktion des Timer1. In dessen ISR setze ich ein Flag, dass ein Impuls gekommen ist (in meinem Fall die fallende Flanke). Außerdem nulle ich hier den TCNT1-Wert. Außerdem wird beim Überlauf von Timer1 eine Variable "ueberlaeufe" inkrementiert. In der Hauptschleife wird folgendes berechnet, wenn das Flag gesetzt ist: timer_ticks = 65536 * (ueberläufe + KORREKTUR_UEBERL) + ICR1 + KORREKTUR_ICR KORREKTUR_UEBERL und KORREKTUR_ICR sind Konstanten, die ich experimentell angepasst habe, dass der Wert stimmt. KORREKTUR_UEBERL ist 1 und KORREKTUR_ICR 4. Während die Berechnung erfolgt, sind die Interrupts gesperrt, um atomaren Variablenzugriff zu garantieren. Das ganze funktioniert, aber das geht bestimmt eleganter. Vielleicht kann ich mir diese Korrigiererei irgendwie sparen. Ich vermute, dass es vorteilhaft ist, einen ICR-Wert zwischenzuspeichern und die Differenz mit dem darauffolgenden ICR-Wert zu berechnen, anstatt jedes mal den TCNT-Wert zu nullen, richtig? Ich habe auch was programmiert, wenn die Anzahl an Überläufen einen bestimmten Wert überschreitet, dass dieser genullt wird. Das greift dann, wenn mein Motor steht, es aber ab und zu Drehzahlimpulse gibt, weil er gerade an der "Grenze" steht und das Drehzahlsignal flattert. Wie könnte ich es lösen, dass nachdem der Motor mal gestanden hat, die erste Berechnung nicht "Müll" liefert? Danke. Third-Eye
Erklär mal genauer, wozu die Korrektur-Konstanten dienen? Was wird da korrigiert? > Ich verwende die Input Capture-Funktion des Timer1. > Außerdem nulle ich hier den TCNT1-Wert. Aua, das kann nicht gut gehen. Denn zwischen dem Interrupt und der Ausführung dieses "nullen" befehl verstreicht eine unbekannte Zeit. Die ist nicht konstant, kann folglich auch nicht durch eine Konstante korrigiert werden. Die Capture Funktion erfasst doch den Zählerstand zum Zeitpuntk des Ereignisses. Den musst du verwenden. Und du darfst den Zähler nicht zurücksetzen, sondern must die Zählerstände von zwei aufeinanderfolgenden Ereignissen voneinander subtrahieren. Wenn der Zähler 16 bit hat und du für die Variablen ebenfalls unint16_t verwendest, dann ergibt die Subtraktion auch nach einem Zähler-Überlauf stets das richtige Ergebnis.
> Wie könnte ich es lösen, dass nachdem der Motor mal gestanden hat, > die erste Berechnung nicht "Müll" liefert? Der erste Interrupt liefert noch kein Meßergebnis. Erst nach zwei Interrupts kannst Du die Differenz der beiden Zählerstände berechnen, und die leifert dann auch keinen Müll. Dabei spielt es keine Rolle, ob der Zähler irgendwann genullt wird (was du nicht tun sollst), oder nicht. Du brauchst bloss eine Variable, die anzeigt, ob nach Start des Motors mindestens zwei Interrupts stattfanden. Das könnte ein Integer sein, der bei jedem Interrupt hochgezählt wird, aber maximal bis auf 2. Motor starten: counter=0; Bei Interrupt: if (counter<2) counter++; previous=current; current=ICR1; In der Auswertung (main-loop): if (counter==2) { diff=current-previous; ... nun die Zeit in Drehzahl umrechnen und anzeigen }
Bei dem begrenzten Wertebereich wird man die Überläufe vom Timer vermutlich nicht wirklich brauchen, zumindest wenn der Vorteiler passend eingestellt ist. Wenn man die Überläufe braucht, muss man etwas aufpassen wenn Überlauf und ICP Ereignis fast gleichzeitig kommen - da kann es passieren das der Überlauf Interrupt zu spät kommt und so in seltenen Fällen einen Falschen Wert liefert. Die Berechnung über die Differenz aus 2 mit ICP gemessenen Zeiten ist der bessere/genauere Weg, um kommt so ohne die Korrekturwerte aus. Die Erkennung ob der Motor gestanden hat, und auch um andere Ausreißer zu reduzieren könnte man machen indem man mehrere Periodendauern misst und dann etwa von 3 oder 5 Messungen den Median nimmt. Die eigentliche Messung für eine Periode geht ja sehr schnell. Ggf. könnte man auch Werte Unterdrücken (kein neuer gültiger Wert) wenn sie zu sehr schwanken.
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.