Wie viele millisekunden hat eine sekunde

In dies Extraausgabe kommt ns Thema Timer von Sprache. Inbegriffen geht es ca mehr als den simplen Aufruf das delay()-Funktion.

Du schaust: Wie viele millisekunden hat eine sekunde

Die Funktion delay() war bis jetzt unser treuer und ständiger Begleiter an Sachen Zeitmessung. Sie steht standardmäßig in der Arduino-Bibliothek von Verfügung, und erlaubt millisekundengenaue Wartezeiten. Was will man so mehr? bei der Entwicklung eingebetteter Systeme – übrigens nicht nur in Echtzeitfragestellungen – spielt Zeitmessung einer zentrale Rolle. delay() ist allerdings ns Mittel fürs Grobe, no für ausgefeilte Einsatzgebiete.

Was stormen konkret bei den simplen funktionen à la delay() heu millis()?

Beschränkte Auflösung: einer Genauigkeit in Millisekunden mag weil das Wartezeiten im Maßstab menschlicher Wahrnehmung passabel erscheinen. Innerhalb Rahmen technischer Ereignisse zu sein diese gelöst ungenügend. In einer ATMega-oder ATTiny-CPU oben Arduino-Boards jawohl wir es bei der weitsichtig mit Taktfrequenzen von 8 MHz heu 16 MHz zu tun. An 16 MHz wegbringen ein einzelner Takt 0,0000000625 sec. Ns ist in dem Vergleich zu einer Millisekunde (0,001 sec) ein Faktor von 1:16.000. Während jeder Millisekunde behandelt ein ATMega Tausende über Maschinenbefehlen. Daher sind Reaktionszeiten in dieser Größenordnung alles andere wie akzeptabel.Aktives Warten: während eines Delays als delay(42) ist ns Arduino-Sketch zum aktiven erwarte verurteilt. Die gewählte Wartezeit bei Millisekunden ist zudem häufig Ergebnis einen groben berechnung nach dem Motto: "Vermutlich brauchen die Initialisierung rund 2 Sekunden. Zur sicherheit verwenden wir noch einfach 3 Sekunden." ns führt zu Ineffizienz.Mangelnde Flexibilität: Timernutzung mittels delay() dient einzig zu Integrieren über Wartezeiten. Außerdem Dienste, besonders periodische Trigger als ein Watchdog-Timer, sind hiermit nicht oder zeigen unzureichend umsetzbar.

Timer on ns Chip

Würde sich ns AVR-Prozessor mit dieser nett von grober Zeitmessung befriedigt geben, sein wir in Arduino-Boards viele funktionale Abstriche bei Kauf nehmen. So erforderlich die Pulse-Width-Modulation in digitalen Ports einer hohe Timerauflösung, ca genaue Aktivitätszyklen (Duty-Cycles) einstellen zu können. Benötigen sie zum beispiel eine durchschnittliche Ausgangsspannung über 2,765643 V in einem digital Ausgang, laub sich das zeigen durch Genauigkeiten jenseits der Möglichkeiten über delay() oder millis() bewerkstelligen.

Bei Bussystemen wie I2C hagen SPI zu sein Vorgänge in dem Mikrosekundenbereich typisches und notwendig. Will einen Programm angeschlossene Komponenten über diese Bussysteme ansteuern, wäre ein auflösung von groben Millisekunden einen Show-Stopper. Nicht zuletzt erweisen wir für ns Kontrolle von Servomotoren heu zur Tonerzeugung zeitliche Bedingungen zusammen notwendig, die weil Millisekunden-getriggerte Timer schlicht nicht umsetzbar wären.

Da wir aus bisheriger erfahrung wissen, dass Arduino-Boards sehr gute Unterstützung zum PWM, Bussysteme, Servo-Ansteuerung und Tonerzeugung leisten, zusammenarbeiten sich zwei Fragen:

Wie erstellen es einen AVR-Prozessor intern, die so erforderlichen zeitlichen Auflösungen umzusetzen?Können uns uns zusammen Entwickler dies Funktionen gleichfalls zunutze machen?

Den Takt angeben

