www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik atmega8, pwm, tongenerator ganz einfach


Autor: Tobi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ich will mit dem Atmega8 ein paar Töne erzeugen, soll ganz einfach 
gehalten werden.
(Ja, ich hab die Suchfunktion benutzt, auch Google, und den ganzen Tag 
damit zugebracht, mich einzulesen, ich habe auch schon verschiedene 
Artikel über Wavetable-Synthesizer und DDS gelesen, aber eigentlich will 
ich nur ein paar versch. Töne erzeugen und gebe mich mit schlechtem 
gameboy-gepiepse zufrieden.)

Ich will die Töne per pwm erzeugen und gebe sie direkt auf nen kleinen 
laptop-lautsprecher. Mein bisheriger Code befindet sich im Ahang.

Der Atmega läuft mit 8Mhz, 8bit timer, kein Prescaler.
fPWM = 8MHz / 256, also ist die pwm-frequenz grob 32khz.
( ich habs auch mal mit prescaler 2 ausprobiert, aber da kam fast nur 
brummen raus).

Ich habe mir mal eine Sinuskurve vorgenommen, diese in 256 (wegen 
8bit-timer) diskrete Werte zerlegt und ein "lookup"-array erstellt.
(Wertebereich von 0 bis 256).

Per Interrupt-Funktion lese ich nun nacheinander die einzelnen Werte 
dieses arrays in OCR1A ein und erzeuge so die verschieden langen 
high-phasen der PWM.

Beim resultierenden Ton hört man nun deutlich Pausen, es hört sich fast 
an wie eine Sirene.

Jetzt zu meinen Fragen:
1. Woher kommen diese Pausen, es kann doch nicht sein, dass diese 256 
Werte so langsam ausgelesen werden, dass man "die Sinus-Kurve hören" 
kann?

2. Die Frequenz der PWM ändert sich ja nie, nur die Frequenz der 
Sinuskurve, die aus den gemittelten PWM-Phasen entsteht.
Welche Frequenz hat jetzt also mein Ton?

3. Wie kann ich ohne viel Aufwand andere Töne erzeugen?
Kann ich dazu einfach die Sinuskurve "stauchen" oder "ziehen"?
Und wie kann ich dann Töne bestimmter Frequenz "erstellen"?
Und müsste ich dann für jeden Ton, den ich verwenden will, eine eigene 
Sinuskurve erstellen und in ein lookup-table packen?

4. Ist es unbedingt notwendig einen Tiefpass vor den Lautsprecher zu 
bauen?

Autor: nixversteh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
const uint8_t  sinewave[1][256] PROGMEM=
...ist für mich 'n seltsames Array. Aber möglicherweise verstehe ich 
wieder mal nix.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>const uint8_t  sinewave[1][256] PROGMEM=

>...ist für mich 'n seltsames Array. Aber möglicherweise verstehe ich
>wieder mal nix.

Richtig, ist halt ein zweidimensionales Array. Ich denke man, dass er es 
später um weitere Töne erweitern will. Das PROGMEM schont den 
Arbeitsspeicher weil die werte direkt aus dem Flash gelesen werden. Evtl 
ist das auch schon das Problem, da der Flash nicht so schnell ist. Darum 
hört man auch Pausen. Vielleicht würde ich es erstmal ohne Progmem 
testen und später dann immer die Töne im RAM cachen.

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für den Tip, die Pausen sind jetzt weg, allerdings hört sich der 
Ton jetzt etwas verzerrt an..
Ein ganz einfacher Tiefpass wird aus 22nF und 100k-Widerstand gebaut, 
oder?
(hab ich so mehrfach im web zum glätten von pwm gesehen).

Autor: Tobi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, hab langsam doch noch etwas mehr verstanden..
Da die PWM eine Frequenz von ca. 32khz hat,
und ich den 8-bit timer benutze,
habe ich doch, wenn ich genau eine sinuswelle in 256 Werte packe,
32khz/256=125, also 125 Sinuswellen pro Sekunde, richtig?
Das wären dann 125 Hz, richtig?

