Forum: Projekte & Code Input Capture Pin (ICP) auslesen ( Frequenz messen)


von Karl N. (karlnapf)


Angehängte Dateien:

Lesenswert?

Im Anhang ein C-Code um den Input Capture Pin auszulesen, den ich mit 
reichlich Unterstützung aus dem Forum geschrieben habe.
Hab einen Atmega16 mit 4MHz externem Quarz benutzt.
Sicherlich noch optimierungsfähig aber ein Anfang.
Gruss

von Karl H. (kbuchegg)


Lesenswert?

Schau den Code noch mal durch.

Was macht der delay.h da drinnen.

Was ist mit den LCD Funktionen? Die hat nicht
jeder.

Namen wie ic_zp_A sind nicht wirklich aussagekräftig.
Was macht die Variable wirklich?

Selbiges für i. i als Variablenname wird normalerweise
für Dinge mit sehr geringen Scope (also zb eine
for-Schleife benutzt). Als Name für eine globale
Variable ist es aber unbrauchbar.

Über den double da drinnen könnte man auch
noch debattieren.

Auch wäre eine kleine Kommentierung, wie das Teil
funktioniert, worauf es basiert angebracht.


Veröffentlichter Code ist dein Aushängeschild gegenüber
der Welt!

von Karl N. (karlnapf)


Lesenswert?

Ich hab ja dazu geschrieben, dass es sich um einen keinenfalls perfekten 
Code handelt.
Wollte damit nur denjenigen helfen, die ein ähnliches Problem haben und 
einen Einstieg suchen.
Mir persönlich ist es immer lieber wenn ich einen Code vor mir habe der 
nicht perfekt durchprogrammiert ist, dafür übersichtlicher.
Außerdem ist es doch unmöglich was zu schreiben, das man dann 1 zu 1 
übernehmen kann.
Die Variablen und die Kommentierung sind sicherlich verbesserungsfähig.

Und auf meinen Ruf als "großer" Programmierer leg ich nicht so viel Wert 
;-)

von Rahul, der Trollige (Gast)


Lesenswert?

>Wollte damit nur denjenigen helfen, die ein ähnliches Problem haben und
>einen Einstieg suchen.
>Und auf meinen Ruf als "großer" Programmierer leg ich nicht so viel Wert

Ist aber nicht schön, wenn diejenigen dann in fiese Fallen tappen, weil 
sie den Code einfach übernehmen.

von Karl H. (kbuchegg)


Lesenswert?

> Wollte damit nur denjenigen helfen, die ein ähnliches Problem haben
> und einen Einstieg suchen.

Da dürfte ich jetzt falsch rübergekommen sein.

Ich honoriere das ja voll und ganz. Ganz im Gegenteil.
Ich finde es gut, wenn du ein Stück Code hast, von dem du
denkst, dass es veröffentlicht werden soll.

Nur solltest du den Code vor der Veröffentlichung etwas
aufräumen. Da finden sich andere dann nämlich viel
schneller zurecht, wenn zb. eine Variable nicht i sondern
FirstEdge oder ErsteFlanke heist.

Nimm es als konstruktive Kritik.

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Und damit du nicht sagst der Klugschwätzer hat leicht reden:
So würde ich das abliefern.

von Karl N. (karlnapf)


Lesenswert?

Freut mich, dass du von dir aus das Ding nochmal überarbeitet hast, so 
kann ich mir jetzt anschauen wie man's richtig macht.
Sieht natürlich schon um einiges professioneller aus.
Bis dann.

von Mister mit Kanister (Gast)


Lesenswert?

Wegen persönlichem Interesse: Bis zu welcher Frequenz kannst Du mit dem 
Code Signale messen? Hast Du das praktisch mal ausprobiert?

von Karl N. (karlnapf)


Lesenswert?

Ich werd's demnächst mal testen und sag dann Bescheid. Komm nur grad 
nicht dazu.

von Karl N. (karlnapf)


Lesenswert?

Zur Frequenzmessung:

