Welcher Timer für was?

Hallo,

ich lese immer wieder von Timern. Mittlerweile habe ich ein Projekt am laufen, in dem dies Sinn macht und zudem auch gut funktioniert.

Warum ich mich jedoch gerade diesen Timer (Timer1) und nicht für einen Anderen entschieden habe, konnte ich zum Start des Projekts mangels Wissen nicht sagen.

Gibt es irgendwo eine Übersicht/Tabelle über die unterschiedlichen Timer-Varianten aus der hervorgeht wo deren Vor- und Nachteile sind, bzw. was deren "gängige Einsatzgebiete" wären?

Gruß Chris

Auf Timer0 läuft millis() und delay(). Daher scheidet der aus, wenn man das verwenden will.

Timer2 ist ein 8 Bit Timer (wie Timer0), aber er hat mehr Prescaler Einstellungen als Timer1. Für schnelle Sachen wird er daher gerne genommen, da er sehr flexibel ist was das Einstellen der Zeiten betrifft.

Timer1 und Timer3 aufwärts (auf dem Mega) sind 16 Bit Timer. Wenn man also lange Zeiten zählen will kann das Vorteile haben, da die nicht so schnell überlaufen. Bei den Timern gibt es noch den Input Capture Modus, aber das braucht man auf dem Arduino eher selten bis gar nicht, da man Signale auch recht gut mit millis() und micros() messen kann. Und es gibt mehr PWM Modi als auf Timer2, was aber in der Praxis auch nicht weiter relevant ist.

Ansonsten funktionieren die aber alle grob gleich. Wenn man einen versteht, versteht man auch die meisten Funktionen der anderen Timer.

Hier ist ein gutes Tutorial:
http://maxembedded.com/2011/06/22/introduction-to-avr-timers/
Wobei es da ein, zwei Stellen gibt bei denen die Register nicht mit den größeren Atmegas übereinstimmen (vor allem hat jeder Timer ein eigenes TIMSK Register! TIMSK0, TIMSK1, TIMSK2. Die Teilen sich nicht ein Register wie bei dem Prozessor im Tutorial). Es lohnt sich daher auch mal die Registerbeschreibung im Datenblatt des Prozessors zu lesen.

+Karma klick :wink:

1000 Dank.

Gruß Chris

Hier ist noch eine brauchbare Einstiegs-Anleitung auf Deutsch:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Zähler_des_AVR
Und teilweise noch das:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Timer

Gerade für den Anfang ist das da gut erklärt. Auch hier gilt dass die Register auf dem Atmega328 und Atmega2560 an ein, zwei Stellen anders sind! Vor allem TIMSK - das Timer Interrupt Masken Register. Und das TIFR Register, wobei man letzteres nicht per Hand anfassen muss.

Da ist auch erklärt wie man Timer2 mit einem Uhrenquarz als RTC verwenden kann. Das ist wieder eine Anwendung die auf dem Arduino nicht relevant ist, da man leicht eine externe RTC verwenden kann.

Was C Code betrifft, bist du aber bei MaxEmbedded besser beraten

EDIT:
Und auf den ATinys sind die Register noch mal ganz anders aufgebaut. Da muss man dann wirklich das Datenblatt lesen. Wobei das da im Datenblatt viel besser beschrieben ist. Auf den ATinys gibt es z.B. sehr hohe Prescaler Einstellungen und PWM ist benutzerfreundlicher gemacht und erklärt.

Hallo,

eine Ergänzung zu den ausführlichen Links von Serenifly, eine Zusammenfassung aus einem englischen Buch, weil die Möglichkeiten doch sehr vielfältig sind. Standardmäßig arbeiten die Timer an Pin 5, 6 mit 1kHz und an Pin 3, 9, 10, 11 mit 500Hz. Änderungen an Timer0 haben Auswirkungen auf die Funktionen delay, millis und micros.

TCCR0B = TCCR0B & 0b11111000 | <setting>; //Timer 0 (PWM pins 5 & 6) 
TCCR1B = TCCR1B & 0b11111000 | <setting>; //Timer 1 (PWM pins 9 & 10) 
TCCR2B = TCCR2B & 0b11111000 | <setting>; //Timer 2 (PWM pins 3 & 11) 

