Forum: Mikrocontroller und Digitale Elektronik Rechteck Erzeugung mit stegeinder Frequenz


von Stephan Schwarz (Gast)


Lesenswert?

Ich hab nun einiges ausprobiert.  Leider alles ohne den erwünschten
Erfolg.
Es muss ein Rechteck erzeugt werden, bei dem sich die Frequenz ständig
erhöht. Die Frequenz läuft aber leider nicht linear, sondern nach einer
e-Funktion. Die immer aktuell berechnet werden muss.

T=1/(10*2^(t/60))

Kann mir da jemand Möglichkeiten nennen.?

von crazy horse (Gast)


Lesenswert?

Wie hoch soll denn die Frequenz max. werden?

von Stephan Schwarz (Gast)


Lesenswert?

10-500 Hz und das ganze soll über 340 sek. langsam hochlaufen.
Das grösste Problem ist, das Die Berechnung schon 3mS in Anspruch
nimmt.
Im Moment berechne ich einfach die Impulsdauer in einen Timerinterrupt.
Funktioniert auch ganz gut, aber ich sehe halt diese 3mS immer als Pause
in meinen Signal.

von Sebastian (Gast)


Lesenswert?

Ich würde die gar nicht aktuell berechnen, sondern EIN mal berechnen und
in einer Tabelle (im Flash oder ext. EEPROM) ablegen. Dann brauchst du
nur noch einen Timer mitlaufen zu lassen, der dafür sorgt, dass du
jeweils den korrekten Wert aus deiner Tabelle liest. Ein Flash-Zugriff
dauert ein paar ns; das ist ja schon ein ziemlicher Gewinn gegenüber
deinen 3ms ... ;-)

von Stephan Schwarz (Gast)


Lesenswert?

Hab auch schon über eine Tabelle nachgedacht, aber es wäre schon eine
ganze Reihe an Werten.
340S lang ist die Reihe. Es sollten wohl 3 Aktualisierungen pro Sekunde
sein. Das macht dann ca. 1000 Werte.
Du meinst also die Werte sollten im Programm berechnet werden, oder
eher extern von Hand berechen und dann in das Programm eingeben?
Wie lege ich die denn in den Flash/EEPROM.

von crazy horse (Gast)


Lesenswert?

vorher berechnen und im Flash ablegen. Kann man prima mit Excel machen.
Geht aber auch mit Berechnung zur Laufzeit. Wenn du sagst, 3
Aktualisierungen/s hast du doch 333ms Zeit, den nächsten Wert zu
berechnen.

von Michael (Gast)


Lesenswert?

3 Aktualisierungen pro Sekunde bedeuten, da0 du 300ms Zeit für die
berechnung hast. Wo ist denn dein Problem?
Michael

von Stephan Schwarz (Gast)


Angehängte Dateien:

Lesenswert?

Ich lasse im Main aber eine Schleife laufen. Diese NOP-Schleife
bestimmt einfach die Länge des Impulses. Im Timerinterrupt wird die
Länge berechnet. Und währende die Berechnung im Timerinterrupt läuft
geht eben nix in der Schleife.

Siehe Anhang

von Stephan Schwarz (Gast)


Angehängte Dateien:

Lesenswert?

tschuldigung, oben das ist der falsche Source Code - hier der aktuelle

von Dirk B (Gast)


Lesenswert?

Mach doch die Frequenz auch mit einem Timer.
Dann musst du nur noch alle 330ms das
Timerregister aktualisieren.

von Arno (Gast)


Lesenswert?

Mit einem AVR würde ich folgendes machen:
Timer0  auf PWM einstellen,der läuft dann alleine.
Timer2 Interrupt:output compare register 0 mit Werte aus Tabelle oder
berechnete Werten füttern.

Arno

von crazy horse (Gast)


Lesenswert?

Du solltest es genau umgekehrt machen: Die Impulserzeugung mit dem
Timer, Berechnung des nächsten Wertes in der Main, dann warten. Ich
würde soagar  2 Timer benutzten:
Timer0 für die Erzeugung des update-Taktes, Timer1 für die eigentliche
Erzeugung des Signals.
Timer0: 333ms Interrupt, bewirkt nichts weiter, als einen (vorher
berechneten) Wert in eine Variable zu schreiben (nennen wir sie mal
reload) und ein Bit (timer_ready) zu setzen.
Timer1: Modus toggle OC1 on compare, Interrupt bei compare.
Der compare-int macht auch nichts weiter, als den Timer zurückzusetzen
und das OCR-Register mit dem reload-Wert zu laden.
Ganz einfach, und noch jede Menge Zeit für den MC, sich zu langweilen.

main: warten, bis das timer_ready-Bit gesetzt ist, das Bit wieder
löschen, den nächsten Wert (reload_next) berechnen, und dann von vorne.

von Stephan Schwarz (Gast)


Lesenswert?

@ crazy horse

