Forum: Mikrocontroller und Digitale Elektronik Frage: Genauigkeit von Internen Zählern


von Johannes L. (johannes_l37)


Lesenswert?

Servus, zur Zeit arbeite ich an einem Programm, das erfasst, wie lange 
der eingang auf High liegt und nun kommt mir als Anfänger eine Frage, 
kann man mit einem internen Zähler überhaupt etwas genaues im us Bereich 
messen?
Ich habe ein Eingangssignal, welches 1ms High ist, das sind meine Werte:


0.962875ms
1.059000ms
0.995000ms
1.058625ms
1.153875ms
0.963125ms
1.024750ms
1.154625ms
0.930000ms
1.056375ms
(Durchnitt von je 10 Messungen)


zwar alles 'ungefähr' richtig, aber kein einziges mal kriege ich 
wirklich 1.00ms heraus :/ liegt das daran das ich schlecht programmiert 
habe oder das es technisch nicht möglich ist? ^^

von Floh (Gast)


Lesenswert?

Die Taktrate deines uC wird nicht 100% stimmen, die 1ms "Referenzzeit" 
wahrscheinlich auch nicht.
Woher kommen die denn?
Außerdem könnte es noch am Programm liegen, wenn unterschiedliche 
Abarbeitungszeiten (beispielsweise durch Abfragen) für den Code 
auftreten.
Da wäre vielleicht das Programm nicht verkehrt zu zeigen.
:-)

von Thomas E. (thomase)


Lesenswert?

Johannes L. schrieb:
> zwar alles 'ungefähr' richtig, aber kein einziges mal kriege ich
> wirklich 1.00ms heraus

Was macht dich denn so sicher, daß dein Eingangssignal tatsächlich exakt 
1  ms lang ist?

Johannes L. schrieb:
> liegt das daran das ich schlecht programmiert

Weiß ja keiner, was du programmiert hast.

Johannes L. schrieb:
> oder das es technisch nicht möglich ist?

Natürlich ist das möglich. 1 ms stellt auch keine große Herausforderung 
dar.

mfg.

von Martin (Gast)


Lesenswert?

Wenn du's genau haben möchtest, mußt du wohl die Capture Hardware für 
den Timer bemühen. Wie auch immer du das jetzt machst ???

von Johannes L. (johannes_l37)


Angehängte Dateien:

Lesenswert?

Thomas Eckmann schrieb:
> Was macht dich denn so sicher, daß dein Eingangssignal tatsächlich exakt
> 1  ms lang ist?
Floh schrieb:
> Die Taktrate deines uC wird nicht 100% stimmen, die 1ms "Referenzzeit"
> wahrscheinlich auch nicht.
> Woher kommen die denn?
Ein Funktionsgenerator und ein Oszilloskop machen mich so sicher das es 
1ms ist :) (hätt ich erwähnen sollen :D)

> Da wäre vielleicht das Programm nicht verkehrt zu zeigen.
> :-)



Zum Programm (siehe Anhang), es bestand ursprünglich aus Main.c ISR.c 
globals.h/.c. Ich hab das ganze jetzt in eine Datei gehängt, da es 
Übersichtlicher ist und das ist mein erstes Programm. ^^

von Kali (Gast)


Lesenswert?

>Ein Funktionsgenerator und ein Oszilloskop machen mich so sicher das es
>1ms ist :) (hätt ich erwähnen sollen :D)

Funktionsgeneratoren und Oszilloskope sind nicht per se genaue Geräte.
Sicherheit gibt Dir die Angabe darüber welche Genauigkeit diese Geräte 
haben (und wann sie das letzte Mal kalibriert worden sind).

von Karl H. (kbuchegg)


Lesenswert?

Gleich die erste Frage:

#define FOSC 8000000UL


interner Oszillator oder Quarz?


In deinem Programm:
Du hast so ziemlich alles gemacht um nur ja schlechte Werte zu bekommen.

* Auswertung durch externen Interrupt
  das macht man so nicht.
  Wenn man externe Zeiten messen will, dann benutzt man den Input 
Capture.

* In der ISR setzt du dir zwar ein Flag, dass die Messung vollständig 
ist, den tatsächlich zu dieser Messung gehörenden Zählerstand holst du 
dir dann aber weiß Gott wann irgendwann einmal später in der 
Hauptschleife.
Der Timer läuft in der Zwischenzeit aber weiter! Ein Programm wird nicht 
in 0-Zeit ausgeführt und das hast du nirgends berücksichtigt. Du tust so 
als hättest du alle Zeit der Welt, dir dann irgendwann einmal das 
Ergebnis abzuholen.