Available PWM Frequency Settings for Each Arduino System Timer 
Arduino Timer   	<setting>  	Divisor  	Frequency (Hertz) 
0 (pins 5 and 6)  	0x01  		1  		62500 
0 (pins 5 and 6)  	0x02  		8  		7812.5 
0 (pins 5 and 6)  	0x03  		64  		976.56 
0 (pins 5 and 6)  	0x04  		256		244.14 
0 (pins 5 and 6)  	0x05  		1024	        61.04 
1 (pins 9 and 10)  	0x01  		1  		31250 
1 (pins 9 and 10)  	0x02  		8  		3906.25 
1 (pins 9 and 10)  	0x03  		64  		488.28 
1 (pins 9 and 10)  	0x04  		256  		122.07 
1 (pins 9 and 10)  	0x05  		1024  		30.52 
2 (pins 3 and 11)  	 0x01  		1  		31250 
2 (pins 3 and 11)  	0x02  		8  		3906.25 
2 (pins 3 and 11)  	0x03  		32  		976.56 
2 (pins 3 and 11)  	0x04  		64  		488.28 
2 (pins 3 and 11)  	0x05  		128  		244.14 
2 (pins 3 and 11)  	0x06  		256  		122.07 
2 (pins 3 and 11)  	0x07  		1024  		30.52

Genauer gesagt ist das eine Tabelle für die Frequenz an den PWM Pins. Es kann ratsam sein diese auf ihr Maximum zu erhöhen wenn man die Frequenz am Verbraucher hört.

Hallo,

sind das nicht eher die einstellbaren Frequenzen der Timer, nur das diese an die "PWM Pins" herausgeführt werden?

Die Frequenz der Timer ergibt sich aus der Kombination von Prescaler und Compare Match Register. Hier ist der Vergleichs-Wert fest und man ändert nur den Prescaler.

Wenn man noch mit dem Vergleichs-Wert herumspielt, kann man je nach PWM Modus glaube ich auch noch andere Frequenzen einstellen. z.B. die 38kHz bei IR-Sendern. Das kann man auch mit PWM machen.

Hab zwar noch nicht alles verstanden, aber dein Posting hört sich interessant an @Serenifly.
Dafür muss man wohl den CTC-Modus aktivieren, oder? Auf welchen festen Wert steht der Vergleichs-Wert ansonsten?
Hat jemand ein (Arduino-)Beispiel hierfür?

Also letztendlich würde mich es interessieren, ob man auch eine Frequenz von 25 kHz erzeugen kann. Dieser Wert wird üblicherweise von PWM-Lüftern verwendet. Der nächste Wert der ansonsten in der Nähe liegen würde wäre 31,25 kHz...

Das hängt vom PWM Modus ab. Da gibt es zig verschiedene. Auf dem Arduino läuft Timer0 auf Fast PWM und Timer1 und Timer2 in phase-correct PWM

Schau ins Datenblatt

Den Teil verstehe ich aber auch nicht komplett. Bei MaxEmbedded gibt es auch zwei Tutorials zu PWM:
http://maxembedded.com/2011/08/07/avr-timers-pwm-mode-part-i/
http://maxembedded.com/2012/01/07/avr-timers-pwm-mode-part-ii/

Da steht z.B.:

The following code discusses how to create a PWM signal of a desired duty cycle. If you wish to change its frequency, you need to alter the TOP value, which can be done using the ICRx register (which is not supported by 8-bit timers). For 16-bit Timer1, it can be varied using ICR1A. I will discuss about this soon when we discuss about servo control.

Ok, das mit dem Compare Register war dann falsch. Das ändert den Duty Cycle. Aber es geht auch anders.

Ob das jetzt Arduino Code oder AVR C ist, ist egal. Der Code da lässt sich sehr leicht anpassen. Reinen Arduino Code auf der Ebene ist eher selten, da das kein Anfänger Thema ist.

Hallo,

Also letztendlich würde mich es interessieren, ob man auch eine Frequenz von 25 kHz erzeugen kann. Dieser Wert wird üblicherweise von PWM-Lüftern verwendet. Der nächste Wert der ansonsten in der Nähe liegen würde wäre 31,25 kHz...

