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? ^^
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. :-)
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.
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 ???
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. ^^
>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).
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.
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
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?
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.
>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.
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.
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
>> 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.
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!)
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.
>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.
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%
Johannes L. schrieb: > Nach "langem" durchlesen in der Doku: Du solltest besser lesen, was Karl Heinz Buchegger geschrieben hat! Ist das denn so schwer?
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.
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.
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.
>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.
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.
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.
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.