Hallo,
ungefähr 10-11% Fehler maximal, allerdings wird er geringer je niedriger
die Frequenz ist, bei ca. 500kHz ist der Fehler fast 0. Als würde der
Timer nicht mitkommen... Allerdings ist es ja dasselbe Signal an beiden
Eingängen, mit 50/50 Tastverhältnis.
Gruß,
Jan
Was da nicht mitkommt, ist die Interrupt-Verarbeitung.
Bis der Kontroller dazu kommt, die Int-Befehle abzuarbeiten muss er erst
aus dem Grundprogramm aussteigen. Bis dahin können mehrere Taktzyklen
vergehen, deren Zahl sogar zufällig verschieden sein kann. Auch das
Nullsetzen des Zählers wird dadurch beeinflusst.
Dazu kommt noch, dass der zuständige Pin das Eingangssignal nicht direkt
an den Zähler weiterleitet sondern mit dem Kontrollertakt gescannt wird.
Ein Teil Fehlers kann auch dadurch entstehen, dass beim T0 (8bit) mehr
Lesezeit gebraucht wird als beim T1 (16bit)
Der durch Int-Verhalten entstehende Fehler kann dadurch verringert
werden, dass man mit Compare-Register arbeitet. Aber die
Torzeiterzeugung bleibt weiterhin mangelhaft.
Für genaue Zeitmessung keine Kontroller sondern einen normalen Zähler
als Messzähler und Zeitbasiszähler verwenden.
Hier kommt noch zusätzlich die Zeile if...>48 in der main dazu: die Ints
der Timer verpfuschen noch den zeitlichenn Ablauf der main, sodass auch
die Messzeit kräftig gestört wird.
Das Problem tritt aber auch auf, wenn ich time so setze das der
Timer1-Überlauf nie eintritt. Und im Timer2-Interrupt werden die Timer
ja zuerst angehalten, und dann erst gelesen und wieder gestartet, also
sollte dafür genug Zeit sein...
Und es sind nicht nur einige wenige Zähl-Takte, sondern z.B. bei 50ms
Torzeit 30000 (Timer0) gegen ca. 27000 (Timer1).
Gruß,
Jan
Aber die Messzeit wird doch erheblich durch den Programmablauf
verändert. Einmal misst der Kontroller z.B. 50ms lang, das andere mal
nur 49ms. Gerade dei Torzeit wird hier in der main bestimmt, und der
Ablauf der main wird durch die Int's erheblich gestört.
Übrigens : ist der Takt des Kontrollers wirklich 16MHz oder läuft er
(per fuse) um den Faktor 8 herabgesetzt?
Meiner Meinung nach ist es ein Pfui, Zeitmessungen per Kontroller
durchzuführen und besonders wenn dabei ein C-Programm auf wenig
kontrollierte Weise in Maschinensprache übersetzt wird.
Peter R. schrieb:> Aber die Messzeit wird doch erheblich durch den Programmablauf> verändert. Einmal misst der Kontroller z.B. 50ms lang, das andere mal> nur 49ms. Gerade dei Torzeit wird hier in der main bestimmt, und der> Ablauf der main wird durch die Int's erheblich gestört.
Sorry, aber das ist doch Unsinn. Die Torzeit wird durch einen weiteren
Timer per Interrupt erzeugt. Die einzige Varianz, die sich da ergibt,
ist die Latenz dieses Interrupts, also maximal ein paar µS.
Timer2 hat glaub ich einen Clock Input der zum Zählen in Hardware
genutzt werden kann. Guck mal ob Timer1 das auch hat, wenn ja nimm die
zum Zählen und Timer0 als Zeitbasis.
Stefan Ernst schrieb:> Sorry, aber das ist doch Unsinn. Die Torzeit wird durch einen weiteren> Timer per Interrupt erzeugt. Die einzige Varianz, die sich da ergibt,> ist die Latenz dieses Interrupts, also maximal ein paar µS.
Der Zeitablauf wird hier durch Zählen innerhalb der main (if..>49..)
bestimmt.
Dabei wird 50 mal der 1ms-Int beteiligt. Die Streuung durch die
Int-latency kann da um den Faktor 50 vergrößert werden, da die ints die
main 50mal unterbrechen.
Wer auf die oben gezeigte Methode Zeitmessungen durchführt, muss eben
seine Ansprüche auf Genauigkeit herabsetzen. Oder er muss genau wissen,
was die Messung verfälscht.
Jan schrieb:> Und es sind nicht nur einige wenige Zähl-Takte, sondern z.B. bei 50ms> Torzeit 30000 (Timer0) gegen ca. 27000 (Timer1).
Was mir aufgefallen ist:
Bei 1Mhz Messfrequenz und 50ms Torzeit sollte der Zählerstand aber 50000
sein.
Ansonsten:
Das das durch die Interrupt Latenz nicht auf die Schwingung genau ist,
ist dir ja klar. 3000 Ticks Differenz ist allerdings zu groß für diese
banale Erklärung. Ich komm allerdings auch nicht drauf, was da los sein
könnte.
Peter R. schrieb:> Stefan Ernst schrieb:>> Sorry, aber das ist doch Unsinn. Die Torzeit wird durch einen weiteren>> Timer per Interrupt erzeugt. Die einzige Varianz, die sich da ergibt,>> ist die Latenz dieses Interrupts, also maximal ein paar µS.>> Der Zeitablauf wird hier durch Zählen innerhalb der main (if..>49..)> bestimmt.
Nein.
Lies das Programm nochmal.
Er benutzt den Timer 2 als Torwächter. In der ISR werden 49 Aufrufe
abgezählt und beim 49. Aufruf die Timer 0 und 1 sofort gestoppt. Die
komplette Steuerung der Torzeit findet im Overflow-Interrupt des Timers
2 statt.
Das ihm bis zum tatsächlichen Stoppen des Timers ein paar Zyklen zu viel
einlaufen ist ihm bewusst. Aber das sind keine 3000 Ticks Differenz der
Messungen von Timer 0 und Timer 1.
Peter R. schrieb:> Der Zeitablauf wird hier durch Zählen innerhalb der main (if..>49..)> bestimmt.
Das "if" steht in einem Interrupt, nicht in main.
Peter R. schrieb:> Dabei wird 50 mal der 1ms-Int beteiligt. Die Streuung durch die> Int-latency kann da um den Faktor 50 vergrößert werden, da die ints die> main unterbrechen.
Die Zähler laufen selbstständig und werden nicht per Software wieder auf
Null gesetzt. Die Latenzen der 50 Interrupts summieren sich daher nicht
auf. Nur die Latenz des letzten Interrupts schlägt zu Buche.
Karl Heinz Buchegger schrieb:> Jan schrieb:>>> Und es sind nicht nur einige wenige Zähl-Takte, sondern z.B. bei 50ms>> Torzeit 30000 (Timer0) gegen ca. 27000 (Timer1).>> Was mir aufgefallen ist:> Bei 1Mhz Messfrequenz und 50ms Torzeit sollte der Zählerstand aber 50000> sein.
Ja richtig, das war bei einer kleineren Frequenz. Bei 1MHz ist der
Fehler sogar noch größer...
Ich komme einfach nicht darauf was da los ist...
Gruß,
Jan
> Wer auf die oben gezeigte Methode Zeitmessungen durchführt,> muss eben seine Ansprüche auf Genauigkeit herabsetzen. Oder> er muss genau wissen, was die Messung verfälscht.
Darum gehts doch noch gar nicht.
Das Problem ist, dass er signifikant verschiedene Messwerte erhält, je
nachdem ob er Timer 0 oder Timer 1 benutzt.
Wenn die Werte falsch sind, sollten sie bei beiden Timern gleich falsch
sein. Sind sie aber nicht. Die Werte laufen auseinander und im Moment
kann das keiner erklären.
Jan schrieb:> Ja richtig, das war bei einer kleineren Frequenz. Bei 1MHz ist der> Fehler sogar noch größer...>> Ich komme einfach nicht darauf was da los ist...
Hast du im Datenblatt nachgesehen, ob es technologische Beschränken für
die Maximalfrequenz gibt, mit denen die Timer getaktet werden dürfen?
(Ich kanns mir zwar nicht vorstellen, dass es da zwischen den Timern
Unterschiede gibt, aber in der Not ist jeder Strohhalm recht)
Jan schrieb:> Und es sind nicht nur einige wenige Zähl-Takte, sondern z.B. bei 50ms> Torzeit 30000 (Timer0) gegen ca. 27000 (Timer1).
Und du bist dir wirklich ganz sicher, was die Zuordnung angeht? Es ist
wirklich Timer1 derjenige, bei dem die Takte fehlen?
Wäre es umgekehrt, kämen zeitweise (und zwar zu lange) in main gesperrte
Interrupts in Betracht.
> was genau meinst Du? Ich setze ja nur jeweils den clock source für alle> drei Timer, oder was meinst Du?
"Enabling and disabling of the clock input must be done when T1/T0 has
been stable for at least one system clock cycle, otherwise it is a risk
that a false Timer/Counter clock pulse is generated."
Ich würde das wiederholte Disable/Enable im TIMER2_OVF_vect_interrupt
komplett weglassen.
1
volatileunsignedchartime;
2
volatileunsignedshortfrequencycounter_1;
3
volatileunsignedshortfrequencycounter_2;
4
volatileunsignedlongfrequency_1;
5
volatileunsignedlongfrequency_2;
6
7
// Timer2 Overflow Interrupt
8
#pragma vector = TIMER2_OVF_vect
9
__interruptvoidTIMER2_OVF_vect_interrupt(void)
10
{
11
uint8_ttmp_tcnt0=TCNT0;
12
uint16_ttmp_tcnt1=TCNT1;
13
14
time++;
15
if(time>48)
16
{
17
frequency_1=tmp_tcnt0+frequencycounter_1*256UL;
18
frequency_2=tmp_tcnt1+frequencycounter_2*65536UL;
19
time=0;
20
frequencycounter_1=0;
21
frequencycounter_2=0;
22
TCNT0=0;
23
TCNT1=0;
24
TCNT2=0;// neue Torzeit starten
25
}
26
}
27
28
// Timer0 Overflow Interrupt
29
#pragma vector = TIMER0_OVF_vect
30
__interruptvoidTIMER0_OVF_vect_interrupt(void)
31
{
32
frequencycounter_1++;
33
// Kann frequencycounter_1 überlaufen?
34
}
35
36
// Timer1 Overflow Interrupt
37
#pragma vector = TIMER1_OVF_vect
38
__interruptvoidTIMER1_OVF_vect_interrupt(void)
39
{
40
frequencycounter_2++;
41
}
42
43
intmain(void)
44
{
45
TIMSK0|=(1<<TOIE0);
46
TIMSK1|=(1<<TOIE1);
47
TIMSK2|=(1<<TOIE2);
48
// External clock source on T0 pin. Clock on rising edge.
49
TCCR0B|=(1<<CS00|1<<CS01|1<<CS02);
50
// External clock source on T1 pin. Clock on rising edge.
// [...] Frequenzen tmp_frequency_X auf LCD ausgeben
67
}
68
}
>> Und es sind nicht nur einige wenige Zähl-Takte, sondern z.B. bei 50ms>> Torzeit 30000 (Timer0) gegen ca. 27000 (Timer1).
Diese Zahlen verstehe ich nicht.
F_CPU 16 MHz, 8-Bit Timer2 Prescaler 64 mit Softwaretimer 0..48 ergibt
eine Torzeitvon 50,176 ms und bei einem 1 MHz exteren Signal an T0/T1
müssten gelten:
50176 = 0 + 196 * 256UL;
50176 = 50176 + 0 * 65536UL;
Krapao schrieb:> Ich würde das wiederholte Disable/Enable im TIMER2_OVF_vect_interrupt> komplett weglassen.
Habe ich ausprobiert, keine Änderung.
>>> Und es sind nicht nur einige wenige Zähl-Takte, sondern z.B. bei 50ms>>> Torzeit 30000 (Timer0) gegen ca. 27000 (Timer1).>> Diese Zahlen verstehe ich nicht.>> F_CPU 16 MHz, 8-Bit Timer2 Prescaler 64 mit Softwaretimer 0..48 ergibt> eine Torzeitvon 50,176 ms und bei einem 1 MHz exteren Signal an T0/T1> müssten gelten:>> 50176 = 0 + 196 * 256UL;> 50176 = 50176 + 0 * 65536UL;
Wie gesagt da hatte ich mich vertan, das war bei einer kleineren
Frequenz.
Mit 1MHz wird der Fehlen noch größer.
Gruß,
Jan
Jan schrieb:> Und es sind nicht nur einige wenige Zähl-Takte, sondern z.B. bei 50ms> Torzeit 30000 (Timer0) gegen ca. 27000 (Timer1).
"ca." nützt nichts!
Zeig mal die genauen Werte für verschiedene Frequenzen, dann kann man
vielleicht eine Regel und daraus den Grund erkennen.
Welchen Compiler benutzt Du überhaupt?
Peter