Forum: Compiler & IDEs abfrageintervall drehgeber


von gast (Gast)


Lesenswert?

Hallo,

ich möchte der Code von Peter für meinem Drehgeber (atmega8) anpassen 
und weißt nicht wie ich
diese Zeilen:
1
  TCCR0 = 1<<WGM01^1<<CS01^1<<CS00;    // CTC, XTAL = 8e6 / 64
2
  OCR0 = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5);  // 1ms

 Bei atMega8 anpassen kann.

ich habe einen Drehgeber mit
1000 Impulse pro Umdrehungen
und maximal 10 000 Drehzahl pro min.
und dafür dachte ich eine XTAL = 16e6 und eine Abfrage Zeit von mehr als 
1 ms.

Welche prescaler kann ich nehmen? (TCCR0)

Bitte um Hilfe, die Sache sind noch neue für mich

danke

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Von welchem µC nach Atmega8 willst du anpassen?

>  TCCR0 = 1<<WGM01^1<<CS01^1<<CS00;    // CTC, XTAL = 8e6 / 64
>  OCR0 = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5);  // 1ms

Die Formel würde auch für andere Prescalerwerte als 64 und andere Zeiten 
als 1e-3 Sekunden funktionieren...

Aufpassen musst du, dass bei OCR0 kein Wert > 8-Bit rauskommt, weil 
Timer0 nur 8-Bit breit ist. Wenn OCR0 zu groß wird, kannst du entweder 
den Prescaler erhöhen oder einen 16-Bit Timer benutzen.

> ich habe einen Drehgeber mit
> 1000 Impulse pro Umdrehungen
> und maximal 10 000 Drehzahl pro min.

Sind das die Maximalwerte, die der Drehgeber mechanisch und elektrisch 
kann (für die der Hersteller garantiert) oder sind das die Werte deiner 
Anlage? Willst du so schnelle Drehzahlen messen oder willst du in einem 
anderen Bereich messen?

von Karl H. (kbuchegg)


Lesenswert?

gast schrieb:

> Bitte um Hilfe, die Sache sind noch neue für mich

Dann wirds Zeit, das Funktionsprinzip eines Timers zu verstehen.
Das ist eigentlich ganz simpel.

Der Timer zählt normalerweise von 0 bis 255, weil er ein 8-Bit Zähler 
ist. Man kann den Timer jetzt anweisen, bei bestimmten Ereignissen einen 
Interrupt zu generieren. Zb. kann man ihm sagen, wenn er bei 255 ist und 
wieder auf 0 gehen würde soll er einen Overflow Interrupt auslösen.

Wie schnell zählt denn der Timer?
Das hängt von der CPU-Taktfrequenz und vom Vorteiler ab.
Ist zb die CPU.Taktfrequenz 1MHz und der Vorteiler 1, dann zählt der 
Timer auch mit 1Mhz oder anders ausgedrückt: er würde in 1 Sekunde von 0 
bis 1000000 zählen. Wenn er könnte. Er kann natürlich nicht, denn bei 
255 ist ja Schluss und es kommt ein Overflow und er beginnt wieder bei 
0.
Wieviele derartige Overflows gibt es in 1 Sekunde?
Ganz einfach. Logischerweise sind das 1000000 / 256 = 3906. Du kriegst 
also 3906 Overflows in der Sekunde, oder anders ausgedrückt 1/3906 = 
alle 0.000256 Sekunden (=0.256 Millisekunden) einen.

Benutzt du einen Vorteiler von 8, dann zählt der Timer nicht mehr mit 
den vorgegebenen 1MHz sondern mit 1MHz / 8 = 125kHz. Wie sieht dann die 
Rechnung aus?  Bis 125000 würde er zählen, wenn er könnte. Wenn alle 256 
Takte wieder bei 0 angefangen wird, macht das 125000 / 256 = 488 
Overflows, oder 1/488 = 0.002 Sekunden (=2 Millisekunden) von einem 
Overflow zum nächsten. Durch den Vorteiler ist also die Zeit zwischen 2 
Overflow Interrupts von 0.256 Millisekunden auf rund 2 Millisekunden 
angewachsen.

Nun ist ein Overflow nur eine Möglichkeit. Es gibt auch noch andere (je 
nach Timer). Zum Beispiel kann man den Timer anweisen, nicht immer bis 
255 zu zählen, bis etwas passiert, sondern man kann ihm auch einen 
Endstand (der dann bei einem 8-Bit Timer klarerweise kleiner als 256 
sein muss) vorgeben, bis zu dem er zählen soll.

Mal angenommen, du gibst ihm vor: 1Mhz, Vorteiler 1, Zählerendstand: 99
Wie sieht dann die Rechnung aus?
Der Timer würde bei einem Vorteiler von 1 wieder in 1 Sekunde von 0 bis 
1000000 zählen, wenn er könnte. Kann er aber nicht, bei 99 ist Schluss 
(so hast du es ihm ja vorgegeben). Wieviele Overflows hast du daher 
jetzt?
1000000 / 100 = 10000. Von einem Overflow zum nächsten vergehen daher 
1/10000 = 0.0001 Sekunden (0.1 Millisekunden). Interessant nicht wahr. 
Gegenüber oben hast du nur den Endwert des Timers, bis zu dem er zählen 
darf verändert. Und da der Timer nicht mehr soweit zählen darf, kommen 
natürlich auch die Overflows viel häufiger.

Das war doch nicht schwer, oder?

Jetzt bist du sicher auch in der Lage, die Berechnung zu verstehen, die 
Peter da benutzt und sie an deine Verhältnisse anzupassen. Gleich 
nachdem du rausgefunden hast, dass der Timer0 eines Mega8 kein OCR0 und 
damit auch nicht die Möglichkeit hat, einen vorzeitigen Overflow 
auszulösen :-)

