Auszug aus dem Arduino Messlabor Kap. 5.
Der Timer 0 mit einer Auflösung von 8 Bit kann zur Erzeugung eines symmetrischen Rechtecksignals verwendet werden. Zur Initialisierung wird TCCR0A=0x42 gesetzt. Das folgende Register stellt den Vorteiler ein. Mit TCCR0B=0x00 ist der Generator abgeschaltet, mit TCCR0B=0x01 erhält er den vollen Takt von 16 MHz. Weitere Vorteiler-Stufen reichen bis zu einem Verhältnis von 1024. Die genaue Frequenz wird mit OCR0A = 255 (/256, kleinste Frequenz) bis OCR0A = 0 (/1, größte Frequenz) eingestellt. Der Zähler zählt aufwärts und springt jeweils auf 0, wenn OCR0A erreicht wird. Gleichzeitig wird dann der Ausgang OC0A am Port D6 getoggelt. Dadurch ergibt sich die höchste Frequenz von 8 MHz. Die tiefste Frequenz ist 16 MHz/2/1023 /256 = 30,528 Hz.
TCCR0A = 0x42; //Timer0 Toggle OC0A
TCCR0B = 0x00; //aus
OCR0A = 255;
Zur Einstellung der Frequenz
müssen zwei Bytes für den Vorteiler und den Timer übertragen werden. Hierzu
wurde das Kommando 90 festgelegt.
if (c==90){ //OC0A Frequenz
TCCR0B = USART_Receive();
OCR0A = USART_Receive();
}
Im User-Programm führt jede
Änderung am Frequenzregler HScroll8 zu einer neuen Ausgabe. Für eine möglichst
feinstufige Einstellung werden fünf Bereiche mit unterschiedlichem Vorteiler
(1, 8, 64, 256, 1024) verwendet. Die ausgegebene Frequenz wird berechnet und
auf der Oberfläche angezeigt.
Private Sub HScroll8_Change()
d = HScroll8.Value
If d = 0 Then pre = 0: n = 0
If d > 0 Then
pre = 5
n = 256 - d
If n > -1 Then f = 8000000 / 1024 / (n + 1)
End If
If d > 192 Then
pre = 4
n = 448 - d
If n > -1 Then f = 8000000 / 256 / (n + 1)
End If
If d > 384 Then
pre = 3
n = 640 - d
If n > -1 Then f = 8000000 / 64 / (n + 1)
End If
If d > 608 Then
pre = 2
n = 864 - d
If n > -1 Then f = 8000000 / 8 / (n + 1)
End If
If d > 832 Then
pre = 1
n = 1088 - d
If n > -1 Then f = 8000000 / (n + 1)
End If
If f < 100000 Then Label11.Caption = "D6 " +
Str(Round(f)) + " Hz"
If f >= 100000 Then Label11.Caption = "D6 " +
Str(Round(f/ 1000)) + " kHz"
SENDBYTE 90
SENDBYTE pre
SENDBYTE n
End Sub
Ausgabe und Anzeige eines
Signals von 1000 Hz
Viele wichtige Frequenzen
können genau eingestellt werden, die meisten Frequenzen sind jedoch krumme
Teile von 16 MHz. Die Auflösung ist bei kleinen Frequenzen hoch und wird gegen
Ende immer gröber. Die vier obersten Frequenzen sind 2 MHz, 2,667 MHz, 4 MHz
und 8 MHz. Zum Vergleich: Der DDS-Generator hat überall eine Auflösung von ca.
1 Hz, reicht aber nur bis 5 kHz.
Mit dem Rechteckgenerator
lassen sich Frequenzen weit oberhalb der Abtastrate des Oszilloskops
einstellen. Zuverlässige Messungen mit dem Oszilloskop sind aber nur bis zur
halben Abtastrate, also bis etwa 31 kHz möglich. In der Nähe der Abtastrate
oder ihrer Vielfachen werden völlig falsche Bilder geliefert. Die doppelte
Abtastrate ist 125 kHz. Stellt man den Rechteckgenerator auf 127 kHz ein, erscheint
ein scheinbares Signal von 2 kHz, also die Differenzfrequenz. Dieses Problem
kann prinzipiell bei jedem DSO beobachtet werden, während es bei einem analogen
Oszilloskop niemals auftritt.
Messung von vermeintlichen 2
kHz bei tatsächlichen 127 kHz
Auffällig sind auch die
schrägen Flanken im Oszillogramm trotz der tatsächlichen Rechteckform. Sie
entstehen durch die endliche Abtastzeit des AD-Wandlers. Der
Sample-And-Hold-Kondensator braucht eine gewisse Zeit, um sich auf die
tatsächliche Spannung aufzuladen. Bei sehr hohen Frequenzen ändert sich der
Zustand aber bereits innerhalb der Abtastzeit. Dadurch werden in den Übergängen
Spannungen zwischen den Extremwerten gemessen. Bei sehr hohen Frequenzen werden
sogar Dreieckspannungen angezeigt.
Dreieckanzeige bei 308 kHz
Der Digitalzähler verwendet
den Timer 1 mit einer Auflösung von 16 Bit. Weil man damit nur bis 65535 zählen
kann, wird bei jedem Überlauf ein Interrupt ausgelöst, um einen zusätzlichen
Zähler zu erhöhen. Das widerspricht zwar dem Grundsatz, dass es nur einen
aktiven Interrupt geben soll, um die laufende DDS-Ausgabe nicht zu stören.
Allerdings tritt der Timer1-Interrupt nur extrem selten auf und nur dann, wenn
gerade Frequenzen über 65 kHz gemessen werden.
ISR (TIMER1_OVF_vect)
{
fh1++;
}
…
TCCR1A = 0x00;
TCCR1B = 0x07; //Timer1
Input
TIMSK1 = 0x01; //Timer1
Overflow Interrupt
TCCR1C = 0;
Zur Initialisierung wird der
Zähler an den Eingang T1 am Port D5 gelegt. Zusätzlich wird der Interrupt
freigegeben. Zur Steuerung der Torzeit wird der Timer2-Interrupt mitverwendet.
Hier wird ein Zeitzähler t eingerichtet. Bei t = 0 wird der Timer1 zusammen mit
seinem externen Highbyte fh1 zurückgesetzt. Bei t = 1 wird der Timer gestartet.
Und genau eine Sekunde später wird er gestoppt und ausgelesen.
ISR (TIMER2_OVF_vect)
{
PORTB |= 1;
…
t++;
if(t==0){ TCCR1B = 0x00;
TCNT1=0; fh1=0;}
if(t==1){ TCCR1B = 0x07;}
if(t==62501){ TCCR1B =
0x00;f=TCNT1; fh2=fh1;}
…
PORTB &= ~1;
}
if (c==91){ //Timer 1 Frequenz
USART_Transmit(fh2);
USART_Transmit(f>>8);
USART_Transmit(f & 0xFF);
}
CLEARBUFFER
SENDBYTE 91
f = READBYTE
f = 256 * f
f = f + READBYTE
f = 256 * f
f = f + READBYTE
Label9 = "D5 " +
Str(f) + " Hz"
Der Frequenzmesser arbeitet
permanent im Hintergrund ohne die DDS-Ausgabe und das Oszilloskop zu stören.
Verbindet man den Eingang D5 mit dem Ausgang D9 (= B0), kann die Abtastrate und
der regelmäßige Aufruf der Timer2-Interruptfiunktion überwacht werden. Hier
werden zuverlässig 62500 Hz angezeigt. Sollte jemals in Folge einer
Firmware-Erweiterung diese Frequenz schwanken oder absinken, weist dies auf
einen Fehler hin, der durch zu viel Zeit im Interrupt verursacht wurde.
Messung der Abtastfrequenz an D8
Messung der DDS-Ausgangsfrequenz von 1000 Hz
Zur Messung der DDS-Frequenz
eignet sich am besten der Rechteck-Ausgang D7 bzw. D4. Hier findet man
teilweise Abweichungen von einem Hertz, die teilweise durch Rundungsfehler
entstehen. Üblicherweise schwankt das unterste Digit eines Frequenzzählers,
weil die Signalfrequenz meist völlig asynchron zur Zeitbasis des Zählers ist.
Die Frequenz von 1 kHz wird in diesem Fall auch durch das Oszilloskop bestätigt, mit dem gleichzeitig das entsprechende Sinussignal gemessen wird. Allerdings kann das Oszilloskop nur Frequenzen unterhalb 31 kHz messen. Der Frequenzzähler arbeitet dagegen bis 8 MHz.
Messung von 8 MHz an D6
Bei der höchsten Messfrequenz von 8 MHz wird eine Abweichung von 4 Hz gemessen. Diese Abweichung ist durch Rechenzeit in der Timer2-Funktion begründet, die zu einer geringfügigen Verlängerung der Torzeit führen. Genauer lässt sich dieser Zeitfehler auf 0,5 µs eingrenzen.
Insgesamt hat ein Frequenzzähler scheinbar eine hervorragende Genauigkeit. Man muss allerdings bedenken, dass alle gemessenen Signale vom gleichen Takt abgeleitet sind, nämlich vom Systemtakt des Arduino. Leider verwendet der Controller keinen Quarz, sondern einen Keramik-Resonator mit 16 MHz. Genaue Messungen zeigen, dass dieser eine Abweichung bis zu rund 0,3% aufweisen kann, also etwa 50 kHz bei 16 MHz. Bei der angezeigten Frequenz von 8 MHz ist also ein Fehler bis 25 kHz möglich.
Diese Toleranzen müssen bei jeder Frequenzmessung berücksichtigt werden. Es gibt allerdings oft Aufgaben, bei denen es nur auf eine relative Genauigkeit oder die Beobachtung von Frequenzänderungen ankommt. In anderen Fällen kann man überlegen, den Keramikresonator auszubauen und durch einen Quarz zu ersetzen.