Habe mir dazu ein kleines prog geschrieben, mit dem man Sinuskurven 
manipulieren kann (stauchen,strecken), und das die Sinuskurve i.d. 
positiven Bereich verschiebt (Werte sollen ja für PWM herhalten), und 
die Werte auf 0-256 normiert. Mithilfe der obigen Formel kann ich ja nun 
versch. Frequenzen erzeugen und speichern.

Habe mir jetzt drei Frequenzen, 500Hz, 600Hz und 700Hz generiert, aber 
das hört sich ziemlich mies an, immer noch entfernt von klaren tönen.

Verrechnet habe ich mich hoffentlich nicht, ich hab das ganze mal 
geplottet, ist im Anhang zu finden (geplottet hab ich die 256 Werte, die 
errechnet werden für 600Hz).

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist bei 8 Bit (=256 verschieden Werte) der größte Arrayindex nicht 255 
(Index fängt ja mit 0 an und müßte daher bei 255 enden)?

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:-) ja, hast recht, hab ich mittlerweile auch gemerkt, ändert aber 
leider nichts..

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um verschiedene Töne zu erzeugen, bringen verschiedene Array-Indizes 
nichts. Du brauchst eine Sinus-Tabelle, durch die Du verschieden 
schnell steppst, d.h. Du überspringst ab und zu Werte (bei hohen 
Frequenzen)  oder wiederholst Werte (bei niedrigen Werten).

Genau das macht eine DDS. Hast Du dieses DDS-Prinzip verstanden?

Du inkrementierts nicht jedes mal (i++), sondern addierst eine 
(Fixed-Point-)Konstante (und nimmts nur die oberen 8 Bit des 
16-Bit-Ergebnisses als Index ins Array).

Das schöne: die ausgegebene Frequenz ist direkt proportional zu dieser 
Konstanten.

Ich habe hier im Forum schon etliche Beispiele und Litertur-Links 
gepostet.

Viel Erfolg! Du bist schon ganz nah am Ziel.

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hab schon versucht, die schrittweise z.B. zu verdoppeln, mit magerem 
Ergebnis..

wenn ich hier nach DDS suche finde ich fast nur Beiträge über 
Hardware-Bausteine oder in Verbindung mit einem Widerstandsnetzwerk..

"sondern addierst eine
(Fixed-Point-)Konstante (und nimmts nur die oberen 8 Bit des
16-Bit-Ergebnisses als Index ins Array)"

Das verstehe ich leider gerade überhaupt nicht..

Aber nochmal, wenn ich verschiedene sinus-frequenzen in je eine 
lookup-tabelle packe, kann ich doch mit den versch. lookup-tabellen dann 
unterschiedl. töne erzeugen, weil ein sinus mit hoher frequenz doch 
einen höheren ton erzeugt als einer mit langsamer frequenz, oder?

Autor: Mattes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
push, interessiert mich auch

Autor: Telekatz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ungefähr so ist das gemeint:
uint8_t tone=0;

uint16_t counter= 0x0;
uint16_t rate = 0x100;

ISR(TIMER1_COMPA_vect){
  counter += rate;
  OCR1A=pgm_read_byte(&sinewave[tone][(counter>>8)]);
  }


Wenn du rate größer machst, läuft counter schneller durch und die 
Frequenz wird größer. Bei kleinerem rate veringert sich die Frequenz.

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habs jetzt schon soweit geschafft, dass das, was rauskommt sich 
wirklich wie töne anhört, und zwar astreines gameboy-gepiepse :-)

Hab zwar keine Ahnung, was er oben mit 16bit und 8bit abschneiden 
gemeint hat, aber ich hab jetzt mal, wie er gesagt hat, statt i++ zu 
wählen,
i += scale
gemacht, und scale erhöhe/erniedrige ich im Programm, dadurch kommen 
schonmal unterschiedliche Töne raus, weil er ja die sinuskurve mit hohem 
scale-wert schneller abläuft.

Aber irgendwas fehlt noch, wenn ich scale die ganze zeit erhöhe werden 
die Töne nicht immer höher, manchmal sind auch ziemlich schräge, etwas 
tiefere töne dabei (vllt wegen überlauf oder so)..

Ich werd mich morgen oder übermorgen nochmal dransetzen und mal 
versuchen, ne tabelle mit "sauberen" tönen zu erstellen, dass man auch 
mal melodien dudeln kann..

