PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Frequenz einlesen über den AVR Butterfly



Heiko R.
08.11.2005, 09:19
Hallo,

Wir haben es geschafft mit dem "Butterfly zu sprechen". Nun stehen wir vor dem Problem eine Frequenz einzulesen. Wir bekommen 4-20mA von einem Drucksensor und wandeln dieses Signal mit einem Strom/Frequenzwandler um. Nun würden wir gerne die Frequenz einlesen um dadurch den entsprechenden Druck zu errechnen. Wie wäre das den beim Butterfly am besten möglich? Kennt sich da einer schon mit aus?

Gruß Heiko

Heiko R.
11.11.2005, 14:05
Hallo,

wir lesen jetzt die Flanke von einem High-Pegel der Frequenz ein mit pulsein. Leider lässt sich da glaube ich nur die High-Pegel-länge einlesen. Oder ebend die Low-Pegellänge. Kann das sein? Wir müssten nämlich nur einen Takt einlesen, dass aber möglichst genau. Wäre das noch anders möglich oder geht das nur mit Pulsein, dann die Low und Highflanke zusammenaddiert und dann 1 durch den Wert. Das Problem ist, dass der Butterfly recht ungenau ist. Wir lassen uns den zahlenwert ausgeben, aber der schwankt halt um einiges und manchmal wird er garnicht angezeigt. Wenn ich dann beide Werte addiere habe ich somit eine Riesenverfälschung. Und eine Mittelwertbildung fällt durch 2 Gründe flach. 1. Wenn ein Wert fehlt so ist das ergebniss Schmarn und 2. wissen wir nicht wie schnell sich unser Takt ändert.

Hat zufällig einer ne Patentlösung oder einen Vorschlag wie ich eine Pulsperiode mit dem AVR Butterfly möglichst genau einlese?

Gruß Heiko

SprinterSB
11.11.2005, 17:56
AVRs können einen Input Capture machen.

An speziellen Pins (ICPx etwa) bewirkt ein Signal, daß der Wert des Timersx gesichert wird. Diesen gesicherten Wert muss man dann möglichst schnell auslesen. Jedefalls, bevor das nächste Ereignis auftritt. Triggern kann man auf fallende/steigende Flanke und auf Wechsel.

Ebenfalls gibt es IRQs dafür.

Wie's genau geht, und was zu beachten ist, steht im Manual bei den 16 Bit-Timern unter Input Capture.

hrei
11.11.2005, 18:56
Hallo!

Ansich ist das mit Capture sehr sinnvoll und einfach zu handhaben. Die einzige Falle besteht darin, daß zum Lesen des Capture Registerpaares die Interrupts abgeschaltet sein müssen.

Ein Beispiel für das Wesentliche:

Das Vorspiel:


On Icp1 Oncapture 'Interrupt-Routine
Config Timer1 = Timer , Capture Edge = Falling , Prescale = 256

Enable Icp1 'Capture-Interrupt freigeben
Enable Interrupts 'Interrupts global freigeben


Dein Code zu Anzeigen, Berechnen oder sonstwas.....

Die ISR:


Oncapture: 'Timer1-Capture
Disable Interrupts 'nötig für Auslesen von Cap1
Wcount = Capture1 'Wert sichern
Timer1 = 0 'Timer-Reset
Enable Interrupts 'Interrupts wieder aktivieren
Return


Grüße
Henrik

Rage_Empire
12.11.2005, 10:47
Hm, das mit dem Timer hab ich bei meiner Anwendung auch so. Aber ich bin mir im Moment auch am Überlegen, ob ich es mit Pulsein machen kann, da ich dann wieder einen Timer Frei habe. Die Länge von High-Pegel und Low-Pegel kann man mit einem Flipflop zusammen bringen (Frequenzteilung), wodurch die gesammte T ermittelt würde. Jedoch habe ich verständnissprobleme mit dem Pulsein-Befehl, welcher auch noch von der Taktfrequenz abhängig ist.

hrei
12.11.2005, 13:28
Hallo,


Jedoch habe ich verständnissprobleme mit dem Pulsein-Befehl, welcher auch noch von der Taktfrequenz abhängig ist.

