Hallo, würde gerne mit einem ATmega32 Drehzahlen im Bereich von 100 - 10000 U/min mit einer Auflösung von 1 U/min bestimmen. Ich bekomme nur einen Puls pro Umdrehung. Weiß nicht genau wie ich dies anstellen soll, bzw. ob es überhaupt möglich ist. Wenn ich die Pulse pro Zeit messen, muss die Messzeit ja ziemlich groß sein, um die Auflösung hinzubekommen. 60 Sekunden, oder liege ich da falsch. Gibt es einen sinnvolle Möglichkeit diese Aufgabe zu lösen? Gruß Mike
die zeit differenz zwischen zwei impulse sollte ausreichen um die aktuelle geschwindigkeit zu bestimmen.
Die Auflösung in kombination mit dem Wertebereich bereite mir gerade etwas Schwierigkeiten.
Mike schrieb: > Die Auflösung in kombination mit dem Wertebereich bereite mir gerade > etwas Schwierigkeiten. Inwiefern? Bei 10000 U/Min hast du rund 166.66 Umdrehungen in 1 Sekunde. Das heist du kriegst 166 Pulse von deiner Markierung in 1 Sekunde. Oder aber anders ausgedrückt: Von einem Puls zum nächsten vergehen 0.006 Sekunden, oder 6 Millisekunden. Eine halbe Ewigkeit für einen µC. Mittels Input Capture kannst du die Zeit zwischen 2 Pulsen noch viel genauer bestimmen. Durchsuch mal das Forum nach Frequenzmessung. Das ist im Grunde genau das gleiche, nur das das Ergebnis in Hz und nicht in U/Min angegeben wird. Im Grunde ist das aber völlig identisch, denn um bei deinem Beispiel zu bleiben: Bei 10000 U/Min tauchen deine Messpulse mit einer Frequenz von 166.6 Hz auf :-)
mhhh ... also ich habe es mit einem 16-bit-Timer umgesetzt. Ermittel damit den Couterwert zwischen 2 Pulsen ( neuer Wert - alter Wert). Nur ist ja die Auflösung nun anhängig von der Drehzahl. Die Forderung nach einer Auflösung von 1 U/min krieg ich irgendwie bei den niedrigen Drehzahlen ich hin.
Mike schrieb: > mhhh ... also ich habe es mit einem 16-bit-Timer umgesetzt. Schön. > Ermittel > damit den Couterwert zwischen 2 Pulsen ( neuer Wert - alter Wert). Auch super > Nur > ist ja die Auflösung nun anhängig von der Drehzahl. Logisch > Die Forderung nach > einer Auflösung von 1 U/min krieg ich irgendwie bei den niedrigen > Drehzahlen ich hin. Warum nicht? Rechne doch einmal vor, warum das nicht funktioniert.
Timer @1Mhz 100 U/min -> T=0.6 -> Zählerwert zwischen 2 Pulsen: 600000 101 U/min -> T=0.594059 -> Zählerwert zwischen 2 Pulsen: 594059 10000 U/min -> T=0.6 -> Zählerwert zwischen 2 Pulsen: 6000 10001 U/min -> T=0.594059 -> Zählerwert zwischen 2 Pulsen: 5999 Mhh ... dann müsste es doch gehen, oder ist mein Ansatz falsch? Bei den niedrigen Drehzahlen muss ich halt die Überläufe mitzählen.
Mike schrieb: > Bei den niedrigen Drehzahlen muss ich halt die Überläufe mitzählen. :-) Exakt. Du kannst auch mal untersuchen, was passiert, wenn du bei einer kleinen Drehzahl den Vorteiler wechselst. Kein Mensch sagt, dass der konstant bleiben muss. Ich habs jetzt nicht durchgerechnet, ob du dann die geforderte Auflösung noch hinkriegst.
Das übliche Verfahren zur Messung kleiner Frequenzen, hier sind es ja 1,66 ... 166 Hz, ist das "reziproke Zählen" (reciprocal counter), also die Messung der Periodendauer und anschließende Division zur Bestimmung des Kehrwertes. Die 1,66 Hz werden bei 1 MHz Zähltakt auf +/- 1 Mikrosekunde genau bestimmt, das sind fast 6 Stellen Auflösung.
Du brauchst, um die gewünschte Auflösung zu erreichen, einen Timertakt von mindestens 166,7Hz·10000=1,667MHz. Dann reicht aber, wie du schon festgestellt hast, die Zählerbreite von 16 Bit nicht mehr aus, um auch die langsamste Drehzahl zu messen. Mit einer 8-Bit-Variable, die die Überläufe zählt, hast du praktisch einen 24-Bit-Zähler. Der ist dann schon wieder so groß, dass du problemlos den Timertakt und damit die Auflösung noch ein Stück erhöhen kannst. Theoretisch läuft der 24-Bit- Timer erst bei 1,667Hz·2²⁴=28MHz über, was der ATmega32 hardwaretech- nisch schon gar nicht mehr schafft. Nimm also als Timertakt direkt den Quarztakt des ATmega32, der hoffent- lich höher als 1MHz ist (je höher desto besser). Betreibe den 16-Bit- Timer im Input-Capture-Modus und zähle zusätzlich im Overflow-Interrupt eine 8-Bit-Variable hoch. Damit müsste dein Vorhaben gelingen, und du bist schon auf dem richtigen Weg dorthin.
Stimmt doch alles garnicht :-) Sicherlich möchtest Du bei höchster Drehzahl nicht 166 Ergebnisse/s zu sehen bekommen, sondern max. drei bis fünf, nicht wahr? Zähle deshalb die eingetroffenen Drehzahlimpulse zusammen mit der Gesamtzeit (capture-Wert + Überlaufe) und starte die Auswertung, wenn die Mindestezeit (0,2s) abgelaufen ist und mindestens ein Impuls gezählt wurde. Bei hohen Drehzahlen bekommst Du fünf Ergebnisse/s und bei der kleinsten etwa 1,6. Ein neues Ergebnis erscheint dann immer synchron zum letzten Drehimpuls. Zur Verfeinerung kannst Du nach zwei Sekunden Warten ohne Eingangsimpuls eine '0' ausgeben, um den Stillstand der Drehung anzuzeigen.
Danke für die Tipps. Ich habe jetzt in der Int-Service-Routine folgenden Code stehen:
1 | uint16_t TCNT3_rpm1_save; |
2 | uint16_t TCNT3_rpm1_old; |
3 | uint32_t TCNT3_rpm1_diff; |
4 | uint8_t TCNT3_overflow_save1; |
5 | uint8_t TCNT3_overflow_old1; |
6 | |
7 | uint16_t TCNT3_rpm2_save; |
8 | uint16_t TCNT3_rpm2_old; |
9 | uint32_t TCNT3_rpm2_diff; |
10 | uint8_t TCNT3_overflow_save2; |
11 | uint8_t TCNT3_overflow_old2; |
12 | |
13 | uint8_t TCNT3_overflow = 0; |
14 | |
15 | .
|
16 | .
|
17 | .
|
18 | |
19 | ISR(INT0_vect) |
20 | {
|
21 | |
22 | TCNT3_rpm2_save=TCNT3; |
23 | TCNT3_overflow_save2 = TCNT3_overflow; |
24 | |
25 | TCNT3_rpm2_diff= ( TCNT3_overflow_save2 - TCNT3_overflow_old2 ) * 65535 + TCNT3_rpm2_save-TCNT3_rpm2_old; |
26 | |
27 | TCNT3_rpm2_old=TCNT3_rpm2_save; |
28 | TCNT3_overflow_old2 = TCNT3_overflow_save2; |
29 | |
30 | }
|
Nun nimmt die Berechnung in Verbindung mit den häufigen Aufrufen so viel Zeit in anspruch, dass der Rest des Programms ins stocken gerät. Gibt es eine Möglichkeit dies besser zu machen? Gruß Mike
Häufige Aufrufe sehe ich nicht; die wirst Du auch nicht haben. Irgendeine große Berechnung sehe ich auch nicht. Schreib 'mal die 65535 als hex-Zahl 0xFFFF; jetzt sieht man besser, dass wohl 0x10000 gemeint sind. Bekommst Du denn schon ein plausibles Ergebnis? Wenn alles 'sauber' läuft, wird die Drehzahlmessung vielleicht 1% Rechenleistung beanspruchen, sodass nichts stocken muß. Dabei gehe ich von 16MHz Taktfrequenz aus.
Tropenhitze schrieb: > Stimmt doch alles garnicht :-) > > Sicherlich möchtest Du bei höchster Drehzahl nicht 166 Ergebnisse/s zu > sehen bekommen, sondern max. drei bis fünf, nicht wahr? > Zähle deshalb die eingetroffenen Drehzahlimpulse zusammen mit der > Gesamtzeit (capture-Wert + Überlaufe) und starte die Auswertung, wenn > die Mindestezeit (0,2s) abgelaufen ist und mindestens ein Impuls gezählt > wurde. Bei hohen Drehzahlen bekommst Du fünf Ergebnisse/s und bei der > kleinsten etwa 1,6. > Ein neues Ergebnis erscheint dann immer synchron zum letzten Drehimpuls. Warum so aufwändig? Die Erfassung ist doch ohnehin von der Anzeige getrennt. In der Anzeige greife ich mit die letzte Periodendauer ab und berechne die Drehzahl daraus. Und zwar genau dann, wann ich sie brauche - völlig unabhängig von der Drehzahl mit konstanter Updaterate am Display. Wer ein schlechtes Gewissen wegen der vielen ermittelten aber nichtgenutzten Periodendauern hat, der kann ja gerne beispielsweise den gleitenden Mittelwert über die letzten x Periodendauern berechnen und damit die Genauigkeit verbessern. Gruß, Bernd
Die Drehzahlbestimmung funktioniert. Nur sobald ich die Daten auf einen SD-Karte speichere, werden falsche Werte angezeigt. Zuerst dacht ich, der µC ist mit Drehzahlerfassung + speichern auf SD-Karte überfordert. Doch das Problem tritt auf, sobalt ich einmal den Zyklus Fopen(), Fclose() hatte. Schaue mir gerade die beiden Funktionen genauer an. Vielleicht machen die irgendwas mit dem Timer. Ich benutze die Lib von Peter Fleury.
... hat noch eine delay-Funktion die mit dem gleichen Timer wie die Drehzahl erfassung gearbeitet hat. Daher die Probleme. Nun funktioniert es. Danke an alle Helfer! Gruß Mike
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.