Genau aus diesem Grund gibt es nämlich den Input Capture: Der speichert 
instantan den Zählerstand des Timers in einem Register weg, so dass 
dieser Zählerstand exakt dem Zählerstand entspricht, an dem die Flanke 
daherkam. Nachdem die Hardware diesen Teil, der für die Genauigkeit 
entscheidend ist, für dich erledigt hat, hast du Zeit genug diesen Wert 
dann weiter zu bearbeiten. Im Prinzip ist das wie bei einer Stoppuhr. 
Dein Programm macht folgendes: Dein Helfer schreit "Jetzt". Daraufhin 
drehst du um, gehst gemütlich zur Anzeigewand und liest die Uhr ab, die 
natürlich die ganze Zeit weitergelaufen ist. Das ist aber etwas völlig 
anderes als zb eine Lichtschranke die automatisch die Zwischenzeit 
wegspeichert und "Jetzt" rufst. Mit dieser Weggespeicherten Zwischenzeit 
kannst du gemütlich zur Auswertung gehen, der passiert nichts mehr.

von Johannes L. (johannes_l37)


Lesenswert?

Kali schrieb:
>>Ein Funktionsgenerator und ein Oszilloskop machen mich so sicher das es
>>1ms ist :) (hätt ich erwähnen sollen :D)
>
> Funktionsgeneratoren und Oszilloskope sind nicht per se genaue Geräte.
> Sicherheit gibt Dir die Angabe darüber welche Genauigkeit diese Geräte
> haben (und wann sie das letzte Mal kalibriert worden sind).

Wann es zuletz kalibriert worden ist, weiss ich nicht genau, aber zur 
Genauigkeit, meinst du soetwas?
2 GSa/s sample rate half channel, 1 GSa/s each channel
mal eben über ein Datenblatt geschaut hab

von Kali (Gast)


Lesenswert?

Um noch direkt auf die Frage aus der Überschrift zu antworten:
Die Zähler selbst arbeiten digital, sind also absolut genau.

Ich vermute mal, das Du den internen RC-Oszillator benutzt. Ist das 
richtig?

von Peter II (Gast)


Lesenswert?

ich habe die Register jetzt nicht Kopf, dann es sein das du den 
Vorteiler vom Timer nicht zurücksetzt?

dann hättest du ja schon eine abweichung weil du nicht genau weist do 
der Vorteile steht.

von Kali (Gast)


Lesenswert?

>Wann es zuletz kalibriert worden ist, weiss ich nicht genau, aber zur
>Genauigkeit, meinst du soetwas?
>2 GSa/s sample rate half channel, 1 GSa/s each channel

Nein. Das ist die Angabe über die Abtastrate.

von Kali (Gast)


Lesenswert?

Angaben zur Genauigkeit (irgendeines Gerätes) erkennst Du, neben dem 
Text "Genauigkeit", "Precision", "Deviation" etc. an einem 
Plus-Minus-Zeichen oder einem Prozentzeichen bei der Zahl.

von Johannes L. (johannes_l37)


Lesenswert?

Kali schrieb:
> Um noch direkt auf die Frage aus der Überschrift zu antworten:
> Die Zähler selbst arbeiten digital, sind also absolut genau.
>
> Ich vermute mal, das Du den internen RC-Oszillator benutzt. Ist das
> richtig?

Ja

>ich habe die Register jetzt nicht Kopf, dann es sein das du den
>Vorteiler vom Timer nicht zurücksetzt?

TCCR0B = 0x01;
Kein Prescaller
Edit: Ach du meinst das OverFlow Zähl Register? Bisher noch nicht, jetzt 
schon, ändert allerdings nicht viel an den Werten ^^


1.088375ms
1.121875ms
1.122250ms
1.090250ms
1.120875ms
1.123125ms
1.154375ms
0.960125ms
1.024625ms
1.089875ms

von Kali (Gast)


Lesenswert?

>> Ich vermute mal, das Du den internen RC-Oszillator benutzt. Ist das
>> richtig?

>Ja

Na dann... Schau mal in das Datenblatt. Die Genauigkeit ist eher 
schlecht. Bei einem Mega162 ist die etwa 10% bei 3V und 20°C.
Die erkennbaren 15% Abweichung sind, etwa im Verein mit der 
Ungenauigkeit des Generators und des Oszilloskops also in etwa richtig.

von Peter II (Gast)


Lesenswert?