Das ganze gerät bei ca. 75kHz an seine Grenzen. Dann wird das Display 
nur noch ganz langsam beschrieben und es mischen sich falsche Zahlen mit 
rein.
Je höher die Frequenz wird desto langsamer wird das Display beschrieben. 
Könnte daran liegen, dass dann die Zahlen länger werden und die Zeit 
für's Beschreiben länger wird.
Außer über's Display wüßt ich aber nicht wie ich's sonst testen könnte.

von Karl H. (kbuchegg)


Lesenswert?

Holger Brenner wrote:
> Zur Frequenzmessung:
>
> Das ganze gerät bei ca. 75kHz an seine Grenzen. Dann wird das Display
> nur noch ganz langsam beschrieben und es mischen sich falsche Zahlen mit
> rein.
> Je höher die Frequenz wird desto langsamer wird das Display beschrieben.
> Könnte daran liegen, dass dann die Zahlen länger werden und die Zeit
> für's Beschreiben länger wird.

Das denke ich nicht.
Das Problem wird eher sein, dass ab dieser Frequenz schon
so viele Input capture Interrupts generiert werden, dass
der Prozessor praktisch nur noch Capture Interrupts bearbeitet.

von Werner B. (Gast)


Lesenswert?

>Das Problem wird eher sein, dass ab dieser Frequenz schon
>so viele Input capture Interrupts generiert werden, dass
>der Prozessor praktisch nur noch Capture Interrupts bearbeitet.

Vorschlag: Den ICP-Interrupt nach der zweiten Flanke (in der ISR) 
sperren und erst nach der Ausgabe auf dem LCD wieder aktivieren.
Vllt musst du vorher noch das ICP-Interrupt Flag zurücksetzen.
2. Vorschlag: 8MHz statt 4

Werner

von Benjamin Ullrich (Gast)


Lesenswert?

Servus Miteinander,
Gleich vorneweg ich bin alles andere als ein Profi.
Ich selber benötige eine art Frequenz zu messen, bin also auf den ICP 
gestoßen und hab mal dieses Programm hier ausprobiert.
Nun habe ich ein paar Problemchen bzw ideen:

Ideen:
Bekommt man tatsächlich beim Auslesen des Zählerstandes Probleme mit den 
Interrupts so wie im Manual beschrieben ? also muss man zuerst das SREG 
sichern mit cli() interrupts sperren und dann SREG wiederherstellen?

Sollte man den Overflow nicht bei DisplayUpdate == 1 totstellen da der 
sonst weiterzählt ?

Problem:
der Frequenzbereich der mich interessiert ist von ca 1Hz - 500Hz;
Ich habe noch keinen Quarz und nutze den 1MHz Oszillator bei ca 25° und 
recht genau 5,00V

Wenn ich mit meinem Rechteckgenerator 10kHz - 200Hz gehe bekomme ich 
gute ergebnisse, unter 200Hz bekomme ich irgendwann natürlich den 
Overflow aber Stellenweise Totale aurseißer ( Teilweise nur 95% Fehler) 
je weiter ich mit der Frequenz nach unten gehe desteo mehr unbrauchbare 
Werte habe ich.

Da das Ganze ja eine Periodendauermessung ist und ich bei niedrigen f 
eigentlich mehr Pulse bekomme sollte die Messung doch eigentlich genauer 
werden.
Auch wenn ich mit dem Prescalar so weit Hochgehe dass kein Overflow mehr 
entsteht sind meine Werte trotzdem nur bis 50Hz brauchbar.

Ich hab auch mal an der SV für den Chip nachgemessen, ich habe keinen 
erhöhten Stromverbrauch und die Spannung bricht auch nicht zusammen.

Hat einer eine Idee? (Nutze die die  FreqCount.c mit UART ausgabe statt 
LCD)

von Hauke R. (lafkaschar) Benutzerseite


Lesenswert?

