www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik erzeugen eines sinus mit variabler frequenz


Autor: Kervin Küchler (kernel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi.
Ich bin gerade ein bisschen am Testen mit nem ATmega32 und wollte jetzt 
mal nen Sinus mit variabler Frequenz erzeugen, um schöne Töne ausgeben 
zu können und später vielleicht auch mehrere Töne gleichzeitig ausgeben 
zu können (Überlagerung).

Ich hab mir beim Programmstart ne Sinus-Tabelle mit 64 Einträgen 
angelegt:
for (i = 0; i < 64; i++)
        sintab[i] = (127. * sin(2  PI  i /64)) + 127.;

Im weiteren Verlauf des Programms nehm ich immer einen Wert davon, geb 
ihn über eine 8-Bit-PWM (Timer 2) aus und erhöhe den Zähler, der auf 
eine Stelle in der Tabelle zeigt.
Über nen Tiefpass am Ausgangs-Pin ergibt sich dann auch ein schöner 
Sinus mit ca. 1 Hz bei Taktfrequenz 1 MHz.

Wie kann ich diese Frequenz jetzt zur Laufzeit ändern?

Danke schon mal.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wie kann ich diese Frequenz jetzt zur Laufzeit ändern?
Vielleicht durch Ändern der PWM-Frequenz?

> Danke schon mal.
Keine Ursache...

Autor: Einhart (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

mach z.B. das Holen des nächsten Tabellenwertes in der Interruptroutine 
eines anderen Timers. Die Änderung des Interruptzyklus dieses Timers 
ändert dann die Frequenz des Sinus.

Autor: Markus 8051 (markus_8051)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@johnny.m: Eben nicht!

@kernel: Du mußt die Frequenz ändern, mit der Du die Schleife aufrufst, 
die einen Wert aus der Tabelle holt, ihn ins PWM-Register schreibt und 
den Zähler erhöht. Dabei solltest Du daran denken, daß die maximale 
Frequenz, die Du über einen PWM-Ausgang ausgeben kannst um ein 
vielfaches unter der PWM-Frequenz liegt. Schließlich ist der PWM ein 
Tiefpass nachgeschaltet, daß die Aufgabe hat, die eigentlich 
PWM-Frequenz rauszufiltern. Je nachdem wie steil Dein Filter ist und wie 
sauber Du das Signal haben möchtest, mußt Du den Abstand von 
PWM-Frequenz und maximaler Ausgabefrequenz wählen.

Mit welcher Frequenz arbeitet denn Deine PWM?

Allgemein kann man aber sagen, daß PWM eine schlechte Methode ist, ein 
Audiosignal mit einem µC zu erzeugen. Da würde ich eher so einen ganz 
simplen D/A-Wandler, bestehend aus ein paar Widerständen an einem 
acht-bit-Port verwenden - mal vorausgesetzt, Du hast noch sowas frei.

Markus_8051

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist eine normale "DDS"-Sinuserzeugung. Um die Frequenz zu ändern 
variiert man die Sprungweite in der Tabelle, die Zeit zwischen den 
Tabellenwertausgaben bleibt konstant.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Eben nicht!
Stimmt natürlich. Man müsste dann ja auch die Tabellenwerte entsprechend 
skalieren. Und dabei ginge die ganze Auflösung den Bach runter...

Autor: Lupin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christoph damit verlierst du aber an auflösung, wenn möglich ist es 
besser die timer frequenz mit der die neuen werte geladen werden zu 
erhöhen.

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja sicher, jeder DDS hat Jitter. Je höher die Frequenz desto schlimmer, 
die Stufen sind ja ab der niedrigsten Frequenz gleich. Die Sinustabelle 
muß möglichst groß sein, so dass die niedrigste Frequenz gerade jeden 
Tabellenwert einmal aufruft. Mit PWM wird die Auflösung nochmal 
verschlechtert, denn die muß in der Frequenz noch deutlich über dem 
Tabellenauslesetakt liegen.

Autor: Loenny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei Verwendung des 16Bit Timers bekommt man mit einem 3,68640MHz Quarz 
eine Auflösung von delta_f=56,25Hz. Bei einer Periode des Sinus mit 8Bit 
ist die max. Frequenz f_max=13,619kHz.

delta_f = 3.68640MHz / 2^16

f_max = 2^8 * 3,68640MHz / 2^16

init = f_soll * 2^16 / 3.6864MHz

Ich weiß jetzt nur nicht ob man den Timer auch mehr als "eins" erhöhen 
kann.


for (;;)
TEMP = TEMP + init;

u_sin = sintab[TEMP(15:8)];

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich weiß jetzt nur nicht ob man den Timer auch mehr als "eins"
> erhöhen kann.

Das nicht. Aber mit dem CTC Modus kannst du dir
sehr einfach fast nach jeder beliebigen Taktzyklenzahl
einen Interrupt auslösen lassen.



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.