Kali schrieb:
> Na dann... Schau mal in das Datenblatt. Die Genauigkeit ist eher
> schlecht. Bei einem Mega162 ist die etwa 10% bei 3V und 20°C.
> Die erkennbaren 15% Abweichung sind, etwa im Verein mit der
> Ungenauigkeit des Generators und des Oszilloskops also in etwa richtig.

sie schrankt aber nicht spontan, sonder anhängig von der Spannung und 
der Temperatur. Wenn er mehere Messungen in eim paar sekunden macht, 
dann ist der RC in dieser zeit recht konstant (aber nicht zwingend 
genau!)

von Karl H. (kbuchegg)


Lesenswert?

Johannes L. schrieb:

> Edit: Ach du meinst das OverFlow Zähl Register? Bisher noch nicht, jetzt
> schon, ändert allerdings nicht viel an den Werten ^^
>

Schau dir nochmal meinen Beitrag von weiter oben an.


Als Erstabhilfe speicherst du dir hier

ISR(INT0_vect)
{
  if(Aufoderab==0)
  {
    TIMSK0 = 0x01;
    EICRA = 0x02;
    Aufoderab=1;
  }
  else
  {
    TIMSK0 = 0x00;
    EICRA = 0x03;
    Aufoderab=0;
    fertig=1;

  }
}




als allererstes sofort bei Betreten der ISR den aktuellen Zählerstand 
TCNT0 samt Overflowzählung in globale Variablen weg und benutzt diese 
Werte dann in der Hauptschleife.


Auf lange Sicht gesehen lege ich dir aber den Input Capture Modus nahe. 
Denn genau für solche Fälle wie deinen ist der nämlich eigentlich 
gedacht.

von Kali (Gast)


Lesenswert?

>sie schwankt aber nicht spontan, sonder anhängig von der Spannung und
>der Temperatur. Wenn er mehere Messungen in eim paar sekunden macht,
>dann ist der RC in dieser zeit recht konstant (aber nicht zwingend
>genau!)

Das ist richtig. Danke für den Hinweis, Peter.

Die kurzzeitige Schwankung um ca. 14% ist damit nicht erklärt.
Es bleibt also abzuwarten was die Verbesserung der Software und die 
Klärung der Genauigkeit der Messgeräte ergibt.

von Johannes L. (johannes_l37)


Lesenswert?

Kali schrieb:
>>> Ich vermute mal, das Du den internen RC-Oszillator benutzt. Ist das
>>> richtig?
>
>>Ja
>
> Na dann... Schau mal in das Datenblatt. Die Genauigkeit ist eher
> schlecht. Bei einem Mega162 ist die etwa 10% bei 3V und 20°C.
> Die erkennbaren 15% Abweichung sind, etwa im Verein mit der
> Ungenauigkeit des Generators und des Oszilloskops also in etwa richtig.

Nach "langem" durchlesen in der Doku:

Factory calibration   8.0MHz      3V     25°C          ±10%

von Andreas K. (derandi)


Lesenswert?

Der soll das mal auf Input-Capture-Interrupt umbauen.

von willi (Gast)


Lesenswert?

Johannes L. schrieb:
> Nach "langem" durchlesen in der Doku:

Du solltest besser lesen, was Karl Heinz Buchegger geschrieben hat! Ist 
das denn so schwer?

von Karl H. (kbuchegg)


Lesenswert?

Johannes L. schrieb:

> Nach "langem" durchlesen in der Doku:
>
> Factory calibration   8.0MHz      3V     25°C          ±10%

Die Frage ist, wie schnell der Oszillator tatsächlich seine Frequenz 
ändert, wenn Spannung und Temperatur konstant bleiben. Der Text 
suggeriert ja eher, dass die tatsächliche Taktfrequenz bei 25° bei +-10% 
rund um 8Mhz liegt. Ändert sich die Temp, dann ist der Wert ein anderer, 
kein Thema. Aber wenn sich innerhalb von ein paar Sekunden am Chip 
nichts ändert, sollte er eigentlich seine Frequenz (egal welche das 
jetzt im 10% Bereich ist) nicht wahnsinnig stark verändern.

von Johannes L. (johannes_l37)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Gleich die erste Frage:
>
> #define FOSC 8000000UL
>
>
> interner Oszillator oder Quarz?
>
>
> In deinem Programm:
> Du hast so ziemlich alles gemacht um nur ja schlechte Werte zu bekommen.
>
> * Auswertung durch externen Interrupt
>   das macht man so nicht.
>   Wenn man externe Zeiten messen will, dann benutzt man den Input
> Capture.
>
Noch nicht von gehört aber mal schaun