Ich kenn mich mit C nicht aus und weis auch nciht wie der FreqCount.c 
funktioniert, aber ich würde im Overflow Interrupt eine Variable 
hochzählen und diese dann mal 256 und danach plus den Zählerwert 
rechnen. Und schon ist das Overflow Problem gelöst.

von Sepp (Gast)


Lesenswert?

>FreqCount.c

wie würde denn ein solcher PIN an einem PIC eingelesen werden???

ich komm mit den Datenblättern nicht zu Potte

von ein Freund (Gast)


Lesenswert?

Hallo wirklich ein tolles Programm,
hatte ein Paar Probleme mit der Messung über den Capture Betrieb da ich 
die Berechnung in der Interrupt gemacht habe.
Jetzt arbeite ich nach dem hier beschriebenen Prinzip und es 
funktioniert wirklich gut.
Habe aber noch irgendwie leicht Abweichungen. Will sehr genau messen und 
arbeite daher mit 8MHz. Messe zu Testzwecken meinen eigenen Timer0 den 
ich auf genau 1Hz eingestellt habe. Mein Ergebniss liegt aber bei 
1,02Hz.
Bei höheren Frequenzen wird die Abweichung noch größer.

@Hauke Radtki: Ich denke das hier schon nach dem von dir beschriebenen 
Prinzip gearbeitet wird nur das der Timer1 ein 16Bit Timer ist und daher 
nicht mit 256 multipliziert wird sondern mit 65536.

@Karl Napf: In jedemfall erstmal vielen Dank für den Tip. ;-)

von Klaus D. (kolisson)


Angehängte Dateien:

Lesenswert?

hallo,

das ist ja ein recht alter thread. trotzdem habe ihn heute erst gelesen 
und
fand das programm :

> Autor:  Karl heinz Buchegger (kbuchegg) (Moderator)
>Datum: 08.02.2007 22:28
>Dateianhang: FreqCount.c

ganz schön.

als bascom-fan habe ich mal an bascom angepasst und etwas erweitert.

im anhang dann der code

gruss
klaus

von gast (Gast)


Lesenswert?

double Erg = 0.0;

Erg = (NrOverflows * 65536) + EndTime - StartTime;
      sprintf(s,"Erg als Float: %f\r\n",Erg);
    uputs(s);


ausgabe:

Erg als Float : ?

von Karl H. (kbuchegg)


Lesenswert?


von Steffen (Gast)


Lesenswert?

Hallo,

ich bin gerade dabei, diesen Code zu verwenden. Verstehe aber folgende 
Logik nicht:
1
Erg = (NrOverflows * 65536) + EndTime - StartTime;

Angenommen der StartTime ist 65000 und EndTimer wäre 100. Es hat 
folglich 1 Overflow stattgefunden.
Rechne ich also:
Erg = (1*65536) + 100 - 65000
    = 65536 + 136
    = 65672

Die vergangene Zeit in Timer Werten ist jedoch nur 136.
Ist daran etwas falsch? Oder wird hier tatsächlich ein Overflow zuviel 
gezählt, der nicht gezählt werden dürfte?

von T. (Gast)


Lesenswert?

Ist 100 - 65000 denn +136 ?

von Steffen (Gast)


Lesenswert?

T. schrieb:
> Ist 100 - 65000 denn +136 ?

Scheinbar nicht...
Könntest du mir das mal erklären, wie dort in dem Beispiel "gerechnet" 
wird?

von T. (Gast)


Lesenswert?

Erm, du hast es behauptet...

von Steffen (Gast)


Lesenswert?

Hatte ich auch so gedacht, aber scheinbar habe ich einen Denkfehler. 
Darum habe ich gebeten, ob du mir die Rechnung mal erklären kannst, 
damit ich es verstehe.
Danke.

von Klaus D. (kolisson)


Lesenswert?

((1*65536)-65000) + 100 = 636


also einmal  von 65000 bis overflow
und dann noch die 100

gruss

von Erik B. (bibabulks)


Angehängte Dateien:

Lesenswert?

Hallo,

