Hallo, habe im Internet eine Schaltung für einen LCF Meter entdeckt,
leider ist es schlecht dokumentiert und nun wollte ich mal ein eigenes
Projekt erstellen. Leider habe ich am Anfang schon ein
Verständnisproblem. Habe mit einem Atmega8 den Timer 1 im CTC Modus
einen 1s Takt erzeugt, mit dem Timer0 möchte ich die Frequenz erfassen.
Habe als Referenz einen 4MHz Quarzoszillator, die Schaltung misst aber
3.97xxxxxMhz. Warum die Abweichung, da der Oszillator auf 500 ppm genau
sein soll. Zweitens habe ich eine Frage zur Genauigkeit. Bei der
Addition von doble und int kommt ein falscher Wert heraus. Ich addiere
zur Frequenz testweise 0.05 dazu, aber statt z.B. 3975123.05 kommt
3975123.00 heraus. Warum?
Anbei der Code. Wäre toll wenn mir jemand eine Erklärung und Tipps geben
könnte, da ich noch sehr am Anfang stehe, danke.
Hier der Code:
pit schrieb:> Bei der> Addition von doble und int kommt ein falscher Wert heraus. Ich addiere> zur Frequenz testweise 0.05 dazu, aber statt z.B. 3975123.05 kommt> 3975123.00 heraus. Warum?
Versuch mal:
test2=(double)frequenz+test2;
pit schrieb:> Ich addiere> zur Frequenz testweise 0.05 dazu, aber statt z.B. 3975123.05 kommt> 3975123.00 heraus. Warum?
double ist bei Atmel nur float, also nur 7-8 echte stellen. Damit kann
das nicht genauer rechnen.
http://de.wikipedia.org/wiki/Einfache_Genauigkeit
Die gemessene Frequenz stimmt nicht ganz, weil die Berechnung der
Frequenz und Ausgabe einige Zeit benötigt. Damit geht eine Teil der 1 s
Messzeit zum Zählen verloren.
Umgehen ließe sich dieses Problem, indem der Zähler nicht zurück gesetzt
wird, sondern die Differenz zum letzten Zählerstand berechnet wird.
Ein zusätzliches Problem ergibt sich dadurch, dass der Zähler für die
Überläufe von Timer0 und das Auslesen von Timer0 nicht unbedingt
synchron sind. Hier gibt es 2 mögliche Lösungen:
Der erste wäre den Timer0 an zu halten und erst dann die Werte
auszulesen, incl. eines ggf. noch ausstehenden Interrupts. Die dabei
verlorene Zeit muss man berücksichtigen, etwa indem man Timer 1 neu
programmiert.
Alternativ kann man auch den laufenden Timer auslesen, muss dann aber
aufpassen ob ggf. eine Interrupt für den Überlauf noch aussteht. Das
geht, ist aber nicht ganz trivial.
Schließlich gäbe es für eher niedrige Frequenzen (z.B. 50 kHz) noch die
Möglichkeit eine Reziproke Zeitmessung mit Hilfe der ICP Funktion zu
nutzen. Das gibt etwas mehr Auflösung, bzw. eine schnellere Messung. Die
Schwierigkeiten (und Lösungen dazu) bei der Software sind aber fast die
gleichen.
Ich zeig Dir ein Beispiel, was Du vielleicht als Referenz nehmen kannst,
und was auch funktioniert:
http://www.mino-elektronik.de/fmeter/fm_software.htm#bsp1
Es ist zwar für den ATmega88 geschrieben, sollte aber auch auf dem
ATmega8 laufen. Die LCD-Ausgabe kannst Du ja sicher an Deine Hardware
anpassen.
Detlef Kunz schrieb:> pit schrieb:>> Bei der>> Addition von doble und int kommt ein falscher Wert heraus. Ich addiere>> zur Frequenz testweise 0.05 dazu, aber statt z.B. 3975123.05 kommt>> 3975123.00 heraus. Warum?>> Versuch mal:> test2=(double)frequenz+test2;
Danke, aber nein, daran liegt es nicht.
Gruß Pit
Peter II schrieb:> pit schrieb:>> Ich addiere>> zur Frequenz testweise 0.05 dazu, aber statt z.B. 3975123.05 kommt>> 3975123.00 heraus. Warum?>> double ist bei Atmel nur float, also nur 7-8 echte stellen. Damit kann> das nicht genauer rechnen.>> http://de.wikipedia.org/wiki/Einfache_Genauigkeit
Danke für den Tip, scheint daran zu liegen, das nur mit 7-8 Stellen
gerechnet wird.
Gruß Pit
Ulrich H. schrieb:> Die gemessene Frequenz stimmt nicht ganz, weil die Berechnung der> Frequenz und Ausgabe einige Zeit benötigt. Damit geht eine Teil der 1 s> Messzeit zum Zählen verloren.> Umgehen ließe sich dieses Problem, indem der Zähler nicht zurück gesetzt> wird, sondern die Differenz zum letzten Zählerstand berechnet wird.>> Ein zusätzliches Problem ergibt sich dadurch, dass der Zähler für die> Überläufe von Timer0 und das Auslesen von Timer0 nicht unbedingt> synchron sind. Hier gibt es 2 mögliche Lösungen:> Der erste wäre den Timer0 an zu halten und erst dann die Werte> auszulesen, incl. eines ggf. noch ausstehenden Interrupts. Die dabei> verlorene Zeit muss man berücksichtigen, etwa indem man Timer 1 neu> programmiert.> Alternativ kann man auch den laufenden Timer auslesen, muss dann aber> aufpassen ob ggf. eine Interrupt für den Überlauf noch aussteht. Das> geht, ist aber nicht ganz trivial.>> Schließlich gäbe es für eher niedrige Frequenzen (z.B. 50 kHz) noch die> Möglichkeit eine Reziproke Zeitmessung mit Hilfe der ICP Funktion zu> nutzen. Das gibt etwas mehr Auflösung, bzw. eine schnellere Messung. Die> Schwierigkeiten (und Lösungen dazu) bei der Software sind aber fast die> gleichen.
Hi Ulrich,
das scheint mir plausibel. Muss mir dann mal Gedanken machn wie ich das
Programm umschreiebe um die Genauigkeit zu steigern. Gibt es eine
Möglichkeit herauszufinden wieviele Takte "verloren" gehen für die
Berechnungen? Kann man das mit dem Simulator herausfinden? Oder ist das
bei Timerbenutzung nicht möglich.
P.S. Kennt jemand einen gutes Tutorial im Umgang mit dem Simulator?
Gruß Pit
m.n. schrieb:> Ich zeig Dir ein Beispiel, was Du vielleicht als Referenz nehmen kannst,> und was auch funktioniert:> http://www.mino-elektronik.de/fmeter/fm_software.htm#bsp1>> Es ist zwar für den ATmega88 geschrieben, sollte aber auch auf dem> ATmega8 laufen. Die LCD-Ausgabe kannst Du ja sicher an Deine Hardware> anpassen.
Hi,
danke für den Link, werde mal schauen ob mir das weierhilft.
Gruß Pit
Wie lange ein Stück Code braucht, kann man im Simulator recht gut
ansehen. Allerdings kann sich die Laufzeit durch eine andere
Compiler-version oder ggf. auch Änderungen im Code, die zu anderer
Optimierung führen, ändern.
Der bessere Weg ist es die Abhängigkeit von der Laufzeit weitgehend zu
vermeiden. Dafür gibt es verschiedene Möglichkeiten, z.B. am Anfang und
Ende der Laufzeit den Timer mit dem gleichen Code auslesen und die Zahl
durch Differenzbildung zu bestimmen. Wenn man sich mit den Latenzzeiten
für den Interrupt richtig mühe gibt kriegt man das auch auf den Zyklus
genau hin, ist aber nicht so einfach, weil beim Aufruf der ISR
Verzögerungen vorkommen können. Alternativ kann man auch so ähnlich mit
dem selben code Teil den externen Eingang freigeben bzw. blockieren.
Der bessere Weg ist aber die Nutzung der ICP Funktion für eine Reciproke
Frequenzmessung. Das ist wohl auch einfacher als die klassische Zählung
mit exakter Torzeit in Software.
Ulrich H. schrieb:> Wie lange ein Stück Code braucht, kann man im Simulator recht gut> ansehen. Allerdings kann sich die Laufzeit durch eine andere> Compiler-version oder ggf. auch Änderungen im Code, die zu anderer> Optimierung führen, ändern.>> Der bessere Weg ist es die Abhängigkeit von der Laufzeit weitgehend zu> vermeiden. Dafür gibt es verschiedene Möglichkeiten, z.B. am Anfang und> Ende der Laufzeit den Timer mit dem gleichen Code auslesen und die Zahl> durch Differenzbildung zu bestimmen. Wenn man sich mit den Latenzzeiten> für den Interrupt richtig mühe gibt kriegt man das auch auf den Zyklus> genau hin, ist aber nicht so einfach, weil beim Aufruf der ISR> Verzögerungen vorkommen können. Alternativ kann man auch so ähnlich mit> dem selben code Teil den externen Eingang freigeben bzw. blockieren.>> Der bessere Weg ist aber die Nutzung der ICP Funktion für eine Reciproke> Frequenzmessung. Das ist wohl auch einfacher als die klassische Zählung> mit exakter Torzeit in Software.
Hi Ulrich,
danke schon mal für die Infos. Ich werde mich noch mal etwas einlesen
müssen in Sachen Timer, Interrupts und Simulator. Vor Allem die ICP
Funktion werde ich mir mal ansehen.
Ich bin aber schon mal ganz froh, die im Internet entdeckte Schaltung
von einem 8515 auf einen Atmega8 umgeschrieben und geändert zu haben.
War einfach mal die Herausforderung die vielen ungenutzten Eingänge beim
8515 zu optimieren. Die Schaltung funktioniert schon mal fürs Messen von
Frequenzen, kleinen Kondensatoren, sowie Spulen und über die "Tau
Messung" auch von großen Elkos.
Die Ungenauigkeiten muss ich nun über Programmänderungen optimieren, da
ich aber einen ISP Anschluß mit eingebaut habe, kann ich neue Programme
gut testen. Auf jeden Fall lernt man imens durch so ein Projekt.
Gruß Pit