Für die genannten aufgaben integrieren das AVR-Microcontroller diverse Timer mit zugeordneten Zählregistern von 8 heu 16 Bits Breite. Diese Register starten mit ns initialen Wert von 0. Ihre Inkrementieren, so das eigentliche Hochzählen, erfolgt automatisch und periodisch. Laufen die jeweiligen register über, wird ein Timer-Überlauf-Interrupt ausgelöst.

Ein häufiger Irrtum ist übrigens, das die CPU von Arduino ns Timer antreibt. Ns Timer eines Arduino bzw. Einer AVR-Mikrocontrollers by ATmel sind von der CPU bzw. MCU unabhängig. Diese Tatsache sollten sie sich in den nachfolgenden diskussion vor augen halten.

Um einer möglichst hohe Auflösung zu erhalten, könnte ns erste Ansatz dies liegen, ns Updates ns Counter (d.h. Deren Inkrementieren) synchron zu Prozessortakt vorzunehmen. Das hat allerdings ns entscheidenden Schönheitsfehler. Bei einer angenommenen Taktfrequenz by 16 MHz wäre der Überlauf einer 8-Bit-Timers nach 16 Mikrosekunden erreicht, das eines 16-Bit-Registers nach ca 4,1 Millisekunden.

Das zu sein natürlich vorteilhaft zum kurzzeitige Zeitintervalle. Was aber, einmal wir länger Zeiträume überdecken wollen? um dies zu ermöglichen, bieten die Mikrocontroller fähnrich Prescaler. Dies konfigurieren, nach als vielen Taktzyklen ns System einen Zählregister inkrementieren soll. Durchführbarkeit Werte liegen bei 8, 64, 256 hagen 1024. Eine Prescale-Einstellung by 1024 führt zb zum Inkrementieren von Zählers dazugehörigen nach 64 Mikrosekunden bzw. 1024 Taktzyklen bei 16 MHz Taktfrequenz, sodass ns 16-Bit-Zähler zuerst nach 4,2 sekunde überläuft.

Um präzise Intervalle kommen sie programmieren, erlauben sich Timer-Register mit Zählerständen vorbelegen statt sie bei 0 starten zu lassen. Wenn angekommen, uns würden glücklich alle 0,5 sekunde eine led abwechselnd einer und ausschalten. Das gewünschte Frequenz des Timers wäre folglich 2 Hz. Einer Takt besteht im Auslösen einer Timer-Überlaufs. Zusammen genau lässt sich dies erreichen?

Wir haben es mit attache Parametern kommen sie tun:

bits definiert die Größe des Zählerregister in Bits, Über 16 für ein 16-Bit-Timer.maxcount entspricht kommen sie maximalen Zahlenwerts 2bits.prescale zu sein der auf erläuterte konfigurierbare Prescalewert, so die Zahl ns Taktzyklen bis ein zusätzlich Inkrementieren ns Timeregisters erfolgt.cpufreq vertreten die CPU-Frequenz. Das Taktzyklus angeklagt sich folglich aus 1 / cpufreq.initcount ist ns vorbelegte Startwert ns Zählregisters.count ist das notwendige Zahl von Inkrementierungen, um einem Timeroverflow auszulösen. Es gilt: count = maxcount - initcount.deltaT nominiert das gewünschte Zeitintervall bis zu zum Auslösen von Timer-Overflows. Einer könnte auch definieren: deltaT = 1 / timerfreq (gewünschte Zahl über Timer Overflows jeden Sekunde).

Es zutreffend prescale / cpufreq * count = deltaT

=> count = deltaT * cpufreq / prescale

=> maxcount - initcount = deltaT * cpufreq / prescale

=> initcount = maxcount - deltaT * cpufreq / prescale

Beispielsrechnung: alle 0,5 sekunden soll einer Timer-Overflow-Interrupt stattfinden.

Mehr sehen: Gäste Bei Anne Will Heute Abend, Aktuell: News Und Informationen Zu Anne Will

Wir verwenden einer 16-Bit-Timer: bits = 16 => maxcount = 216 = 65536.Wir bedürfen einen Timer Overflow pro halb Sekunde. deltaT = 0,5 sec = 1 / timerfreqDie Taktfrequenz ns Arduino-Board beträgt cpufreq = 16 MHz = 16.000.000 HzAls Prescale-Wert liegt prescale = 256 vor.

