mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Rechteck Erzeugung mit stegeinder Frequenz


Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.?

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie hoch soll denn die Frequenz max. werden?

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ... ;-)

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael (Gast)
Datum:

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

Autor: Stephan Schwarz (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan Schwarz (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
tschuldigung, oben das ist der falsche Source Code - hier der aktuelle

Autor: Dirk B (Gast)
Datum:

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

Autor: Arno (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Datenblatt ab S.74, OC1A, Waveformgeneration...

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso: Du kannst auch

OCR1A = 460;

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

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stephan Schwarz (Gast)
Datum:
Angehängte Dateien:

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

weiss einer woran das liegen kann?

Autor: Stephan Schwarz (Gast)
Datum:

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

Autor: Stephan Schwarz (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.