Hallo zusammen,
bin Anfänger also alles ganz langsam.
Ich programmiere eine Frequenzmessung in C (Atmel Studio 7, GCC).
Dazu muss ich das ICF1-Flag abfragen ob dieses innerhalb 40ms gesetzt
wurde.
Ist dies nicht der Fall, Ausgabe "A"
Ist dies der Fall, ICR1-Wert in eine Variable und auf das nächste
ICF1-Flag warten.
Leider habe ich keine Ahnung wie ich die "Warteschleife" umsetzen soll.
An sich müsste es Sinngemäß so funktionieren:
if (TIFR1 == 0x27 && Zeit<40ms)
{Anweisung}
Ich kann da auch keine for-Schleife nehmen die 1ms pro Durchlauf dauert,
das verfälscht mein Ergebnis.
Und es darf keine ISR benutzt werden...soll eben alles in der
Hautschleife passieren.
Danke für eure Hilfe
AC
Da das ganze Programm sehr Zeitkritisch wird soll dort keine ISR benutzt
werden. Die Frequenzmessung soll in der Hauptschleife geschehen. Dieser
jemand der das "verbietet" hat das ganze, wie oben beschrieben, in
BASCOM programmiert und ich muss jetzt diesen Teil aber in C umsetzen.
AC schrieb:> Da das ganze Programm sehr Zeitkritisch wird
Das kann nicht sein, wenn es erlaubt ist mehrere Millisekunden in der
Hauptschleife auf ein Flag aktiv zu warten.
tja, was soll ich sagen...ich habe die frequenzmessung schon mit der ISr
Timer1 Capt gemacht und da zittert der Wert etwas (bei eingestellten
55Hz zwischen 55,018Hz und 54,863Hz).
Und ich soll es jetzt wie oben geschrieben programmieren...also nochmal:
Leider habe ich keine Ahnung wie ich die "Warteschleife" umsetzen soll.
An sich müsste es Sinngemäß so funktionieren:
if (TIFR1 == 0x27 && Zeit<40ms)
{Anweisung}
Jemand eine Idee?
AC schrieb:> tja, was soll ich sagen...ich habe die frequenzmessung schon mit der ISr> Timer1 Capt gemacht und da zittert der Wert etwas (bei eingestellten> 55Hz zwischen 55,018Hz und 54,863Hz).> Und ich soll es jetzt wie oben geschrieben programmieren...also nochmal:>> Leider habe ich keine Ahnung wie ich die "Warteschleife" umsetzen soll.> An sich müsste es Sinngemäß so funktionieren:>> if (TIFR1 == 0x27 && Zeit<40ms)> {Anweisung}>> Jemand eine Idee?
Suche dir eine andere Aufgabe.
AC schrieb:> Und ich soll es jetzt wie oben geschrieben programmieren
Es ist völliger Unsinn das nicht mit einer ISR zu machen.
Dagegen spricht auch eine Zeitkritikalität des restlichen Programms
nicht.
Wenn eine Interrupt-Unterbrechung von wenigen Mikrosekunden dein
Programm stört, dann ist es falsch.
AC schrieb:> tja, was soll ich sagen...ich habe die frequenzmessung schon mit der ISr> Timer1 Capt gemacht und da zittert der Wert etwas (bei eingestellten> 55Hz zwischen 55,018Hz und 54,863Hz).
Dann rechne mal nach, wie hoch Dein Quantisierungsfehler überhaupt ist.
Der Witz am Cature ist nämlich, daß es von der Interruptlatenz
unabhängig ist. Aber besser als ein Timertakt kann es nicht auflösen.
Wenn das nicht reicht, mußt Du den Timertakt erhöhen oder über mehrere
Perioden messen.
Bevor ich die Aufgabe bekommen habe, habe ich es, wie folgt umgesetzt
wobei der Wert z.B bei eingestellter frequenz vonn 55Hz zwischen
55,018Hz und 54,863Hz zittert:
1
TimerInitialisierung:
2
TCCR1A=0x00;//Timer1 Normal Mode
3
TCCR1B=0x45;//Input Capture Edge (Positive Flanke); Kein Vorteiler
Controller ist ein Atmega1284P mit 20Mhz Takt. Die Frequenz wird von
einem FreqGen (Velleman) der per USB angeschlossen wird eingespeist.
Ist der Code so in Ordnung oder könnte das Zittern der Werte irgendwo im
Code verursacht werden?
Peter D. schrieb:> Dann rechne mal nach, wie hoch Dein Quantisierungsfehler überhaupt ist.
Das sollte er tatsächlich dringend mal tun, völlig klar.
> Der Witz am Cature ist nämlich, daß es von der Interruptlatenz> unabhängig ist.
Nein, leider natürlich nicht wirklich. Klar, das Capture selber passiert
unabhängig von allen Aktivitäten der MCU. Aber: Der Code muss auf ein
ICP-Ereignis reagieren, bevor das nächste eintritt, sonst ist der
Capturewert schlicht verloren und es wird Müll bei der Messung
herauskommen, weil erst der nächste (oder übernachste...u.s.w.)
Capturewert zur Messung verwendet wird.
Das gilt übrigens völlig unabhängig davon, ob der Code zur Messung in
einer ISR agiert oder in main(), da sowohl die Antwortzeit in main() als
auch in einer ISR unmittelbar von den Sperrzeiten aller anderen
Interrupts im System abhängt.
Deswegen ist es natürlich sehr vermessen, zu sagen, das Capture wäre von
der Interruptlatenz unabhängig...
AC schrieb:> Bevor ich die Aufgabe bekommen habe, habe ich es, wie folgt umgesetzt> wobei der Wert z.B bei eingestellter frequenz vonn 55Hz zwischen> 55,018Hz und 54,863Hz zittert:> frequenz = frequenz / 1024;
Soll man daraus die nicht ganz unwichtige Erkenntnis ziehen, dass der
Timer womöglich mit einem Prescaler von 1024 läuft? Das hieße, er läuft
mit einer Frequenz von ca. 19,5 kHz und kann damit die Periodendauer in
Schritten von ca. 51 µs ermitteln. Deine 55 Hz haben eine Periodendauer
von ca. 18 ms, was etwa 355 mal so viel ist. Das heißt, wenn deine
Messung nur um einen Timer-Tick schwankt, reicht das schon aus, um
deinen angezeigten Wert um etwa 0,15 Hz schwanken zu lassen, was
ziemlich genau deiner Beobachtung entspricht. Mit anderen Worten: Die
Auflösung deiner Messung ist einfach nicht höher.
Der Vorteiler ist mit 1024 zu groß, folglich der Zählwert zu klein: er
wird derzeit 355 oder 356, und daraus werden nach obiger Rechnung eben
55.0176 bzw. 54.8631.
Mal ganz davon abgesehen kümmert sich der Code nicht um atomare Zugriffe
oder darum, was passiert, wenn während der Ausgabe ein Interrupt
auftritt. Da kommt dann in manchen Fällen vermutlich auch mal
zwischendrin irgendein Unsinn raus.
AC schrieb:> Schleife:
Du nutzt nicht zufällig die Arduino-Umgebung? Da werden Timer durchaus
auch mit anderen Aufgaben betraut - ohne das Du es siehst.
Falls nicht - was macht Dein Programm denn sonst noch so?
S. Landolt schrieb:> er wird derzeit 355 oder 356, und daraus werden nach obiger Rechnung eben> 55.0176 bzw. 54.8631.
Wie einfach man es doch schreiben kann. ;-)
Meins wirkt dagegen so kompliziert...
Danke für die Erklärung das es schon mal mit der Auflösung zu tun haben
kann.
Wenn ich jetzt den Vorteiler auf 1 setze und die Zeile
1
frequenz=frequenz/1024;
in der Berechnung rausnehme, dann werden bei 50Hz, 2932,121 Hz
angezeigt. Die erste Stelle vor dem Komma und die Nachkomma stellen
zittern etwas.
Hab ich einen Fehler in der Berechnung?
Dann würde ich Timer1 ohne Vorteiler laufen lassen.
Auf dieser "seite" (Display) wird nur die Frequenz ausgegeben und auf
einer anderen "seite" 2 ADC Werte. Die Display Seiten schalte ich mit
einem Taster um.
c-hater schrieb:> Der Code muss auf ein> ICP-Ereignis reagieren, bevor das nächste eintritt
Das habe ich bei 55Hz einfach mal als gegeben vorausgesetzt.
d.h bei 400000 Zählschritten macht er über 6 Overflows und ich addiere
nur 1?
Wenn ich den Vorteiler auf 8 setze dann dauert ein zählschritt 400ns,
also bei 20ms (50Hz) sind es 50000. Schlimmstenfalls bei 45Hz 55555,56
zähltakte...wäre dann ein overflow?
Yeah...danke euch!
Habe jetzt den Vorteiler auf gesetzt und bei 45Hz werden 44,996Hz und
bei 65Hz werden 64,994Hz angezeigt. Und wenn überhaupt dann zuckt nur
die letzte Nachkommastelle. das ist dann ne Abweichung von nichtmal
0,01% das muss reichen...anstatt das bereits programmierte zu optimieren
habe ich mich verrückt machen lassen.
Danke nochmal