da sagst Du was... Bei dieser Hilfestelle:
"It will increase in 10 uS units. But this depends on the XTAL. You can change the library routine to adjust the units."
bin ich auch verzweifelt, habe mir die Routine in der Lib angesehen und kein sinnvolles Schräubchen zum Drehen gefunden.
Auch in der neuen Verschlimmbesserung der Bascom Dokumentation findet sich dazu nichts Neues.

Nun bin ich sowieso eher der praktische Typ, also habe ich den Quark mal mit verschiedenen Taktfrequenzen ausprobiert. Wunder über Wunder:

Bei 4 über 8 bis zu 16 Mhz bekam ich die gleichen Resultate mit einer Abweichung, die die +- 3x10µS die sowieso programmbedingt ist, nicht überschritt.

Nebenbei: Verzichtet man auf ein Bitwait, muss die Erfassung unbedingt in einer Schleife erfolgen, da die erste Messung immer Murks sein kann.

Da die Pulseinmethode sowieso kein Präzisonsinstrument ist, kann man auch zwei Pulsein Befehle hintereinander ausfürhren, einmal für Low und einmal für High. Die Addition ergibt dann die Periodendauer.

Sieht z.B. so aus:


Pulsein Freq_ein , Pinb , 1 , 0 'Low messen in 10µS Einheiten
Temp = Freq_ein
Pulsein Freq_ein , Pinb , 1 , 1 'High messen
Freq_ein = Temp + Freq_ein 'entspricht Periodendauer in 10µS


Grüße
Henrik

Rage_Empire
12.11.2005, 13:50
Theoretisch könnte man mit ein schon erwähnten Flip-flop die Pulshigh- und -Lowdauer zusammenfassen. Dann 3 oder 4 messungen mit Pulsein....Durchschnitt errechnen und schon hat man die Frequenz. ich denke bei höheren frequenzen kommts auf 5Hz oder 10Hz auch nicht an.

hrei
12.11.2005, 14:41
Hallo,


Theoretisch könnte man mit ein schon erwähnten Flip-flop die Pulshigh- und -Lowdauer zusammenfassen.


Klar geht das, nur hat man dann einen normalerweise höchst entbehrlichen 14-Füßer auf der Platine herumfliegen.



Dann 3 oder 4 messungen mit Pulsein....Durchschnitt errechnen und schon hat man die Frequenz.


Die erste Messung musst Du auf jeden Fall wegwerfen, da das Ergebnis der allgemein bekannte und berüchtigte Rainer Zufall ist :-) und das arithmetische Mittel versaut.


ich denke bei höheren frequenzen kommts auf 5Hz oder 10Hz auch nicht an.

Gerade bei hohen Frequenzen wird es kritisch, weil nur wenige 10µS Units in der Periode erfasst werden. Wenn Dir von 100 Units 3 fehlen, ist das schmerzlicher, als wenn es bei 10.000 zu 3 Ausfällen kommt.

Bei hohen Frequenzen sollte man sowieso nicht die Periodendauer messen, sondern die auflaufenden Impulse per Torzeit zählen.

Grüße
Henrik

Rage_Empire
12.11.2005, 14:51
Also sollte man bei höheren Frequenzen lieber den Timer verwenden, wenn ichs jetzt richtig verstanden hab.

SprinterSB
12.11.2005, 15:37
Einen Timer verwendet man so oder so, aber einmal verwendet man dessen InputCapture-Einheit, um Zeiten genau zu messen, und einmal verwendet man externe Impulse, um den Timer hochzählen zu lassen. Bei letzterem braucht man noch einen zweiten Timer.
Dummerweise liegen die Tx Eingänge an anderen Pins als die ICPx.

hrei
12.11.2005, 16:50
Einen Timer verwendet man so oder so, aber einmal verwendet man dessen InputCapture-Einheit, um Zeiten genau zu messen, und einmal verwendet man externe Impulse, um den Timer hochzählen zu lassen. Bei letzterem braucht man noch einen zweiten Timer.
Dummerweise liegen die Tx Eingänge an anderen Pins als die ICPx.

Öhmm... ganz so isses ja nu nicht.

* Die Pulsein-Methode verwendet keinen Timer.

* Die Capture Methode verwendet einen Timer.