> * In der ISR setzt du dir zwar ein Flag, dass die Messung vollständig
> ist, den tatsächlich zu dieser Messung gehörenden Zählerstand holst du
> dir dann aber weiß Gott wann irgendwann einmal später in der
> Hauptschleife.
Sobald die Messung Fertig ist, kann er in  die While Schleife, in der 
Sofort dann auch die Interrupts deaktiviert werden, aber ich glaube das 
cli(); setze ich dann mal ans Ende vom (else) vom int0 vect, (oder wie 
das bei Int.Capt. dann heißt)


> Genau aus diesem Grund gibt es nämlich den Input Capture.

Unterm Strich: Lernen wie man Inp. Capt. benutzt und anwenden :), danke 
soweit ersteinmal :) ich geh dann mal im Datenblatt schmöckern ^^

Schuldige das ich deinen Beitrag erst jetzt gelesen habe, unter den 
Beiträgen der ganzen anderen habe ich den deinen schlichtweg nicht 
gesehen.

von Karl H. (kbuchegg)


Lesenswert?

Andreas K. schrieb:
> Der soll das mal auf Input-Capture-Interrupt umbauen.


Oder wenigstens den Zählerstand im Interrupt wegschreiben.

Mit SChaudern hab ich auch einen _delay_ms( 1000 ) im Programm gefunden, 
der unter INterrupt-Sperre abläuft. D.h der erste Interrupt danach 
findet irgendwann statt, aber sicher nicht zum Zeitpunkt der Flanke.

So gesehen sind seine Werte eigentlich erstaunlich genau und nur noch 
durch die Mittelwertbildung über 10 Messungen zu erklären.

von Kali (Gast)


Lesenswert?

>Aber wenn sich innerhalb von ein paar Sekunden am Chip
>nichts ändert, sollte er eigentlich seine Frequenz (egal welche das
>jetzt im 10% Bereich ist) nicht wahnsinnig stark verändern.

Ja. Das hat Peter ja auch schon bemerkt. Mein Fehler, das ich die 
Genauigkeit auch auf die Kurzzeitgenauigkeit übertragen habe.


Ich habe das jetzt nicht zuende durchgedacht, aber dieser lange Code in 
main im Falle von fertig==1 scheint mir potentiell unvorhersagbare 
Zählerstände produzieren zu können, da nicht klar ist, ob Interrupts 
anstehen wenn der globale Interruptflag wieder gelöscht wird.

von Kali (Gast)


Lesenswert?

Die sofortige Speicherung des Zählerstandes im Interrupt und das 
unterlassen der Interruptsperre sollte eine deutliche Verbesserung 
bringen. (Wozu war das eigentlich gut)?

Am besten wäre natürlich, wie schon erwähnt, der Capture-Modus.

von Karl H. (kbuchegg)


Lesenswert?

Du darfst deine Interrupts nicht sperren! Und wenn du das musst, dann
muss die Sperre so kurz wie nur irgendwie möglich sein. Die Interrupts
sind dein Messmittel, sie starten und stoppen deine Messung. Sperrst du
die Interrupts, dann musst du ach in der Zwischenzeit aufgelaufene
Interrupt Requests wieder löschen. Denn ansonsten wird der zur Flanke
gehörende Interrupt verzögert ausgeführt. Du drückst quasi den
Startknopf deiner Stoppuhr irgendwann, weil du beim Start des Läufers zu
beschäftigt warst und nicht hingesehen hast.

von Stunden später (Gast)


Lesenswert?

Martin schrieb:
> Wenn du's genau haben möchtest, mußt du wohl die Capture Hardware für
> den Timer bemühen. Wie auch immer du das jetzt machst ???

Andreas K. schrieb:
> Der soll das mal auf Input-Capture-Interrupt umbauen.

von Peter D. (peda)


Lesenswert?

Johannes L. schrieb:
>> Ich vermute mal, das Du den internen RC-Oszillator benutzt. Ist das
>> richtig?
>
> Ja

Taugt gerade mal als Eieruhr, aber zu mehr nicht.

Programmier mal den CKOUT-Pin und dann schau Dir den Jitter auf dem Oszi 
an.


Peter

von Matthias (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Programmier mal den CKOUT-Pin und dann schau Dir den Jitter auf dem Oszi
> an.

Und jetzt stell dir vor, dass du den gleichen Jitter auf dem 1 kHz 
Signal hast. Da mittelt der sich schon kräftig weg.

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.