Hab den hier geposteten Code von Karl Napf verwendet, besten Dank 
hierfür erstmal und die Verbesserungen des anderen Karl's, um über das 
IC-PIN eine Frequenzmessung durchzuführen. Habe den Code ein versucht 
ein bißchen zu erweitern und zwar, dass j Messungen durchgeführt werden 
um dann einen Mittelwert gebildet um die Genauigkeit zu erhöhen. Ich 
verwende für die Messaufgabe einen Atmega168 mit 20MHz Taktfrequenz. 
Beim Test des Programmes mit einem Frequenz-Generator erhalte Ich bis 
ca. 2kHz sehr gute Ergebnisse, d.h. dass die ausgegebene Frequenz auf 
dem Display mit 1Hz Genauigkeit übereinstimmt.
Erhöht man die Frequenz bis 5kHz so muss man feststellen, dass Sie bis 
zu 3Hz abweichen kann. Bei 10kHz ist die Auflösug schon so schlecht, 
dass man sich mit einer Auflösung von 10 Hz bis 20 Hz abfinden muss.

Meine Frage: kann mir jemand weiterhelfen den Code zu verbessern, oder 
einen Tip geben, um die Messgenauigkeit zu verbessern? Entweder bei 2kHz 
Auflösung von 0,1Hz oder bei 20kHz Auflösung von 1Hz? Ist das überhaupt 
möglich?

Hintergrund ist Ich möchte Frequenzen bis 150Mhz messen, die über Teiler 
bis in den kHz-Bereich herunter geteilt werden sollen. Teilungsfaktor 
bei 2kHz der Messfrequenz wäre dann nach Adam Ries 75 000 macht bei 
einer Auflösung von 1Hz, wie es bisher ist 75 kHz Gesamtauflösung. Dies 
möchte Ich gern verbessern.

Danke im vorraus

von Erik B. (bibabulks)


Lesenswert?

sry hat's alles bissl verschoben, hat jemand ne idee???

von Martin (Gast)


Lesenswert?

1
erg = (overflows*65536) + endtime - starttime;  // allg. Formel

Die Logik dahinter ist nicht ganz richtig. Es kann auch ein 
Timer-overflow stattfinden, ohne dass die Messung selbst 65556 Zyklen 
überschritten hat.

von Mitleser (Gast)


Lesenswert?

>Die Logik dahinter ist nicht ganz richtig. Es kann auch ein
>Timer-overflow stattfinden, ohne dass die Messung selbst 65556 Zyklen
>überschritten hat.

Kann das jemand näher ausführen?

Mal eine Frage zur Hardware.

Hab das Ganze mal auf einem Pollinboard versucht (aktive-high) und ein 
alten Rechteckgenerator drangehangen.
Problem ist das sporadisch (für längere Zeit) die Messungen aussetzen, 
sollte man da noch etwas dazwischen schalten?

von Erik B. (bibabulks)


Lesenswert?

Nein du brauchst eigentlich nicht's mehr dazwischen zu schalten. Einfach 
mit dem Ausgang des Frequenzgenerators an das Capture-PIN und natürlich 
noch die Massen zusammenführen. Eichtig ist, dass dein Frequenzgenerator 
für den Mikrocontroller verarbeitbare Pegel ausgibt. (0-5)V TTL z.B.

Wenn du oben aufgeführtes Messprinzip nimmst, ist irgendwann schluss.
Messprinzip ändern Torzeit gewähren und Impulse zählen.

von Mitleser (Gast)


Lesenswert?

Dann muß ich noch irgendwo ein anderes Problem haben,
Pegel 5V stimmt laut Oszi auch ein leichtes hoch und herunterregeln 
bringt nichts.
Evtl. stimmt aber auch im Messaufbau was nicht und ich geh mit über 5V 
in den AVR.
Sollte man da evtl. noch nen Transistor oder gar Schmidt Trigger 
verwenden, so als Sicherheit?
Irgendwann soll das Ding dann mal in eine bestehende Maschiene wandern 
und zur Drehzahl schalten ob die wirklich TTL ausgiebt, ich weiß es 
nicht.
Wie wichtig ist denn auch ein sauberes Rechteck für den Capture-Pin?