Die Tabelle zeigt alle möglichen Kombinationen. Deine Wunschfrequenz von 25kHz ist nicht dabei. Man muß sich dann mit der nächst passenden begnügen. Was noch möglich wäre, den Takt der CPU von 16 auf 8 oder 4MHz runterzunehmen und damit die möglichen Frequenzen zu halbieren oder zu vierteln. Ob das Sinn macht kommt darauf an was der µC sonst noch so machen muß. Oder man muß einen externen "PMW IC anbauen" der mehr Optionen bietet.

Je nach Timer und Modus sollte man die Frequenz auch frei einstellen können. Wenn man auf den Arduino Kram verzichtet und das per Hand macht.

Schau dir mal die Tabelle auf Seite 136 des Atmega328 Datenblatts an. Auf Timer1 läuft auf dem Arduino glaube ich PWM in Modus 1. Phase correct aber mit einem festem TOP von 0xFF. Das heißt der Timer läuft immer von 0 bis 0xFF und wieder zurück und schaltet beim Wert des Compare Match Registers einen Ausgang am.

Es gibt aber unten auch Modi mit variablem TOP Register! z.B Modus 10

Hallo,

okay, wenn man Hardware nah programmiert stehen einem sämtliche Optionen offen. Da muß man erstmal durchblicken. Ich überblicke das nicht. Habe noch ein Bsp. Code von meinem R8C13 angeschaut, ja da konnte man alles machen. Falls man durchblickt. :grin:

Also alles verstanden habe ich auch nicht, aber habe beim Recherchieren noch paar Informationen gefunden :slight_smile:

Wenn ich das richtig gesehen habe, kann man mit dem CTC Modus ein Interrupt auslösen. Damit könnte man z.B. auch einen digitalen Pin toggeln, also ein- und ausschalten. In der Frequenz ist man glaube ich ziemlich variabel und könnte somit auch ein PWM-Signal erzeugen, jedoch mit festem Verhältnis von 50%.

Das 'richtige' gefunden habe ich dann aber auf der Seite von Nick Gammon. Hier ist ziemlich viel erklärt, wovon ich das meiste aber auch nicht so richtig verstanden habe :smiley:

Interessant ist der Abschnitt "Simple timer output" oder der Nachfolgende "Frequencies and periods for various counter values". Dort sind Beispiele und auch eine Tabelle aufgeführt. Eine Frequenz von zum Beispiel 25 kHz kann mit folgendem Code erzeugt werden:

const byte OUTPUT_PIN = 3;  // Timer 2 "B" output: OC2B

const byte n = 79; 

void setup() 
 {
  pinMode (OUTPUT_PIN, OUTPUT);

  TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on compare
  TCCR2B = bit (WGM22) | bit (CS21);         // fast PWM, no prescaler
  OCR2A =  n;                                // from table  
  OCR2B = ((n + 1) / 2) - 1;                 // 50% duty cycle
  }  // end of setup

void loop() { }

Hierbei wird ein Prescaler von 8 verwendet. Das Tastverhältnis kann über OCR2B verändert werden, kann auch in der loop() geschehen.

Hallo,

Danke für den Link, ist erstmal gespeichert. Ist ganz schön viel Stoff. Ich glaube das beackert man nur wenn man es wirklich braucht. :wink:

Hallo,
ermöglicht der Atmega 2560 im Timer0 den Compare- match und den Overflow- Match int. gleichzeitig?
Gruß
Reinhard

Das kannst natürlich beide auswerten. Aber nicht wortwörtlich gleichzeitig. Der Compare Match Interrupt hat eine höhere Priorität als der Overflow Interrupt. Wobei es sowieso sehr unwahrscheinlich ist, dass die beiden zur gleichen Zeit auftreten.

Timer0 wird auf dem Arduino übrigens schon standardmäßig von der Software verwendet.

Danke für die Antwort. Hatte einen Fehler: TIMSK0 |= (1<OCIE0A) statt: TIMSK0 |= (1<<OCIE0A);
ein < zuwenig!

Hallo,

hätte noch eine blöde Frage oder mehrere :wink:
Die Timerausgänge sind doch an bestimmte Pins gekoppelt. Muß man diese Pins der benutzen Timer frei lassen?
Wenn nicht, warum nicht?

Nein. Wenn du den Timer nur intern benutzt sind kannst du die Pins als I/Os verwenden. Die werden nur bei Bedarf mit dem Timer verbunden (d.h. wenn du das im Code so angibst).