* Die Zählmethode verwendet einen Timer für die Torzeit.
Die Impulse erfasst man am besten über einen Interrupteingang, alternativ geht natürlich auch eine Flankendedektion an jedem beliebigen Pin per Software.

Grüße
Henrik

SprinterSB
13.11.2005, 00:26
Einen Timer verwendet man so oder so, aber einmal verwendet man dessen InputCapture-Einheit, um Zeiten genau zu messen, und einmal verwendet man externe Impulse, um den Timer hochzählen zu lassen. Bei letzterem braucht man noch einen zweiten Timer.
Dummerweise liegen die Tx Eingänge an anderen Pins als die ICPx.

Öhmm... ganz so isses ja nu nicht.

* Die Pulsein-Methode verwendet keinen Timer.

* Die Capture Methode verwendet einen Timer.

* Die Zählmethode verwendet einen Timer für die Torzeit.
Die Impulse erfasst man am besten über einen Interrupteingang, alternativ geht natürlich auch eine Flankendedektion an jedem beliebigen Pin per Software.

Grüße
Henrik

Mag sein, daß Pulsin das so macht...

Ich bezog mich in meinem Post auf die Möglichkeiten der zugrundeliegenden AVR-Hardware.

Wenn man seinen AVR auf 1MHz getaktet hat, dürfte man IMHO arge Probleme bekommen, wenn man versucht, Frequenzen über 100kHz softwaremässig zu messen, wahrscheinlich sogar schon deutlich früher. Vor allem mit Basic.

Flankendetektion über Polling und externe IRQs liefern zudem ein recht fehlerbehaftetes Ergebnis, vor allem erster Ansatz. Die Schleife dürfte nicht länger dauern als 10 Takte. Eine auf externe IRQ basierende ISR dürfte komplett nicht länger dauern als 6 Takte (4 Takte IRQ-Latenz). In beiden Fällen sind (andere) IRQs tabu.

Warum also sollte man die Möglichkeiten der Hardware nicht nutzen?

hrei
13.11.2005, 17:14
Mag sein, daß Pulsin das so macht...

Das mag nicht so sein, daß ist so.


Wenn man seinen AVR auf 1MHz getaktet hat, dürfte man IMHO arge Probleme bekommen, wenn man versucht, Frequenzen über 100kHz softwaremässig zu messen, wahrscheinlich sogar schon deutlich früher. Vor allem mit Basic.

Wer einen µC mit 1 MHz taktet, wenn er 100 kHz messen will, hat kein (programm)technisches Problem, sondern ein Verständnisproblem.


Flankendetektion über Polling und externe IRQs liefern zudem ein recht fehlerbehaftetes Ergebnis, vor allem erster Ansatz. Die Schleife dürfte nicht länger dauern als 10 Takte. Eine auf externe IRQ basierende ISR dürfte komplett nicht länger dauern als 6 Takte (4 Takte IRQ-Latenz). In beiden Fällen sind (andere) IRQs tabu.

Schneller als das direkte Aufaddieren der Impulse im Interrupt ist keine andere Methode. Die ISR besteht aus einem Befehl + return: INCR var.


Warum also sollte man die Möglichkeiten der Hardware nicht nutzen?
Weil der Fragesteller erwähnte, er hätte die Timer gerne für andere Zwecke frei?

Ohne zu wissen, welcher Frequenzbereich denn nun tatsächlich erfasst werden soll, können nur alle Methoden aufgezeigt werden. Bei niedrigen Frequenzen <1 kHz ist die Periodendauermessung meist sinnvoll, darüber hinaus werden i.d.R. mit der Impulszählung die besseren Ergebnisse ezielt werden können.

Henrik

Rage_Empire
13.11.2005, 17:45
Henrik hat das schon richtig erkannt.
Man könnte ja eine hohe frequenz runterteilen. dann wäre es mit der Periodendauermessung wieder zu bewältigen. Also, bei meiner anwendung um die 40Kz, teiler durch 32 oder 64 und dann pulsein. Nur die Hardware wächst dann leider auch mit.