Wo ist denn der Modus "toggle OC1 on compare" im Danteblatt
beschrieben. Es geht um einen ATMEGA8.
Ich hab leide nix im Datenblatt gefunden.
Sorry, wenn ich heute viel Frage, aber die Zeit drückt extrem.

von OldBug (Gast)


Lesenswert?

Datenblatt ab S.74, OC1A, Waveformgeneration...

von crazy horse (Gast)


Lesenswert?

Mit dem Mega8 wirds noch einfacher (war nicht irgendwo die Rede von
90S2313?), da kannst du noch die CTC-Funktion nutzen (automatisches
Rücksetzen des Zählers bei OCR1A).

TCCR1A=1<<COM1A0;
TCCR1B=(1<<WGM12 | 1<<CS11);
TIMSK =1<<OCIE1A;

Timer 1 läuft mit clk/8, toggle on OCR1A, Int on OCR1A
Den OCR-Int brauchst du eigentlich gar nicht mehr (timer1 reset wird
automatisch durchgeführt), die neuen Werte nach OCR1A könntest du von
der Timer0-ISR aus reinschreiben. Allerdings musst du dann aufpassen
(Zähler liegt bereits über dem neuen OCR-Wert, aber unter dem alten ->
in diesem Zyklus wird der Ausgang gar nicht angesteuert). Besser mit
OCR-Interrupt, dann kann gar nichts passieren.

von Stephan Schwarz (Gast)


Lesenswert?

TCCR1A=1<<COM1A0;      // Toggle OC1A/OC1B
TCCR1B=(1<<WGM12 | 1<<CS11);     // CTC & clk/8  Takt=2.17014µS
TIMSK =1<<OCIE1A;      // Timer/Counter Output
                                      compare a Match Interrupt enable
OCR1AL=943;


sollte mir eigentlich 500 Hz bringen  - stimmt das?

von crazy horse (Gast)


Lesenswert?

nö.
Der Timer erzeugt ja jeweils nur eine halbe Periode des
Ausgangssignals.
Willst du 500Hz, brauchst du eine Peridendauer von 2ms, OCR muss also
nach 1ms kommen.
1000µs/2.17014µs=475.

von Stephan Schwarz (Gast)


Lesenswert?

1000µs/2.17014µs=460         sagt mir zumindest mein Taschenrechner.

Ich messe eine Frequenz von 1124 Hz --->  sagt mir mein MC und das
Ozsil.

Seltsamer Weise erhalte ich auch bei einem doppeltem Wert von 920 nicht
die halbe Frequenz, sondern 1504 Hz.

von OldBug (Gast)


Lesenswert?

Nunja, das wird wohl daran liegen, daß für OCR1AL bei 0xFF schluss ist
;)

OCR1AL = (460 & 0xFF);
OCR1AH = (460 >> 8);

Oder bin ich da jetzt auf dem Holzweg?

von OldBug (Gast)


Lesenswert?

Achso: Du kannst auch

OCR1A = 460;

Schreiben, wenn ich das grad richtig gelesen habe...

von crazy horse (Gast)


Lesenswert?

jo, 460 ist korrekt, hatte ich wohl einen Tipfehler.
Hast wahrscheinlich noch einen Fehler beim Laden des OCR1A-Registers.
Du musst einen 16bit-Wert schreiben, dabei unbedingt die Reihenfolge
beachten (ganz beliebter Anfängerfehler), erst OCR1AH (0x01), dann
OCR1AL (0xCC) für 460dez.
Einige Compiler unterstützen direkt den 16bit-Zugriff:

unsigned int reload;
OCR1A=reload;

von Stephan Schwarz (Gast)


Lesenswert?

"ganz beliebter Anfängerfehler" !!!!
Was ich gerade damit bewiesen hab!!
Dachte ich köönte einfach in das L Byte reinschreiben und es wird dann
in H Byte weitergeschreiben.

500 Hz sind da!!  Juhu

Dann geben ich mich nun mal an die Berechnung meiner Werte.
Neben bei mal ganz herzlichen Dank für die Info`s hier.

von Stephan Schwarz (Gast)


Angehängte Dateien:

Lesenswert?

Nun hab ich Trouble mit dem Timer0.
Er läuft nur kurz an und stop anschliessend.

weiss einer woran das liegen kann?

von Stephan Schwarz (Gast)


Lesenswert?

Anscheinend stören sich die beiden Timmer. Wenn ich den Timer1
deaktiviere, läuft Timmer 0 durch

von Stephan Schwarz (Gast)


Angehängte Dateien:

Lesenswert?

Ok die Teimer laufen nun, aber ich erhalte leider keinen Wert aus dem
Timer0 zurück.
Ich möchte damit die Programmlaufzeit bestimmen um den Wert (t)  in die
Berechnung der aktuellen Frequenz einfliessen zu lassen.
Aber der Wert n_overflows, der mir die Anzahl der der Overflows zurück
geben soll, ändert sich nicht.

Kann mir da nochmal jemand weiterhelfen?

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.