Ich hab mal meine bisherigen Ergebnisse hier in einem Artikel 
zusammengefasst:
http://www.infolexikon.de/blog/atmega-music/
Noch nicht ganz fertig, aber ich setz mich wie gesagt morgen/übermorgen 
nochmal dran und machs fertig!

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hab in deinen blog nur einmal kurz drübergeschaut, aber du redest 
immer bei 8 bit von 0 bis 256
es sind zwar 256 werte aber der wertebereich ist trotzdem von 0 bis 
255!!!!

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jo, hast recht, sorry, werds gleich ändern..

aber nochmal zu dem 8bit - 16bit problem..ich versteh immer noch net, 
welche 8bit ich da wie abschneiden soll?

Soll ich, wenn ich den sinus z.B. mit 1.5 abtasten will, nen float 
addieren, und der hat 16 bit, und ich schneide dann das nachkomma ab 
oder wie?

Autor: Telekatz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du änderst den Typ deiner zählvariable i auf uint16_t und nimmst als 
Index auf dein Sinuskurven Array nur die oberen 8 Bit von i.

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, hab jetzt mal versucht, das zu realisieren, die Tonhöhen ändern sich 
jetzt zwar entsprechend, Töne werden höher wenn ich scale erhöhe,
aber hören sich jetzt auch wieder sehr mies an..woran könnte das liegen?
uint16_t i=0;
uint8_t tone=1;
uint16_t scale=1;

static inline uint8_t highByte(uint16_t x){
        return(uint8_t)(x>>8);
}

ISR(TIMER1_COMPA_vect){
        OCR1A=pgm_read_byte(&sinewave[tone][highByte(i)]);
        i += scale;
}

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mhm...die abtast-rate kann ich ja jetzt feiner einstellen..einige der 
Töne hören sich "gut" an, also nicht schräg oder verzerrt...
gibts eine Möglichkeit, die "sauberen" Töne auszurechnen, Formel oder 
Richtwerte, oder muss ich jetzt jede einzelne Möglichkeit durchhören und 
aufschreiben??

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habs immer noch nicht gerafft..
mein index-counter hat jetzt 16bit, ist ja uint16_t.
d.h. er kann Werte zwischen 0 und 32767 annehmen.

indem ich aber nur die oberen 8 bit davon benutze, kann mein counter 
also wieder nur werte zwischen 0 und 256 annehmen.

Das hiesse, dass ich scale dann um 32767/256 = 128 erhöhen muss, wenn 
ich den Wert des Counters im Endeffekt um 1 erhöhen will, oder?

Ich hab hier mal ne Tabelle, von Tönen die ich benutzen möchte:
c'' = 523.25 Hz
d'' = 587.33 Hz
e'' = 659.26 Hz
f'' = 698.46 Hz
g'' = 783.99 Hz
a'' = 880.00 Hz
h'' = 987.77 Hz

Wenn ich jetzt als Sinus-Tabelle einen Sinus mit 100 Hz nehme,
wie muss ich dann Scale verändern, um auf die obigen Hz-Freqs zu kommen?

Bsp.: c'':523.25 Hz = 5.2325 * 100Hz => 5.2325 * 128 = 670
Das haut aber auch nicht hin.

Kann mir bitte jemand helfen?

Autor: Telekatz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1. Ein Byte kann immernoch nur Werte zwischen 0 un 255 annehmen.
2. Zwei Bytes können Werte von 0 bis 65535 annehmen (nicht nur bis 
32767)
3. Deine Sinustabelle hat keine Frequenz. Die 256 verschiedenen Werte 
des Arrays bilden genau eine komplette Sinuskurve.

Die Frequenz errechnet sich dann folgendermaßen:

f = (31259Hz * scale) / 65536

Autor: Tobi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
d.h. hiesse dann also,
dass ich den scale zu meiner gewünschten freq mit
scale = 65536/31259*f = 2.096 * f
berechnen kann.

Also wieder für c'' = 523.25 Hz:
scale = 2.096*523.25 = 1096,732,
also müsste ich dann für scale 1096 einstellen.