Ihr merkt schon das ich langsam verzweifel g versuche mich schon seit 
längerem an dem Beispiel.

von Erik B. (bibabulks)


Lesenswert?

Erstmal welchen Controller & Welche Frequenz kannst ruhig mal erwähnen . 
. .

von Karl H. (kbuchegg)


Lesenswert?

Mitleser schrieb:
> Dann muß ich noch irgendwo ein anderes Problem haben,
> Pegel 5V stimmt laut Oszi auch ein leichtes hoch und herunterregeln
> bringt nichts.

Kann mich daran erinnern, dass ich damals mit dem Programm auf einem 
Mega16 gespielt habe.
Durch berühren mit dem Finger zeigte die Anzeige 50Hz an.
Dein Frequenzgenerator liefert mit Sicherheit um einiges saubere 
Rechtecksignale als mein Körper, der sich die Netzfrequenz von irgendwo 
her einfängt,

> Evtl. stimmt aber auch im Messaufbau was nicht und ich geh mit über 5V
> in den AVR.

Bist du am richtigen Pin?

von Karl H. (kbuchegg)


Lesenswert?

Mitleser schrieb:
>>Die Logik dahinter ist nicht ganz richtig. Es kann auch ein
>>Timer-overflow stattfinden, ohne dass die Messung selbst 65556 Zyklen
>>überschritten hat.
>
> Kann das jemand näher ausführen?

Nimm dir reale Werte (erfinde welche), setz in die Formel ein und sieh 
nach was rauskommt.

Dadurch das der Startwert dann größer als der Endwert ist, rechnet sich 
dieser eine Overflow wieder heraus.

Du musst nur, anders als Steffen weiter oben, so rechnen wie es auch der 
µC macht: von links nach rechts und nicht als mitdenkender Leser 
zunächst Teilausdrücke zusammenziehen.

von Robert Schepp (Gast)


Lesenswert?

Hallo zusammen,

habe auch einige Versuche unternommen, über Int0/Int1 die pos. Flanke, 
und über ICP die neg. Flanke, und damit die Dauer eines Fernsteuer PPM- 
Signals zu messen.
Der sich ändernde Fehler in der Genauigkeit hängt meiner Ansicht nach an 
eventuellen Asymetrien in den Interruptroutinen.
Dauert die Routine für die erste Flanke länger als für die zweite, 
ändert sich der Fehler prozentual bei sich ändernder Frequenz.
D.h. es muß peinlichst darauf geachtet werden, beide Interruptroutinen 
exakt gleich lang (Laufzeit) zu machen.

anderes Thema:
Durch Auswerten des Timer Overflows bzw. des erreichten Zählerstandes 
kann man einen anderen Vorteiler einstellen, und hat damit eine 
automatische Frequenzanpassung.


Gruß
Robert

von Karl H. (kbuchegg)


Lesenswert?

Robert Schepp schrieb:

> Der sich ändernde Fehler in der Genauigkeit hängt meiner Ansicht nach an
> eventuellen Asymetrien in den Interruptroutinen.

Wie schnell taktest du deinen Prozessor?
1kHz, 10kHz?

> D.h. es muß peinlichst darauf geachtet werden, beide Interruptroutinen
> exakt gleich lang (Laufzeit) zu machen.

Übertreib mal nicht.
Dein µC arbeitet schnell genug, dass das kein Problem darstellt.

von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe die Ideen oben mal mit einfließen lassen. Ich berechne mir das 
Ergebnis direkt in der ISR, da ich später direkt dort entscheiden muss, 
ob je nach Frequenz etwas getan werden muss oder nicht.
Ich habe im obigen Programm folgende Codezeilen ergänzt:
1
  
2
if ( (TIFR & (1 << TOV1)) && (!(EndTime & 0x8000)) ){    // Überlaufstattgefunden, der zur Messung gehört?
3
  NrOverflows++;
4
  }  