von gast (Gast)


Lesenswert?

Hallo,

@stefan

ja so schnelleren Drehzahlen will ich messen.

@ Karl
Vielen Dank für die Erklärung, genau die brauchte ich

danke

von Stefan B. (stefan) Benutzerseite


Lesenswert?

gast schrieb:

> @stefan
>
> ja so schnelleren Drehzahlen will ich messen.

Dann mache eine Fehlerabschätzung um die benötigte Messzeit heraus zu 
finden.

10000 rpm sind 166,667 Umdrehungen/s
*1000 Impuls/Umdrehung => 166667 Impulse/s (6 µs/Impuls)

In 1ms würde man 166 Impulse zählen und 0,667 nicht. Das wäre ein Fehler 
von 0,4% (=> 10000 - 40 rpm). 166 Impulse passen gut in einen 
8-Bit-Wert.

In 2ms würde man 333 Impulse zählen, d.h. man braucht bereits einen 
16-Bit-Wert. Der Fehler wäre 0,334 / 333 = 0,1% (=> 10000 - 10 rpm).

Zur Ausnutzung des 16-Bit Zählers könnte man die Messzeit auf 
65535/166667 = ~393,2ms ausdehnen. Dann bekäme man einen Fehler von 
~0,03% (=>10000 - 3 rpm)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

>> ich möchte der Code von Peter für meinem Drehgeber (atmega8) anpassen...
> In 1ms würde man 166 Impulse zählen
Nein, mit einem Abtastintervall von 1 ms würde man 165 Impulse verpassen 
:-(

Oder im Umkehrschluss:
die Abtastfrequenz muß mindestens 1/167 ms sein, also müsste spätestens 
alle 6us ein Interrupt ausgeführt werden. Das ist sehr sehr 
grenzwertig...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Lothar Miller schrieb:

>>> ich möchte der Code von Peter für meinem Drehgeber (atmega8) anpassen...
>> In 1ms würde man 166 Impulse zählen
> Nein, mit einem Abtastintervall von 1 ms würde man 165 Impulse verpassen

Abtastintervall und Messzeit unterscheide ich. Wenn der Timer bei jedem 
Interrupt einen Eingang abtastet, hast du Recht, dass 1ms Intervalle 
dazwischen viel zu lang sind. Unter der Messzeit verstehe ich die Zeit 
in der ein Hardwarezähler an einem Eingang des AVRs aktiv ist (sog. 
Torzeit).

von gast (Gast)


Lesenswert?

@stefan

>Zur Ausnutzung des 16-Bit Zählers könnte man die Messzeit auf
>65535/166667 = ~393,2ms ausdehnen. Dann bekäme man einen Fehler von
>~0,03% (=>10000 - 3 rpm)

bitte kennst du einer 16-Bit Zählers die du mir empholen kannst?


>In 2ms würde man 333 Impulse zählen, d.h. man braucht bereits einen
>16-Bit-Wert. Der Fehler wäre 0,334 / 333 = 0,1% (=> 10000 - 10 rpm).

Peter hat in seiner code der Timer0 compare benutzt bei Atmega8 finde 
ich nur der Timer Counter2 Match als Ersetzung, leider ist er 
8-bit-wert.

wie kannt ich das umgehen

vielen dank

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Stefan B. schrieb:
> Abtastintervall und Messzeit unterscheide ich.
Richtig, aber es geht hier noch gar nicht um die Messung, sondern erst 
mal um die Abtastung, weil kein Hardwarezähler vorhanden/verwendet 
ist.

Leider hat ein AVR keine Eingänge, die ein Quadratursignal (incl. 
Richtung) direkt auswerten könnten. Aber wenn es nur um die Drehzahl 
geht, und die Drehrichtung egal ist, dann könnte einfach ein 
Hardwarezähler verwendet werden.

EDIT:
> Peter hat in seiner code der Timer0 compare benutzt bei Atmega8 finde
> ich nur der Timer Counter2 Match als Ersetzung, leider ist er
> 8-bit-wert.
Mir scheint, hier kommt was durcheinander:
Peter verwendet den Counter als Zeitgeber.
gast verwendet den Counter als Impulszähler.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

"Man muss die ursprüngliche Fragestellung rauskitzeln und dann die beste 
Methode finden, um die Aufgabe zu lösen."

Angenommen es geht um die Ermittlung der Drehzahl im 10000 rpm Bereich 
mit einem Impulsgeber (physikalisch ein Drehgeber) mit 1000 
Impulsen/Umdrehung. Das Grundproblem ist dann eine Frequenzmessung bis 
167 kHz und für solche Frequenzmessungen gibt es sehr viele 
Beispielprojekte.

Dann kann ein System aus Torzeit und Hardwarezähler verwendet werden. 
Für die Torzeit einen AVR-internen Timer und für den Zähler einen 
AVR-internen Counter. Welche Kombination 8/8 8/16 16/8 oder 16/16 muss 
man sich ansehen. Da hilft das Datenblatt. Die Frequenz (Drehzahl) 
ergibt sich aus f = Impulse/Torzeit.

Man kann auch versuchen, die Zeit zwischen den Impulsen direkt zu messen 
und die Frequenz (Drehzahl) über f=1/Zeit zwischen Impulsen zu 
berechnen. Ich vermute(!): Die von Lothar berechneten 6µs sind bei bei 
einem AVR mit 16 MHz noch messbar, allerdings mit >~1% (+-100rpm) 
Fehler. Die notwendigen Zeitstempel könnte man sich eventuell von der 
Input Capture Einheit im AVR geben lassen.

von gast (Gast)


Lesenswert?

vielen Dank,
ich versuche es jetzt zu bekommen
gruß

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.