Hab ich gemacht, da kam dann wieder Gebrumme raus..
Wahrscheinlich hab ich wieder irgendeinen saublöden fehler im Code 
gemacht und finde ihn nicht..

Für die Hilfe zeige ich mich gern erkenntlich und schreibe nen Artikel 
fürs Wiki, sobald ichs hinbekommen hab!

Autor: Telekatz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nimm die Sinustabelle aus deinem ersten Beitrag.

Die Sachen mit den 100Hz und 300Hz Tabellen ist Murks! Die ergeben 
nämlich wenn mann sie aneinander setzt keinen Sinus mehr. Da spring der 
Wert beim Übergang vom letzten auf den ersten Wert plötzlich und das 
hört sich Scheiße an.

Autor: Tobi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
alles klar, hab jetzt wieder die sinus-tabelle aus dem ersten beitrag.
geändert hat sich leider immer noch nicht viel.
ich hab auch das gefühl, dass ichs immer noch nicht verstanden hab.
also zuerst mal sind mein counter und mein scale jetzt beide 16bit, 
haben also einen Wertebereich von 0 bis 65536.

Nachdem ich scale zum Index-Counter addiert habe, nehme ich vom Counter 
dann jeweils die oberen 8bit, habe dann also wieder Werte zwischen 0 und 
256, oder?

Inwieweit hilft mir das jetzt, dadurch verfeinere ich doch nichts?

Wenn ich scale immer um 256 erhöhe (also im Endeffekt ja dann dem 
Index-Counter immer 1 aufaddiere) bekomme ich klare töne, aber nicht 
proportional zum scale-wert, in nicht erkennbarer anordnung..

Eigentlich steigt doch die Frequenz mit steigendem scale-Wert stetig an, 
d.h. die Töne müssten immer höher werden?

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Nachdem ich scale zum Index-Counter addiert habe, nehme ich
>>vom Counter dann jeweils die oberen 8bit, habe dann also
>>wieder Werte zwischen 0 und 256, oder?

also mit den wertebereichen musst dir echt mal einprägen, ist zwar nicht 
weiter wichtig, kann dir aber bei berechnungen extrem auf die füße 
fallen:
8bit: 0 bis 255, aber 256 werte
16bit: 0 bin 65535, aber 65536 werte

Autor: Telekatz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie hört es sich denn an? Nimm´s mal auf und poste es.

Autor: Tobi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ok, das hier ist das soundfile zum code meines letzten posts.
ich erhöhe scale also die ganze zeit um 256, aber die Töne folgen 
aufeinander ohne erkennbaren zusammenhang..

Autor: Telekatz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probier es mal mit folgenden Änderungen:

const uint8_t  sinewave[1][256] PROGMEM= //256 values

volatile uint16_t scale=523;

for(uint16_t y=0;y<2096;y+=64){
    scale = y;
    char buffer[20];
    itoa(scale, buffer, 10);
    lcd_string(buffer);
    itoa((122*(scale/256)),buffer, 10);
    set_cursor(11,2);
    lcd_string(buffer);
    lcd_string("Hz");
    Delay_ms(100);
  }

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jab, mit den änderungen funktioniert es! es sind saubere Töne!
leider versteh ich noch nicht warum...?

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das liegt am Skalieren und an Fixedpoint-Arithmetik.
Du kannst Dir das obere Byte von i als Stellen vor dem Komma  und das 
untere Byte als Stellen nach dem Komma vorstellen.
Wenn der Wert i jetzt z.B. 400 ist, bedeutet das, Du erhöhst scale um 
400/256=1,5625.
D.h. beim ersten Mal ändert sich der scale>>8 um eins, beim zweiten Add 
aber um 2 , da 800 / 256 = 3,125 und vorher schon um 1 erhöht wurde.

Im Mittel eben um 1,5625


Beachte: die Frequenz von Halbton zu halbton: mit 12. Wurzel aus 2 = 
1,059... multiplizieren.


Zu den DDS-Beiträgen:
Wenn es um AD9xxx-Bausteine geht, ist eine Hardware-DDS (meist HF bis 
xxx MHz) gemeint.
Wenn ein R-Netzwerk vorkommt, bist Du schon richtig, denn es ist egal, 
ob Du die Werte über DA-Wandler oder PWM ausgist. Das DDS-Prinzip ist 
das selbe, nur die Ausgabe ist jeweils anders.