5
  if ( EndTime < StartTime ){    // Overflow stattgefunden, der aber nicht zur Messung gehört?
6
  NrOverflows--;
7
  }
Einerseits durch das hineinziehen in die ISR, muss ich prüfen, ob 
während Auftritt der ISR ein Overflow stattgefunden hat.
Die zweite Ergänzung prüft, ob ein Overflow vorliegt, der aber nicht zur 
Messung gehört.
Leider bekomme ich manchmal, nicht immer trotzdem 1 Overflow zu viel in 
der Messung.
Erkennt noch jemand einen Fehler in der Logik?

Danke.

P.S. Die Zeilen sind für Atmega8 geschrieben.

von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

Kleiner Fehler in der angehängten Datei, dort habe ich die 
Variablennamen noch nicht angepasst. Hier mit Fehler behoben, ändert 
aber nichts an der Logik :-)

von Peter D. (peda)


Lesenswert?

Daniel schrieb:
> Leider bekomme ich manchmal, nicht immer trotzdem 1 Overflow zu viel in
> der Messung.

Du mußt die Überlaufbehandlung auch bei der Startflanke machen.
Oder einfach garkeine extra Start/Stop-Behandlung, sondern einfach 2 
aufeinanderfolgende Auslesungen subtrahieren (alte Stopzeit = neue 
Startzeit).

http://www.mikrocontroller.net/attachment/16302/TIMER32.C


Peter

von Martin H. (ar583)


Lesenswert?

Hallo,

ich habe mir mal die Frequenzmessungsprogramme von Karl Napf und Karl 
Heinz Buchegger angesehen und denke, dass diese für meine Anwendung 
passen könnten. Bin mir da aber nicht so ganz sicher und möchte euch 
deshalb gerne fragen, was ihr dazu sagt.

Ich würde nämlich gerne die Frequenz eines Rechtecksignals messen, die 
ca. im Bereich von 1-10Hz liegt, also sie wird mal höher mal niedriger. 
Der High-Pegel dieses Signals soll ebenfalls veränderlich sein. Mal kann 
er 0,5V sein, mal 4V. Ich würde gerne die Frequenz dieses Signals messen 
und gleichzeitig als "schönes" Rechtecksignal an einem anderen Port 
ausgeben, der Pegel soll dann 0V low bzw. 5V high sein.

Ist es möglich so etwas zu realisieren, oder müssen die High-Pegel immer 
gleich sein? Kann gleichzeitig gemessen und an einem anderen Port das 
Signal in der gemessenen Frequenz ausgegeben werden?
Ich hab so daran gedacht, solange sich die Frequenz am Eingang nicht 
ändert, müsste ja keine neue Frequenz an den Ausgangsport geschrieben 
werden. Das Ganze muss nicht so ne genaue Auflösung haben, aber es 
sollte so im 1Hz-Bereich unterschieden werden können (z.B. zwischen 4Hz 
und 5Hz). Ich möchte das auf dem Atmega16A realisieren.

Lg

von Ingo (Gast)


Lesenswert?

Wenn nun der InputCapture auslöst, der Timerwert gespeichert wird, und 
alle Interrupts gerade durch eine andere ISR gesperrt sind und innerhalb 
dieser zeit der Timer überläuft, was passiert wenn die Interrupts wieder 
freigegeben werden? Zuerst wird doch die Overflow ISR angesprungen, der 
Overflowcounter incrementiert und erst anschließend die Input Capture 
ISR abgearbeitet. Dann passt aber der gecaputerte Wert nicht zum 
Overflowcounter und die Frequenz ist falsch.

Also macht das doch keinen Sinn. Man müsste eigentlich jedesmal prüfen 
ob der alte Wert größer ist als der neue, dann nämlich ist der Timer 
min. einmal übergelaufen, richtig?

Eigentlich eignet sich ein INT0 Interrupt besser, denn da wird der 
Zählerstand manuell ausgelesen und somit passt der Wert immer zum 
Overflowcounter.

Oder liege ich falsch?

Ingo

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.