Der Timer startet anstatt von mit 0 mit folgendem Anfangszählerstand initcount = 65.536 - 8.000.000/256 = 34.286

Das Timer-Register muss anfangsverdacht mit 34.286 starten, damit bis um zum Timer Overflow – in Überschreiten über 65.636 – genau eine halbe sekunden vergeht. An jedem Durchlauf der Interrrupt-Service-Routine ist ns Zähler jeweils wieder mit 34.286 initialisieren.

Ein entsprechender map out könnte wie folgt aussehen. In die in diesem erwähnten Register ankunft wir später noch kommen sie sprechen.

#define ledPin 13void setup() pinMode(ledPin, OUTPUT); // Ausgabe angeführt festlegen // Timer 1 noInterrupts(); // jedermann Interrupts temporär abschalten TCCR1A = 0; TCCR1B = 0; TCNT1 = 34286; // Timer nach obiger Rechnung vorbelegen TCCR1B // hier kommt die selbstdefinierte Interruptbehandlungsroutine // für den Timer OverflowISR(TIMER1_OVF_vect) TCNT1 = 34286; // Zähler wieder vorbelegen digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // led ein und ausvoid loop() // Wir könnten hier hinzufügen Code integrieren

World of Timers

Ein Arduino hinweisen nicht nur einen einzelnen Timer sondern etliche Timer auf. Sind nicht Wunder, zu sein Timer doch essenzielle Grundkomponenten zum verschiedene aufgaben eines Mikrocontrollers.

Timer 0 ( 8 Bit) Verwendet zum Funktionen zusammen delay(), millis(), micros()Timer 1 ( 16 Bit) Verwendet über der Servo-BibliothekTimer 2 ( 8 Bit) Verwendet von der Tone-BibliothekTimer 3 (16 Bit) zeigen Mega Timer 4 (16 Bit) zeigen MegaTimer 5 (16 Bit) zeigen Mega

Beim Arduino:

PWM Pins 5 und 6 kontrolliert durch Timer 0PWM Pins 9 und 10 kontrolliert aufgrund Timer 1PWM Pins 3 und 11 kontrolliert durch Timer 2

Beim Arduino Mega:

PWM Pins 4 und 13 kontrolliert durch Timer 0PWM Pins 11 und 12 kontrolliert durch Timer 1PWM Pins 9 und 10 kontrolliert aufgrund Timer 2PWM Pins 2, 3 und 5 kontrolliert weil Timer 3PWM Pins 6, 7 und 8 kontrolliert durch Timer 4PWM Pins 44, 45 und 45 kontrolliert weil Timer 5

Es ergibt zusätzlich varied Einschränkungen zu beachten:

Pin 11 ns Arduino ist zugleich pen mit PWM-Fähigkeit und Master-Out-Slave-In-Pin des SPI-Busses. Demzufolge lassen sich beide Funktionen nicht gleichzeitig nutzen. Für die Tonerzeugung zu sein mindestens Timer 2 im Einsatz. Deshalb lassen sich die Pins 3, 11 (Arduino) bzw. 9, 10 (Arduino Mega) nicht für PWM nutzen, solange die Funktion tone() im einsatz ist.Beim verbinden von Servos rechts sich Timer exklusiv dieser pflicht widmen, wieso den sich die Zahl ns Digitalpins mit PMW-Unterstützung reduziert.

Timer-Register

Wie innerhalb Sketch weiter auf ersichtlich, erfolgt die steuerung der Timer-Funktionalität von verschiedene Register. Das Symbol µ vertreter die Nummer des jeweiligen Timers, so 0, 1, 2, ..., . . TCNTµ ist daher das Zählregister über Timer µ. Das Zählregister zum Timer 1 zu sein dementsprechend TCNT1, das für Timer 0 TCNT0.

Der Einfachheit halber beziehen sich ns nachfolgenden Diskussionen wie auch die beide Beispiel-Sketches an Timer 1. Ns Weiteren erspare mir Ihnen einer Aufzählung sämtlicher Details, jedoch fokussiere mich an die relevanten Eigenschaften.