Noch zum Lesen:
Beitrag "Musik machen in Assambler"
Beitrag "Sinus generieren - welcher AVR am besten?"
www.myplace.nu/avr/minidds/index.htm

Suce auch nach DTFM, das wird häufig mit Software-DDS gemacht.
Oder nach Tonerzeugung oder Sinuston oder Sinusgenerator.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>fPWM = 8MHz / 256, also ist die pwm-frequenz grob 32khz
ach so, ist die pwm frequenz nicht:
Ausgangsfrequenz = (Quarzfrequenz/Prescale ) /(Timerauflösung*2)
also bei dir 8000000/1/512=15,6KHz (statt deiner angegebenen 32kHz)
da ja einmal raufzählen und wieder runterzählen eine periode ist 
(0..255..0)
ist aber auch nebensächlich

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ISR(TIMER1_COMPA_vect){
  OCR1A=pgm_read_byte(&sinewave[tone][(i>>8)]);
     i += scale;
  }

geht kompakter so:
  OCR1A=pgm_read_byte(&sinewave[tone][(i += scale>>8)]);


Außerdem würde ich i als Union gestalten, das hat den Vorteil, dass man 
ohne Bit-Geschiebe  auf ein einzelnes Byte zugreifen kann:
s.a. Beitrag "Re: In uint16_t HB und LB schreiben !? In C"

#define lo 0 // Abhängig von der Endianess des Systems!!
#define hi 1 // kann bei ATMEL anders herum sein ?!?
union {uint16_t u16;uint8_t u8[2];} i;

jetzt kann die obere Zeile so heißen:
  OCR1A=pgm_read_byte(&sinewave[tone][i.u8[hi]]);//high-byte


Zu den komischen Tönen: ein Grund ist, dass bei Dir das scale zu große 
Werte annimmt. Dadurch verändert sich scale während einer 
Sinus-Schwingung zu stark (hat extreme Frequenzmodulation).

Die anderen Gründe hat Telekatz ja schon genannt.


Außerdem gibt es eine Frequenzspiegelung, wenn scale größer als 32767 
wird, da dann das "Phase-Wheel" rückwärts läuft - gut, bei Sinus merkt 
man das nicht gleich, aber bei einer anderen Signalform (Sägezahn) läuft 
das Signal andersherum.
Erklärung: da die Summe wiederum nur 16 Bit hat, wird die Summe (scale) 
kleiner statt größer. z.B. 50000 + 40000 = 90000 , passt aber nicht in 
16 Bit rein, wird also auf 90000 - 65536 = 24464 abgeschnitten.

Zu Variablennamen: ich würde statt i  ddsSum  und statt scale  ddsAdd 
verwenden.


Zur Hardware: hast Du einen DC-Entkopplungskondensator am Ausgang 
eingebaut?
Sonst kann es sein, dass die Membran des LS durch den Gleichstrom 
anschlägt und deswegen Verzerrungen auftreten.

Suche mal bei Analog-Devices nach
"A Technical Tutorial on Digital Signal Synthesis", damit habe ich es 
damals gelernt.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, der 16bit-Add heißt dann
ddsSum.u16 += ddsAdd;

Die ISR ist am effektivsten in ASM programmiert.
Evtl. an eine höhere PWM-Frequenz oder eine kürzere Tabelle (64 oder 
128)denken. Könnte ein schöneres Ausgangssignal geben, vor allem bei 
höheren Frequenzen.

Ob das volatile notwendig ist?
Es wird ja in der ISR nicht verändert, und die ISR kann nicht davon 
ausgehen, dass i noch in einem Register steht.


Mit DDS kann man leicht mehrstimmige Melodien erzeugen, für jeden Ton 
eine eigene ddsSum, und alle gelookten Werte addieren.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zu www.myplace.nu/avr/minidds/index.htm :
hier wird die DDS in der Main gemacht, damit die komplette 
Prozessorleistung dafür verwendet wird.
Die Main besteht nur aus 6 ASM-Befehlen, welche 9 Cyclen brauchen. Die 
DDS läuft also bei ihm mit 11059200/9=1228800 Hz.
Resolution = fCPU/150994944 (9*2**24) 24=Breite des Phasenaccus
Die serielle Kommunikation (Frequenz- und Form-Änderung) geschieht im 
IRQ.