SprinterSB
13.11.2005, 18:37
Ich gehe mal davon aus, daß es in Ordnung ist, hier die Möglichkeiten der Hardware eines AVR aufzuzeigen, die zur Lösung der Frage das OP hinführen könne. Hierzu gehört auch das Zählen externer Pulse mittels externer Timer-Quelle.

Ich sehe nicht, warum man damit nicht eine Frequenz von f messen können sollte, wenn man auf 10*f taktet. Voraussetzung ist, daß die einzelenen Pulse länger sind als ein Prozessortakt -- eine Einschränkung an das Signal, die man bei allen Verfahren hat.

Ok, je höher die Anforderungen an eine Messung sind, desto mehr Hardware muss man vorhalten -- ne Binsenweisheit. Nen Timer frei zu haben ist freilich immer nett...

Ohne Kenntnis der restlichen Applikation ist es kaum möglich zu beurteilen, wie man einen externen IRQ am besten dienstbar macht, das weiß der OP am besten.

Die externen IRQs haben hohe Priorität. Lässt man kaskadierende IRQs zu, schafft man eine IRQ-Latenzzeit von 9 Takten, 2 Takte für Save/Restore von SREG und 2 Takte adiw für der Zähler, 4 Takte reti. Leistet man sich den Luxus, die verwendeten Register zu sichern, ist man grob bei 20 Takten.
Damit erhält man eine untere Grenze für die Pulslängen eines fehlerfrei messbaren Signals.

Heiko R.
14.11.2005, 08:25
Hallo,

sorry das ich so lange nichts gesagt habe. Ich möchte eine Frequenz von max 10KHz messen. Wenn ich es richtig verstanden habe wäre somit die pulsein-Variante schon möglich, oder? Habe ich das jetzt richtig verstanden, dass die Zahl die er uns bei pulsein ausgibt, mit 10µs multipliziert werden muss? Steht die Info im User Guide oder wo hast du diese Info denn her Henrik?
Wenn es ohne Timer gehen würde wäre es schon besser für uns, da der Timer irgendwie nie das macht was wir wollen ](*,) :-s .

Gruß Heiko

Heiko R.
14.11.2005, 08:47
Hallo,

ích habe gerade noch mal die pulsein-Variante ausprobiert und meine Chiptaktung geändert. Dadurch ändert sich ja auch die ausgegebene Zahl. Mit welcher Taktung hast du deinen Chip getaktet, dass er die Zahl * 10µs ausgibt? Durch die höhere Taktung streut der Wert auch nicht mehr so stark.

Gruß Heiko

Werner_Just
14.11.2005, 10:48
Hallo Henrik,

> Die einzige Falle besteht darin, daß zum Lesen des Capture
> Registerpaares die Interrupts abgeschaltet sein müssen.
Ist das nicht standardmäßig in einer Interrupt-Routine sowieso so?
D.h. solange Du in OnCapture die Interrupts nicht explitzit wieder frei gibst sind sie innerhalb der Interrupt-Routine gesperrt und werden erst beim Return wieder freigeschaltet.

Aber noch was anderes...
Funktioniert das Timer-Capture bei Dir im BASCOM-Simulator?
Bei mir übernimmt der BASCOM-Simulator den aktuellen Timerwert nicht in das Capture Register. Weder bei Deinem Code, noch bei meinem, noch beim Beispiel von Rowalt. Simuliere ich den Code in Studio4 klappt es, genauso wie in real Hardware. Der von BASCOM erzeugte Code scheint also korrekt zu sein.

Mark Albert hat sich bei Supportanfragen dazu bisher nie geäussert. Keine Antwort, auch auf Nachfrage :(

Ist das nur auf meinem Rechner so? (Getestet hab ich es unter W95/2000/XP, mit BASCOM 1.11.7.4 bis 1.11.7.9 und M8, M16 und M32er Atmel.)

Ciao,
Werner

Heiko R.
15.11.2005, 06:56
Hallo,

hat sich glaube ich geklärt. Ich müsste einen Anstieg, der in 100-400ms erledigt ist, bearbeiten. Ich müsste aber den Wert ständig abtasten um nicht über einen Punkt in der Rampe hinauszufahren. Wenn keiner mehr eine neue Lösungsidee hat, dann werde ich es vermutlich anders lösen müssen.

Gruß Heiko