Hallo zusammen,
nach kräftiger Unterstützung dieses Forums klappt meine Frequenzmessung
mit einem ATmega32 und einem Frequenzgenerator(als Testsignal) ab ca. 20
Hz einwandfrei. Die Werte werden per UART übertragen. Doch gehe ich
niedriger, so erhalte ich willkürliche Werte. Ich weiß nicht, woran es
liegen kann. Die Frequenzen werden nochmal zusätzlich mit einem
Oszilloskop überprüft.
Könnt ihr mir vielleicht weiter helfen?
Ich benutze eine interne Frequenz von 8MHz, Timer1 mit 125kHz, Input
Capture Unit reagiert auf steigende Flanke vom Analog Komparator. Dieser
hat eine Referenzspannung von einigen mV. (Ich habe mehrere
Oszillator-Frequenzen und Taktefrequenzen des Timer1 ausprobiert und
immer bekomme ich das selbe Fehlerbild)
Im Anhang befindet sich der komplette Code.
Hier ist der Ausschnitt aus dem Quellcode: (Nachträglich werde ich noch
eine Mittelung des Wertes einbauen)
while(1)
{
TCNT1 = 0; //Setze Zählerstand T1 auf 0
ICR1=0; //Setze Input Capture Register auf 0
TIFR |= (1<<ICF1); // Input Capture Flag löschen
while (!(TIFR & 1<<ICF1)) //Warte bis nächste positive Flanke
{
if (TIFR & 1<<TOV1) //Ergibt sich innerhalb von 1
Timerüberlauf von T1 keine positive Flanke,
{ // so ist v=0 km/h
UART_SendByte('v');
UART_SendByte(0);
TIFR |= (1<<TOV1); //Timerüberlauf = 0 setzen
}
}
TCNT1 = 0; //Setze Zählerstand T1 auf 0
ICR1=0; //Setze Input Capture Register auf 0
TIFR |= (1<<ICF1); // Input Capture Flag löschen
while (!(TIFR & 1<<ICF1)) //Warte bis nächste positive Flanke
{
if (TIFR & 1<<TOV1) //Ergibt sich innerhalb von 1
Timerüberlauf von T1 keine positive Flanke,
{ //so ist v=0 km/h
UART_SendByte('v');
UART_SendByte(0);
TIFR |= (1<<TOV1);
}
}
Periode = ICR1; // Lese Wert der nächsten positiven Flanke
//Bestimmung der Geschwindigkeit
Frequenz = (125000.0 / (double)Periode);
Die Auswertung der ICP in der main-Schleife verstehe nicht nicht so ganz, ich würde das über einen Interrupt lösen. Du überprüfst zwar auf einen Überlauf des Timers, berechnest am Ende trotzdem immer die Frequenz, die im Falle des Überlaufes nicht stimmt. Hast du mal ausgerechnet was die niedrigste Frequenz ist die du noch messen kannst, ohne das der Timer überläuft?
Warum wertest du den Timerüberlauf nicht einfach mit dem passenden Interrupt aus?
Gast
#2412842
Wenn man schon input capture nutzt, dann sollte man die Differenz von 2 ICP Events nutzen, nicht bei der ersten Flanke nur dem Timer auf 0 setzen und dann messen. Der Fehler könnte durch die Qualität des Einagnsgsignals verursacht sein. Gibt es das Problem denn auch bei einem Digitalen Eingangssignal ?
Erstmal Danke für die schnellen Antworten!!! André Althaus schrieb: > Die Auswertung der ICP in der main-Schleife verstehe nicht nicht so > ganz, ich würde das über einen Interrupt lösen. > Du überprüfst zwar auf einen Überlauf des Timers, berechnest am Ende > trotzdem immer die Frequenz, die im Falle des Überlaufes nicht stimmt. Der Überlauf des Timer findet nur statt, wenn kein Signal oder eine zu kleine Frequenz anliegt. Wenn kein Signal anliegt, klappt die Auswertung ohne Probleme. Wird die Frequenz zu klein, bekomme ich auch diese willkürlichen Werte. André Althaus schrieb: > Hast du mal ausgerechnet was die niedrigste Frequenz ist die du noch > messen kannst, ohne das der Timer überläuft? Die niedrigste Frequenz, welche ohne Fehler angezeigt wird liegt ca. bei 20Hz. An der Stelle ist der Timer gerade mal 6250 also weit vom Überlauf entfernt. Ich denke, dass es nichts mit dem Überlauf zutun hat, denn der Fehler tritt weitaus früher auf. Andreas K. schrieb: > Warum wertest du den Timerüberlauf nicht einfach mit dem passenden > Interrupt aus? Weil der Interrupt nicht funktioniert hatte. Hab dann einfach wieder die klassische Variante gewählt, um erst einmal den 1. Fehler zu beheben. Danach kann ich dann den Quellcode etwas übersichtlicher gestalten. Ulrich schrieb: > Wenn man schon input capture nutzt, dann sollte man die Differenz von 2 > ICP Events nutzen, nicht bei der ersten Flanke nur dem Timer auf 0 > setzen und dann messen. Das könnte ich versuchen, aber meinst du, der Fehler sei dadurch behoben? Ob ich jetz die Frequenz aus einem Wert berechne oder aus der Differenz zweier Werte, macht doch keinen Unterschied. Ulrich schrieb: > Der Fehler könnte durch die Qualität des Einagnsgsignals verursacht > sein. Gibt es das Problem denn auch bei einem Digitalen Eingangssignal > ? Wenn ich als Eingangssignal ein Rechtecksignal auswähle, dann tritt der Fehler genauso auf. Auf meinem Oszilloskop ist es ein reiner Sinus bzw. Rechteck.
Gast
#2413089
Sascha M. schrieb: > An der Stelle ist der Timer gerade mal 6250 also weit vom Überlauf > entfernt. Bist du dir sicher? Wenn man die 6250 mal 10 nimmt kommt das verdächtig nahe an 65536 heran also einen 16 Bit Überlauf. Was misst du denn? Ständig wechselnde Frequenzen, oder systematisch falsche Werte also immer das gleiche falsche Ergebnis bei einer konstanten Frequenz?
Gast
#2413111
UR Schmitt schrieb: > Bist du dir sicher? Wenn man die 6250 mal 10 nimmt kommt das verdächtig > nahe an 65536 heran also einen 16 Bit Überlauf. Bei einer Timerfrequenz von 125kHz (Pro Takt 8us) und einer zu messenden Periodendauer von 20Hz = 50ms ergibt es einen Counterwert von 6250. UR Schmitt schrieb: > Was misst du denn? Ständig wechselnde Frequenzen, oder systematisch > falsche Werte also immer das gleiche falsche Ergebnis bei einer > konstanten Frequenz? Ständig wechselnde Werte. Der Wert springt ständig zwischen Verschiedenen Werten hin und her...
Gast
#2413117
sashm schrieb: > Ständig wechselnde Werte. Der Wert springt ständig zwischen > Verschiedenen Werten hin und her... Dann könnte es ein Hardwareproblem sein. Vieleicht fängt sich deine Schaltung Netzbrumm oder Netzstörungen ein. Bei höheren Frequenzen merkst du das nicht weil die Messung schnell genug erfolgt.
Gast
#2413123
Blöde Idee: Du hast aber schon ausgeshlossen daß dein Testgenerator bei den Frequenzen stabil ist? Nicht daß der da ein Problem hat.
UR Schmitt schrieb: > Dann könnte es ein Hardwareproblem sein. Vieleicht fängt sich deine > Schaltung Netzbrumm oder Netzstörungen ein. Bei höheren Frequenzen > merkst du das nicht weil die Messung schnell genug erfolgt. Könnte möglich sein. Ich habe am Eingangspin des Atmegas mein Oszilloskop angeschlossen und sehe keine Störungen oder sonstige Verzerrung des Sinussignals. Könnte ich das mit einem Trenntrafo lösen? UR Schmitt schrieb: > Blöde Idee: > Du hast aber schon ausgeshlossen daß dein Testgenerator bei den > Frequenzen stabil ist? Nicht daß der da ein Problem hat. Ideen sind doch nie blöd :) Das Bild auf dem Oszilloskop sieht sauber aus. Kann dort keine Verzerrungen feststellen... das wundert mich deshalb wirklich...
Gast
#2413151
du sprichst von Sinussignal....schalte um auf Rechteck; was passiert ?
Digi Tal schrieb: > du sprichst von Sinussignal....schalte um auf Rechteck; was passiert ? Der gleiche Fehler tritt auf. Ich weiß wirklich nicht, woran es liegen könnte!
Dann lass dir doch mal alle Werte ausgeben. Fang bei ICR1 an. (Seltsame Ausgabe hast du da. Da werden Buchstaben gesendet und hinten nach die Zahlen in Binärform. Hast du am anderen Ende der UART ein Spezialprogramm hängen? Wenn ja, dann würd ich erst mal eine vernünftige ASCII Ausgabe machen und da ganz einfach ein Terminal drannhängen. Dann kann man auch beliebige Ausgaben machen ohne am PC Programm rumdoktoren zu müssen)
Karl Heinz Buchegger schrieb: > Dann lass dir doch mal alle Werte ausgeben. > Fang bei ICR1 an. > > (Seltsame Ausgabe hast du da. Da werden Buchstaben gesendet und hinten > nach die Zahlen in Binärform. Hast du am anderen Ende der UART ein > Spezialprogramm hängen? Wenn ja, dann würd ich erst mal eine vernünftige > ASCII Ausgabe machen und da ganz einfach ein Terminal drannhängen. Dann > kann man auch beliebige Ausgaben machen ohne am PC Programm rumdoktoren > zu müssen) Ok, ich werde es mal mit allen Werten ausprobieren! Gibt es da eine elegante Lösung zum Auslesen der Register? Ich benutze ein Terminalprogramm, welches mir die Daten als Binär, Hex und Dezimal anzeigt: H-Term. Die Buchstaben hab ich nur zum Testen eingefügt, da ich am Ende die Geschwindigkeit erhalten möchte, habe ich das Formelzeichen v gewählt.
Sash uM schrieb: > Ok, ich werde es mal mit allen Werten ausprobieren! Gibt es da eine > elegante Lösung zum Auslesen der Register? Du brauchst nicht alle Werte, sondern nur die Register die du auch verwendest. Sind ja bei dir nicht allzuviele. > Ich benutze ein Terminalprogramm, welches mir die Daten als Binär, Hex > und Dezimal anzeigt: H-Term. Dann mach dir doch als erstes mal vernünftige Ausgabefunktionen! Nur mit einem UART_SendByte wirst du auf Dauer nicht weit kommen.
1 | |
2 | |
3 | |
4 | |
5 | |
und schon kannst du einen String ausgeben
1 | |
2 | |
3 | |
dann noch welche für Zahlen
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
und schon bist du bereit, deine Register nach Herzenslust auszugeben
1 | |
2 | |
3 | |
4 | |
5 | |
und zwar ohne dass du ständig Bytes im HTerm entschlüsseln musst. UNd wenn dir das immer noch zu mühsam ist, dann gibt es eben wieder eine neue Hilfsfunktion
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
und schon ist es kein Thema mehr die Werte von TCNT1, ICR1 und meinetwegen auch noch PIND auszugeben
1 | |
2 | |
3 | |
4 | |
5 | |
Lass dir die Dinge als Text hinschreiben (OK, der Text "Fehler: Ueberlauf\n" ist ein bischen lang, da dauert dann die Übertragung schon seine Zeit, so dass du das Timing deines Programmes eventuell durcheinander bringst). Dann steht auf deinem Terminal schwarz auf weiss dort
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
und das ist dann schon etwas ganz anderes als wenn man Hex-Bytes mühsam entschlüsseln muss. Ich werd nie verstehen, warum es so schwer ist, sich in ein paar Minuten ein paar Hilfsfunktionen zu machen. Statt dessen wird da lieber mit Krücken rumhantiert. OK. Zurück zum Problem: Ziel ist es heruaszufinden, ob die Werte in ICR1 schon springen oder nicht und wenn ja um wieviel sie springen.
Gast
#2413543
Sash uM schrieb: > Dieser hat eine Referenzspannung von einigen mV. Wenn der Signalgenerator ein positives Signal gegen Masse liefert, dann würde ich AIN0/PB2 auf halbe Signalspannung setzen. Zum Testen des Codes den AC abschalten und über ICP1/PD6 mit einem Rechtecksignal reingehen.
Gast
#2413579
Dürfte zwar nicht der eigentliche Fehler sein, ist aber dennoch falsch:
1 | |
Das veroderte Zurückschreiben in ein Flag-Register löscht nicht nur das gewünschte Bit, sondern alle die gesetzt waren. Richtig ist's so:
1 | |
Gast
#2413676
nicht Frequenz sondern Periode messen
Karl Heinz Buchegger schrieb: > Dann mach dir doch als erstes mal vernünftige Ausgabefunktionen! > Nur mit einem UART_SendByte wirst du auf Dauer nicht weit kommen. Wow, großen Dank für die ganzen Hilfefunktionen. Ich werde mich dann schnellstmöglich darum kümmern. MWS schrieb: > Zum Testen des Codes den AC abschalten und über ICP1/PD6 mit einem > Rechtecksignal reingehen. Das ist auch eine gute Idee. Danke vielmals. MWS schrieb: > Dürfte zwar nicht der eigentliche Fehler sein, ist aber dennoch falsch:TIFR |= (1<<ICF1);Das veroderte Zurückschreiben in ein Flag-Register löscht nicht nur das > gewünschte Bit, sondern alle die gesetzt waren. > Richtig ist's so:TIFR = (1<<ICF1); Oh, das hatte ich nicht gewusst. Ich bin davon ausgegangen, dass nur das Bit ICF1 gelöscht wird. Im Datenblatt stand beschrieben, dass zum Zurücksetzen des Input Capture Flag das Bit ICF1 gesetzt werden muss. Aber mit dem Befehl REGISTER1 |= (1<<BIT1) wird doch nur das Bit1 im Register1 gesetzt, oder?
Sash uM schrieb: > Aber mit dem Befehl > REGISTER1 |= (1<<BIT1) > wird doch nur das Bit1 im Register1 gesetzt, oder? Da diese Schreibweise identisch ist zu REGISTER1 = REGISTER1 | (1<<BIT1) werden daher dann auch alle anderen Bits erneut als 1 in das Register geschrieben, die auch vorher schon 1 waren. Und da in diesem Register alle Bits auf Neubeschreiben mit 1 mit einem Zurücksetzen reagieren, setzt REGISTER1 |= (1<<BIT1) alle bereits gesetzten Bits zurück.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.