Ist wirklich einfach und straigt forward.


Andreas Schwarz hat ja als Facharbeit einen Generator gebaut (findest Du 
auch im hier bei den Artikeln), hast Du die Beschreibung gelesen?
Dort ist ein Schreibfehler: die ISR wird nicht 256000, sondern 
6553600/(24+1)=262144 mal pro Sekunde aufgerufen.
Deshalb ist für 1kHz das ddsAdd fa00 (64000): 
262144*64000/256/65536=1000.


Korrektur:
geht kompakter so:
  OCR1A=pgm_read_byte(&sinewave[tone][(i += scale>>8)]);

ist falsch geklammert:
  OCR1A=pgm_read_byte(&sinewave[tone][(i += scale)>>8]);


Und wenn Du einen linearen Sweep ("Accelerando") erzeugen willst:
#define i     ddsSum
#define scale ddsAdd
#define sweep ddsAcc
  OCR1A=pgm_read_byte(&sinewave[tone][(ddsSum += ddsAdd += ddsAcc)>>8]);

sweep muss natürlich viel kleiner als scale sein.
Der Wertebereich von ddsAdd muss eingeschränkt werden (wie oben 
beschrieben)  z.B. auf 16 Bit.
Hier könnte für eine feine sweep-Einstellung ein Umstieg auf 24 oder 
32-bit breites ddsSum angezeigt sein.



Das mit der kleineren Tabellengröße nehme ich zurück: eine große Tabelle 
(256) hat keine Nachteile, sondern nur Vorteile (automatischer 
Wrap-Around).

Autor: dan (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen und erstmal entschuldigung, dass ich diesen Thread wieder 
hervorkramen muss.

Ich beschäftige mich nun schon länger mit dem Erzeugen eines Sinus aus 
einer Funktionstabelle und dem skalieren /Frequenz verändern.
Hierzu habe ich mich an den Vorschlag:

ISR(TIMER1_COMPA_vect){
  counter += rate;
  OCR1A=pgm_read_byte(&sinewave[(counter>>8)]);
  }

gehalten. Dies funktioniert bei mir auch recht gut. Allerdings bin ich 
mir noch nicht sicher, wie ich die Rate genau (1.) berechne um eine 
bestimmte Frequenz zu erhalten.
2. Ich habe Fotos hinzugefügt, welche meine Problematik von einer 
fallenden Amplitude beim Erhöhen der Frequenz zeigen. Da ich mein Signal 
über einen Audioverstärker verstärken möchte, darf die Amplitude nicht 
zu groß/klein werden. Außerdem "zappelt" der Sinus und die Töne sind 
nicht so sauber.
3. Als Alternative möchte ich die einzelnen Werte in der Sinustabelle 
öfters wiedergeben, bevor ich zum nächsten Wert weitergehe. Dafür möchte 
ich Timer0 im Overflow Betrieb benutzen, mit TCNT0 würde ich dann die 
Frequenz einstellen wollen:

ISR(TIMER1_COMPA_vect){
  OCR1A=pgm_read_byte(&sinewave[i]);
  }

ISR(TIMER0_OVF_vect)
{
  TCNT0=200;
  i++;
}

mit:

// initial OCR1A value
OCR1A=128; //80;
//Output compare OC1A 8 bit non inverted PWM
TCCR1A=145; // =0x91;
//start timer without prescaler
TCCR1B=1;
//enable output compare interrupt for OCR1A
TIMSK=66; // timer0 interrupt overflow enable
TCCR0B=0b00000001; // kein Vorteiler
TCNT0=1;
//enable global interrupts
sei();

Leider führt dies zu keinem Sinus mehr und der Ausgang bleibt eine Zeit 
lang auf high und schaltet nur kurz etwas verauschtes am Pin.

Ich verwende einen Attiny2313, der mit einem Quarz auf 12Mhz getaktet 
wird.
Vielen Dank schonmal für eure Tipps,
dan

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.