- Labornetzteil AliExpress         
Ergebnis 1 bis 10 von 14

Thema: Frequenzmessung per ICP

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Egal wie man es macht, wenn man beim zählen der Überläufe um einen daneben ist, ist der Fehler 2^16 Zyklen. Man sollte es also schon richtig machen - der mögliche Fehler ist zwar selten, aber wenn dann deutlich.
    Wie schon richtig erkannt ist das Problem wenn ICP und Überlauf praktisch gleichzeitig auftreten. Das kann beim ICP Wert von 0 passieren, aber ggf. auch bei einem kleinen ICP Wert bis vielleicht 100, durch die paar Zyklen die es braucht eine Befehl zu Ende auszuführen oder was länger dauert den 3. Interrupt von Timer 2 auszuführen. Wenn beide Interrupts anstehen, wird zuerst der ICP Interrupt ausgeführt, auch wenn eigentlich erst der Überlauf dran wäre. Die IF Anweisung fängt genau diese Fälle ab, ohne einen verbleibenden Fehler. Wenn der ICP Wert klein ist, und gleichzeitig noch ein Overlow Interrupt ansteht heißt das, dass die Flanke kurz nach dem Overflow kam der wartende Overflow Interrupt eigentlich vorher hätte kommen müssen. Der Fall mit ICP=0 ist dabei nicht mal ein Sonderfall, sondern fällt auch in das Schema. Bei der etwas unscharfen Bedingung "ICP klein" hat man recht viel Spielraum: ICP und Overflow fast gleichzeitig passiert halt nur bei sehr kleinen ICP Werten (d.h. in der Regel unter etwa 200, oder wie lang Interrupts maximal gesperrt sind) oder bei sehr großen werten halt ICP so um 65000. Die Grenze mit 128 am High-byte ist da relativ beliebig und unkritisch. Der Fall das das Overflow Ereignis nach dem ICP kommt führt dann zu einen sehr großen ICP Wert, dicht an der oberen Grenze. In dem Fall wird dann der Overflow Interrupt auch nicht vorgezogen.

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    16.04.2011
    Beiträge
    78
    Wow, was für ein Ansturm, vielen Dank für soviel Rückmeldung oO
    Fangen wir mal an...

    Zeile 83-90: Welchen Zweck haben HighByte und LowByte?
    Davon abgesehen ist es falsch den Overflow-Interrupt vorzuziehen. Entweder gab es bis zum Auftreten des Capture-Ereignisses keinen Überlauf und dann darf z nicht inkrementiert werden, oder es kam zeitgleich oder kurz bevor der Capture-Interrupt abgearbeitet wurde zu einem Überlauf und dann machst du nur einen kleinen Fehler. Ziehst du den Capture dagegen vor machst du einen Fehler von bis zu 2^16.
    Genau genommen brauche ich zur Überprüfung lediglich das HighByte - doch im Datenblatt stand, dass erst das Lowbyte ausgelesen werden muss, damit das HighByte ins TEMP geschrieben wird. Die ganze Bedingung habe ich mir aus der Wiki abgeschaut, betrifft wohl einen selteneren Fall, dass ein verpasster Interrupt "nachgeholt" wird. Ist die Grenze mit 128 aus dem Beispiel zu klein gesetzt?

    Zeile 94: Die Flags werden nur gelöscht wenn der zugehörige Interrupt ausgeführt wird. Wenn der Code nicht sowieso falsch wäre, müsstest du das Flag also tatsächlich hier manuell löschen.
    An der Stelle hat das Programm erkannt, dass ein Overflow verpasst wurde - anhand des gesetzten TOV1-Flags und relativ kleiner ICR1H - inkrementiert die Zählvariable und löscht den "bereits ausgeführte" Flag.

    Die Berechnung ICR1 - Startzeit funktioniert nur solange du mit 16-Bit rechnest. So führst du bei einem Überlauf eine ungewollte Subtraktion durch.
    Das und den 2^16 Fehler verstehe ich leider nicht ganz. Die Differenz wird ihrer Größe wegen in einer unsigned long-Variable gesichert. Wäre es besser wenn ich es in der main() berechne?

    Zeile 111, 122-123 : Unnötig
    Dürfte stimmen, habe es nur zur Vorsicht getan.

    Herrschaften, ich verstehe das Optimierungspotenzial, doch ist mir ersteinmal die Quelle der Ungenauigkeit wichtiger - soll ich beim Vorziehen des Interupts die Grenze nicht auf 128, sondern größer setzen? Wo genau seht ihr jetzt das Problem in dem Code?
    Danke nochmal.

    MfG,
    Nik

  3. #3
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die Grenze für den Vergleich des Highbytes ist unkritisch. Wenn das Overflow Interrupt Flag gesetzt ist, kommen für das High-Byte vom ICP eigentlich nur Werte von vielleicht 0,1, 254 oder 255 in Frage. Durch eine Verzögerung bei der Interrupt-verarbeitung, also insbesondere durch einen anderen Interrupt oder anderes sperren von Interrupts hat man an beiden Ende ein paar mögliche Werte, aber die Reserve ist schon groß. Die anderen ISRs müssen nur sicher unter etwa 32000 Zyklen bleiben - das ist normalerweise kein nennenswertes Problem, wenn man nicht gerade in der ISR (von timer2) mehrfach Fließkommazahlen benutzt. Die jetzige ISR vom Timer 2 liegt mehr so bei 50-100 Zyklen.

    Der Code sieht soweit gut aus, und sollte funktionieren. Den Fehler würde ich eher beim Signal suchen. Um dennoch mögliche Fehler besser zu erkennen wäre es besser nicht gleich in eine Frequenz umzurechnen, sondern erst nur die Zeit auszugeben, ggf. auch nicht auf die LEDs, sondern zum PC schicken.

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    16.04.2011
    Beiträge
    78
    Das Signal wurde mit einem Oszilloskop untersucht und ist präzise, hier liegt kaum der gesuchte Fehler vor.
    Ich schreibe mal die ganze Berechnungsroutine in die main() rein, damit kürzt sich die unsigned long- Variable aus der ISR.

    Dann gilt es jetzt die unsigned long Zeit zu analysieren...Was erwartest du da zu sehen? Ich meine, es werden eben größere Sprünge zu sehen sein, doch worauf willst du hinaus?
    Bis 2Khz habe ich es mir eigentlich einfacher vorgestellt mit der Messung...

    MfG,
    Nik

    P.S: mal hypothetisch, was könnten für Fehler an einem TTL-Signal +5V auftreten?

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    37
    Beiträge
    1.225
    Zitat Zitat von Liquidator Beitrag anzeigen
    Das und den 2^16 Fehler verstehe ich leider nicht ganz. Die Differenz wird ihrer Größe wegen in einer unsigned long-Variable gesichert. Wäre es besser wenn ich es in der main() berechne?
    Vergiss den 2^16-Fehler, da lag ich daneben. Danke Stefan, ich hatte die Logik dahinter nicht ganz durchdrungen.

    Was die Subtraktion angeht: Start 0xff00 und Ende 0x00ff entspricht eigentlich einer Zeit von 0x1ff. Wenn du die voneinander subtrahierst bekommst du bei einer 16-Bit-Subtraktion dank abgeschnittener Carry-Bits auch tatsächlich 0x1ff heraus, bei einer 32-Bit-Subtration wäre das Ergebnis aber 0xffff01ff. Lösen lässt sich das Problem, indem du die Subtraktion in Klammern setzt und das Ergebnis auf uint16_t castest.

    Grüße,
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  6. #6
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von markusj Beitrag anzeigen
    Was die Subtraktion angeht: Start 0xff00 und Ende 0x00ff entspricht eigentlich einer Zeit von 0x1ff. Wenn du die voneinander subtrahierst bekommst du bei einer 16-Bit-Subtraktion dank abgeschnittener Carry-Bits auch tatsächlich 0x1ff heraus, bei einer 32-Bit-Subtration wäre das Ergebnis aber 0xffff01ff. Lösen lässt sich das Problem, indem du die Subtraktion in Klammern setzt und das Ergebnis auf uint16_t castest.
    Sorry Markus, aber du liegst wieder daneben.
    Im Prinzip hast du ja Recht mit der 16-Bit-Arithmetik, aber so einfach ist es nur, wenn die Capture-Länge immer unter einer Timer-Periode liegt, man also keine Overflows mitzählen und einrechnen muss. Wenn man aber mitzählt, dann hat man immer bei Start>Ende einen Overflow gezählt, der nicht hinzugerechnet werden darf. Entweder macht man eine zusätzliche Abfrage und korrigiert die gezählten Overflows ggf, oder man beschränkt das Ende-Start eben NICHT auf 16-Bit, dann fällt dieser zusätzliche Overflow nämlich ganz von alleine raus. Nimm doch einfach mal deine eigenen Beispielwerte und rechne damit die Formel im Code komplett aus, und nicht nur teilweise.
    MfG
    Stefan

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    37
    Beiträge
    1.225
    Zitat Zitat von sternst Beitrag anzeigen
    Sorry Markus, aber du liegst wieder daneben.
    Und du hast schon wieder recht, irgendwie war gestern nicht mein Tag ...

    mfG,
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

Ähnliche Themen

  1. hier ein code für niedrige frequenzmessung mit icp
    Von kolisson im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 10
    Letzter Beitrag: 05.11.2009, 22:23
  2. ICP benutzen ?? (länge von pulsen messen
    Von goara im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 9
    Letzter Beitrag: 30.01.2008, 00:13
  3. AVR - Interner Pullup bei ICP-Betrieb ?
    Von WolleMS im Forum Elektronik
    Antworten: 0
    Letzter Beitrag: 04.05.2007, 15:22
  4. mega168 - ICP vs. Port als Ausgang?!
    Von 0tes_Gesetz im Forum C - Programmierung (GCC u.a.)
    Antworten: 16
    Letzter Beitrag: 02.04.2006, 13:41
  5. 8535 und ICP
    Von wheelchair im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 06.03.2006, 16:04

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress