Forum: Compiler & IDEs Sinus mit atmega16 erzeugen


von Oliver P. (olipir15)


Angehängte Dateien:

Lesenswert?

Hallo :-)

Ich versuche gerade mit einem atmega16 einen Sinusgenerator aufzubauen.
Die Schaltung ist relativ simpel aufgebaut:

- atmega16
- 16MHz Quarz
- an PortB befindet sich ein 8Bit R2R DAC

Den R2R DAC habe ich auf einer kleinen Lochrasterplatine aufgebaut. Der
atmega16 befindet sich auf einem STK500.

Die Schaltung/Software funktioniert grundsätzlich.

Ich bin mir jetzt etwas unsicher was die Berechnung der
Ausgangsfrequenz angeht. - Ich habe mal mein kleines Programm
angehängt.

Konzept des programms ist folgendes:

- Timer1 zählt mit der Quarzfrequenz (CS10 = 1)
- Bei OCR1A comparematch wird ein INT ausgelöst. (OCIE1A = 1)
- Bei comparematch wird TCNT1 auf 0 zurückgestellt (WGM12 = 1)

- Im INT wird ein Wert aus der Sinustabelle sintable[16] im PROGMEM
ausgelesen und auf den DAC ausgegeben. Danach wird i um 1 hochgezählt,
um beim nächsten INT den nächsten Wert aus der sintable zu holen. Nach
einer Periode (16 Werte) wird i auf 0 zurückgesetzt.


... ich dachte mir mal ganz unbedarft und naiv, dass ich der OCR1A
comparewert wie folgt berechnet: ;-)

Quarzfrequenz  INTs pro Periode  Ausgangsfrequenz

Bei einer gewünschten Ausgangsfrequenz von 1750Hz und 16 INTs (bzw.
Werte) pro Periode komme ich auf einen comparewert von ca. 571. (Da
sich ein Divisionsrest ergibt, sollte die theoretische Ausgangsfrequenz
bei ca. 1751,3 Hz liegen)

so g ;-)... - bis jetzt theoretisch alles schön und gut... - nach
aufbau der Schaltung musste ich aber feststellen, dass die erzeugte
Ausgangsfrequenz bei ca. 1645 Hz liegt. (comparewert 571)

...nach einigen Experimenten habe ich herausgefunden, dass man mit
einem Comparewert von 537 relativ genau auf eine Ausgangsfrequenz von
1750 Hz kommt... - das finde ich auch schon mal nicht schlecht... :-)

...jetzt würde ich nur noch gerne verstehen, welchen Fehler ich bei der
Berechnung des Comparewerts gemacht habe... :-)

- Kann mir evtl. jemand einen Hinweis in dieser Richtung geben? :-)


Vielen Dank & Viele Grüße

Oliver

von Werner Hoch (Gast)


Lesenswert?

Deine Bedingung in der ISR ist falsch.

Du gibts 16 mal den Wert aus und beim 17. Mal setzt du den Zähler
zurück.
Folge: dein Sinus ist um 1/16 zu langsam (und ist kein schöner sinus
mehr)

SIGNAL (SIG_OUTPUT_COMPARE1A) {
    if (i > 15)
       i=0;
    PORTB = pgm_read_byte(&sintable[i]);
    i++;
}

von Oliver P. (olipir15)


Angehängte Dateien:

Lesenswert?

Genau das war das Problem! :-)... - Vielen Dank für den Hinweis! ...ich
hatte mir den code mindestens 100x angeschaut und immer nach einem
fehler bei der Timerinitalisierung gesucht... :-)

Jetzt stimmt auch die Frequenz :-)) - siehe Anhang.

Besten Dank nochmals! :-)

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.