TCCR1A (Timer Counter/Control Register): die Flags PWM10 und PWM11 erlauben einer Festlegung der auflösung für das Fall, das Timer 1 kommen sie PWM-Steuerung dient. Ausgangsbasis sei ns Vereinbarung TCCR1A = 0;:

Kein PWM: no-op8-Bit PWM: TCCR1A |= (1 9-Bit PWM: TCCR1A |= (1 10-Bit PWM: TCCR1A |= (1

TCCR1B (Timer Counter/Control Register): Konfiguration des Prescaler.

Kein Prescaler: TCCR1B = 0; TCCR1B |= (1 Prescale = 8: TCCR1B = 0; TCCR1B |= (1 Prescale = 64: TCCR1B = 0; TCCR1B |= (1 Prescale = 256: TCCR1B = 0; TCCR1B |= (1 Prescale = 1024: TCCR1B = 0; TCCR1B |= (1

Weitere Kombinationen zulässig die externe bewährung über ns T1-Pin.

TCNT1 (Timer/Counter Register): d.h. Das eigentliche Zähler.

OCR1 (Output to compare Register): Ist das Zähler an TCNT1 gleich zum Inhalt ns OCR1, erfolgt einer Timer compare Interrupt.

ICR1 (Input record Register, anzeigen für 16-Bit-Register): Messung der Zeit zwischen zwei Flanken von Input record Pins, die aufgrund externe Schaltungen zustand kommen. Laub sich auch zur Messung der Umdrehungszahl einer Motors einsetzen. Wird auch über Einstellungen von TCCR1A mit beeinflusst.

TIMSK1 (Timer/Counter Interrupt Mask Register): hier lassen sich Timer Interrupts unterbinden heu erlauben.

Scharf schalten von Output to compare Interrupts: TIMSK1 |= (1 spitz schalten ns Timer Overflow Interrupts (16 Bit): TIMSK1 |= (1 spitz schalten ns Timer Overflow Interrupts (16 Bit): TIMSK1 |= (1

TIFR1 (Timer/Counter Interrupt Flag Register): hier lassen sich noch unverarbeitete Interrupts feststellen. Das Bits korrespondieren mit denen von TIMSK1.

Alternative ausweg CTC

Statt einen Interrupt in Überlauf eines Timer-Registers auszulösen als im oberen Sketch, gibt es es die alternative Option namens CTC (Clear Timer on compare Match). Bei dieser vergleicht das Mikrocontroller, ob ns Inhalt ns Zählerregisters identisch mit dem Inhalt des zu Timer gehörigen OCR (Output to compare Registers) ist. Wenn ja, wird ein Timer to compare Interrupt abzug und das Register in 0 zurückgesetzt. Wiederum ziel jede halb Sekunde ns Interrupt stattfinden.

Bei einem Prescaling von 256 und einer Taktfrequenz über 16 MHz können wir das obige formel für count anwenden: count = deltaT * cpufreq / prescale = 0.5 * 16.000.000 / 256 = 31.256.

Obiger Sketch möchten sich an diesem Fall deshalb ändern in:

#define ledPin 13void setup()= (1 TIMSK1 // hier kommt die selbstdefinierte Interruptbehandlungsroutine // für ns Timer compare InterruptISR(TIMER1_COMPA_vect) TCNT1 = 0; // it is registered mit 0 initialisieren digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // led ein und ausvoid loop() // Wir kann sein hier zusätzlich Code integrierenZusammenfassungIn dies Extra gehen es um den trimmen mit ausgefeilten Timer-Funktionen in Prozessoren ns ATmel-Familie (ATMega, ATTiny). Damit sollten sie jetzt einen tiefergehendes Verständnis ns Thematik besitzen. Wollen sie es still detaillierter wissen, bezugnahmen ich sie auf Dokumente des Herstellers ATmel wie zum beispiel das hier.

Mehr sehen: Mach Dir Keine Sorge Auf Englisch, Keine Sorge

Mehr von die praktische anwendungen dieser Funktionalität erfahren sie in fortgeschrittenen Anwendungen wie etwa Sound Synthesis, PWM hagen Servomotoren. Eine weitere lohnenswerte Lektüre ist dieser artikel von Adafruit.

Es zu sein aber sogar eine qualität Idee, ns Gelernte aufgrund eigene Experimente zu vertiefen.