Hallo!
Ich hab schon mehrere Einträge im Forum zu FFT gefunden, jedoch nicht
wirklich das passende.
Ich will ganz simpel die Amplitude von drei Frequenzbereiche aus einem
Audiosignal erhalten. Zum Beispiel der Mittelwert zwischen 80 und 250
Hz, dann der Wert von 350 bis 550 Hz und als letzten Wert zwischen 750
Hz und 1500 Hz.
Die Abtastrate wäre mit 100ms voll ausreichend.
Leider peil ich des mit FFT überhaupt nicht. Vielleicht ist dieses
Verfahren für meine Bedürfnisse auch schwachsinnig. Deshalb brauch ich
eure Hilfe.
Die Schaltung soll auch so einfach wie möglich sein. Am besten ohne
großen Aufwand direkt in einen ATMEGA8. Meint ihr das es funktionieren
könnte?
Hatte auch immer an den BA3830, ein Bandpassfilter, gedacht, aber den
gibts nirgens mehr zu kaufen. Ich wäre dann über mehrere AD-Eingänge in
den µC gegangen, um die Werte dann im eigentlichen Programm zu nützen.
Danke im Vorraus.
Simon
Ich wurde es so machen :
1. Bestimmung von "sampling-frequency" : F (mindestens 2*1500)
2. Bestimmung von wie viele Werte pro band brauche ich. W
3. Quellcode von FFT bekommen/schreiben
100 ms maximal pro rechnung ?... toll
Für 1500 Hz Maximal:
10 kHz sampling freq.
512 "samples" (512*10 us = 5,12 ms) pro rechnung gibt ein Wert je ~20
Hz, nicht schlecht. und vielleicht machbar.
4 Anregungen:
BP Filter
ggf. bei MAXIM scheuen
andere habe aber auch welche, MAXIM schickt muster zu uni-s
Analog geht das auch: da gibt-s software, die die
schaltung auslegt im Internet.
digi. Filter können auch mit dem uC gemacht werden und dann
einfach eine max. wert-bestimmung = Ampli. des Freq. bereichs.
FFT braucht ggf. nicht vollständig berechnt zu werden, wenn:
- freq bekannt
- abtast bekannt, etc.
Also Sampling-Frequenz wäre 3kHz, weil ja 1500 Hz maximale Frequenz.
Ein Wert je 20Hz wäre sogar zu übertrieben. Denke mit 256 Samples würde
es auch reichen. dann hät ich 40 Hz.
Also zwischen 80 und 250Hz (sind 170) würde es mir ca. 4 Werte liefern,
daraus dann den Mittelwert und ich hät was ich brauch.
Mit 100ms mein ich nur, wie oft ein neuer Mittelwert akualisiert werden
soll. Also wie oft die ganze Rechenoperation ausgeführt wird.
Punkt 3 ist ein kniffliger Punkt. Ich kenn mich überhaupt nicht mit FFT
aus. Bin deshalb nicht in der Lage, mir mal schnell einen Code zu
schreiben. Des weiteren sind meine Kentnisse in Assembler <= 1%.
Es wäre daher echt nett, wenn jemand einen Assambler-Code so anpassen
könnte, dass dieser einfach nach dem Aufrufen drei Variablem mit dem
entsprechenden Wert füllt.
mfg Simon
Was Christian hat gesagt ist Korrekt, ein Digitales Filter kann im
prinzip alles eingfacher machen. Gibt schon hier ein Thread. Hast du es
gelesen ? (ich hab nicht)
FFT Quellcode, gibt jede menge. für AVR... ich glaube gibt (ich habe für
HC11 und sicher es ist nutzlich).
hier: avr FFT auf asm :
Beitrag "Wer kennt diesen Hersteller ?"
Viel Spaß
Ale
Hallo Ale,
klick mal selbst Deinen Link (Beitrag "Wer kennt diesen Hersteller ?")
an ;-))
Da Deutsch scheinbar nicht Deine Muttersprache ist:
"panzerfahr'n" ist eine (in diesem Fall humorvoll gemeinte) Verkürzung
von "Panzer fahren" und bedeutet in etwa "Es würde sehr viel Spaß machen
mit einem Panzer durch die Gegend zu fahren und ohne Rücksicht auf
Verluste einfach alles platt zu walzen".
CU
Das war blöd ! Sche***e Copy und Paste !!!!!
Die richtige link war :
Beitrag "FFT auf dem AVR"
Ich wollte kein Spaß mit seine Frage machen !, Entschuldigung :-)
Es tut auch mir leid. Ich wollte mich nicht lustig machen.
Ich wollte (auch) darauf hinweisen, dass der Link nicht richitg ist.
Wenn man auf der Seite ganz nach unten scrollt, kommt ein Bild von einem
Panzer. daher mein amüsante Frage. Weil es doch so garnichts mit FFT zu
tun hatte. Was auf keinen Fall böse gemeint!
Beitrag "Re: Wer kennt diesen Hersteller ?"
sorry for that
AxelR.
Na super, 9 Antworten, aber irgendwie doch nicht wirklich hilfreich. Hät
mir mehr erwartet.
Was mir noch bei den ganzen Schaltungen aufgefallen ist, ist der MAX293.
Kann man das nicht auch ohne den machen. Grad für meine Aufgabe müsste
es doch anders gehen.
mfg Simon
So, ich bins nochmal.
Hab grad rausgefunden, dass für meine Anwendung der Goertzel-Algorithmus
voll ausreichend ist.
Hab auch einen Code gefunden, der einen DTMF-Decoder entspricht.
Theoretisch müsste man den Code doch einfach nur auf meine Frequenzen
umschreiben. Wollte den Code eigentlich auch in Basic haben. Außerdem
weiß ich nicht, was im Code der ADC-Wert ist, und in welcher Variable
die Level stehen.
mfg Simon
@Simon:
"Na super, 9 Antworten, aber irgendwie doch nicht wirklich hilfreich.
Hät
mir mehr erwartet."
Ich habe auch viele mahle etwas gefragt und nicht immer die Antwort ich
habe gedach gut war und ich erwartete bekommen. Es ist so, vielleicht du
hast Glück und jemand kennt ganz genau was du brauchst, manchmal nicht.
Aber über was du zuerst gefragt hast glaube ich, es wäre 2 gute
möglichkeiten.
(Ich wurde nicht viel von Float rechnen mit ein AVR, am besten mit int,
wir viel schneller sein).
Ich dachte, es ginge um die Messung von drei Amplituden, dafür ist
Goertzel nicht so geeignet, eher für Schwellenüberschreitung, also
"Tondecoder".
Soweit ich das verstanden habe, ist ein "Goertzel" ein einfacher
IIR-Bandpass, der periodisch wieder genullt wird, da er sonst überläuft.
Es wird nur in diesem Zeitraum entschieden, ob die Amplitude innerhalb
der Bandbreite des Filters einen Schwellenwert überschritten hat. Für
einen echte Messung müßte ja ein Messwert herauskommen.
Für ein Discolauflicht reicht das allemale.
Man gibt einen Wert vor und zieht dann den Takt aus der Musik. Ich
denke, so etwas in der Art soll es wohl werden.
Axel Rühl wrote:
> Für ein Discolauflicht reicht das allemale.> Man gibt einen Wert vor und zieht dann den Takt aus der Musik. Ich> denke, so etwas in der Art soll es wohl werden.
Wenn das stimmt, dann frag ich mich doch glatt obs nicht ein
paar simple RC-Filter auch tun:
http://www.b-kainka.de/bastel85.htm
Es gibt da auch eine recht nette FFT Bibliothek für den AVR. (müsste nur
noch den Link wiederfinden). Die Verwende ich selbst, um in einem etwas
umfangreicheren DMX-Controller eine Lichtorgel und einige andere Späße
zu implementieren.
Da ist aber auch noch ein guter Happen Analoggekrümele auf Lochraster
vornedran (das meiste davon aber nur Beaterkennung). FFT braucht aber
auf jeden Fall richtig böse viel Speicher. Für die 256 Samples wären das
512 Bytes für int16_t samples. 1kB für den komplexenwertigen
Eingangspuffer und ggf. nochmal 1kB für den Ausgangspuffer. Da ist dann
recht schnell der RAM voll bis unter'n Rand.
Danke für die tollen Antworten!
Hät schon gedacht, ich werd meine Idee bald verwerfen können.
@ Hagen Re:
Kann ich dann einfach die Goertzel-Funktion immer wieder
(timer-gesteuert) aufrufen und der Variable Sample den Analogwert von
meinem ADC-Eingang geben, also die Variable durch den Eingang ersetzten?
In r[] stehen dann so wie von mir gewünscht die Amplituden?
@ Axel Rühl:
Genau das hab ich vor. Ein Discolauflicht. Werde dann einfach die drei
Pegel von meinen Frequenzen vergleichen und dann einfach gesagt jeweils
ein Licht switchen.
@ Karl Heinz:
Genau die Schaltung hab ich schon testweise aufgebaut. Bin aber vom
Ergebnis stark enttäuscht. Entspricht leider nicht meinem Vorhaben, denn
die Verbindung zum µC und die Frequenzen machen Probleme.
@ Andreas Lang:
Super, dass trifft auch auf mich zu. Es handelt sich später auch um
einen DMX-Controller, der die Sound-to-Light-Steuerung in ordentlicher
Qualität bereitstellt.
Meinst du wirklich, dass der Goertzel-Algorithmus nicht ausreicht?
Wer nett, wenn du doch noch die Bibliothek finden könntest.
Wär cool, wenn Ihr mir auf diese Fragen auch noch Antwort geben könnt.
ciao Simon
@Simon:
Ich poste einfach mal hier den Code, die FFT-Bibliothek ist von Chan
(elm-chan.org). Das Ganze befindet sich sehr stark im Fluss, die
Hardware ist ein mittelschweres IC-Massengrab und auch sonst ist das
drumherum nicht so dolle derzeit. Was man aber (denke ich mal) verwerten
kann, ist der DMX-Transmitter (separater Mega8, wegen Speicherplatz) und
mal die Grundsätzlichen Funktionen (Master Fader, All On, Crossfade,
Interruptbsierter ADC und FFT2Light).
@All:
Der Code im angehängten File ist noch sehr pre-alpha. Irgendwie
funktioniert er, ist aber weder gut kommentiert noch irgendwas. Ich
werde aber wohl die relevanten Stellen noch hier im Forum hervorheben.
Brauchbar ist schonmal der Kram im Ordner dmxtx. Das ist ein kompletter
DMX-Transmitter mit SPI-Interface. Das DMX-Timing wird komplett im mit
Interrupts erledigt. Der Code ist eher mäßig gut kommentiert, aber
insgesamt doch recht verständlich, da nicht zu komplex. Der Kram in
chaser.c ist allerdings recht wüster Spaghetticode.
Leider habs ich net so mit C. Was hats mit ffft.h auf sich?
Wär echt no ah Sach, wenn du dein Code erklären könntest.
Für die Datei dmxtx.c interessiere ich mich auch. Du hast geschrieben,
dass man den Chip über SPI ansteuern und dadurch DMX-Daten versenden
kann. Wie schaut da des Protokoll und natürlich der Schaltplan aus?
mfg Simon
Der DMX-Transmitter-Code ist für einen Mega8@16MHz geschrieben. Man
hängt ihn einfach 1:1 an den SPI der Master-CPU (trennbar, wenn man ISP
macht) und sendet mit der Master-CPU Daten per SPI.
Mit zwei Nullbytes hintereinander kann man eine aus dem Tritt geratene
Übertragung wieder resetten, ansonsten: 1. Byte Kanalnummer, 2.Byte
Kanalwert.
Am TXD hat man dann DMX512 mit einem max 255 Kanäle großen Universe.
Die größe des Universe ist im Quelltext des Transmitters angegeben und
lässt sich dort leicht ändern. Der Transmittercode ist recht kompakt und
sollte auch ohne große C-Kenntnisse verständlich sein.
ffft.h ist die Include-/Headerdatei für die Assembler-FFT-Bibliothek
(ffft.S).
> Leider habs ich net so mit C.
Mir gings mal ähnlich. Aber es wäre geschickt, wenn Du dich für etwas
wie einen DMX-Controller in C einarbeitest, da das ganze mit BASIC,
insbesondere mit BASCOM echt Tierquälerei ist.
Was du aber auf jeden Fall brauchst ist viel RAM. Schon ein ganz
normaler Chaser (Lauflicht) braucht bei z.B. 12 unterstützten Kanälen 12
Bytes pro Schritt. Will man das dann noch etwas intelligenter oder mit
variabler Fade-Time, dann wirds noch mehr. Ein Speicherplatz für einen
Chaser sollte mindestens 32 Schritte fassen können. Die sind z.B. ganz
schnell weg, wenn man evtl. irgendwelche Scanner oder was auch immer
damit steuern will. Für Anwendungen, bei denen nur Lampen dran sind,
würden wohl auch noch 16 Positionen reichen.
Ganz nett sind sogenannte Memorys und Memory Chaser. Man erstellt dann
erst einzelne Lichtstimmungen (Szenen) und speichert diese. Dann packt
man diese in einen Chaser. Damit kann man sehr schnell sehr hübsches
Licht machen.
Wenn man dann noch mehrere Chaser parallel zusammenmixen kann, ist das
dann ganz edel, braucht man für die Kellerdisco aber eher nicht.
Hier tun es schon 3-12 (je nachdem, wieviele Lampen man hat)
unterschiedliche Chaser, die hin- und wieder mal gewechselt werden.
Wenn man LED-Pars als Lampen verwenden möchte (gerade im Partykeller
recht nützlich, weil die nich eben mal 0,3-1kW pro Lampe ziehen) braucht
man pro Lampe schon mal 5-6 Kanäle, ein einfacher Scanner ist mit 7-11
Kanälen dabei. Deswegen gleich einen AVR mit iel RAM nehmen und Sachen,
wie Bedienelemente (LC-Display, Menüführung oder was auch immer) gleich
in einen extra µC packen und den per UART anbinden.
Der Schaltplan ist so 'ne Sache. Das Gerät dazu ist stückchenweise um
einen Mega16 herum gewachsen und verteilt sich auf 2 Ebenen von
Lochrasterkarten. Das meiste darauf ist eine eher mittelmäßige
Beaterkennung (Schaltplan siehe ELV-Beatcounterbausatz, auf deren
Website) und was man halt sonst noch so braucht (Erzeugung der negativen
Betriebsspannung für die OPs, Gleichrichter und RC-Glied fürs VU-Meter
(und eine eventuelle AGC, damit man nicht immer von hand auf 0db
einstellen muss; das passt dann aber in das jetzige Gehäuse nicht rein).
Da das ganze in erster Linie frei Schnauze bzw "Stift und Schmierzettel"
entstanden ist, werde ich wohl zunächst einmal anhand des Quelltextes
die direkte Peripherie/Anschlussbelegung des Mega16 reverse-engineeren.
Den Analogkram bekomm ich auch so wieder zusammen, wenn ich das Teil
wieder vor mir liegen hab (liegt aber halt grad 200km entfernt).
Hier mal eine grobe Übersicht, was da so drin ist:
- Mega16
- Mega8
- Quarzoszi 16MHz
- 3 LM324
- MAX232
- irgendwas, das zum OPA2134 pinkompatibel ist (der ist viel zu
hochwertig dafür, steckt aber trotzdem im Sockel, weil ich grad nix
anderes dahatte)
- MC34063 oder wie er heißt
- Jede menge Hühnerfutter (2 SMCC-Spulen, diverse Kondensatoren und
Widerstände)
- 2 Potis
- 2 Kippschalter, davon einer mit Mittelstellung
- 1 Duoled
- 13 normale LEDs
Bilder hab ich leider grad keine von. Werde aber mal welche machen, wenn
ich das Gerät wieder zu fassen kriege.
Danke für die Beschreibung zum DMX-Transmitter. Ach ja, könnte mir
jemand ne hex-File vom Code schicken. Hab grad kein C-Compiler parat.
Und noch ne Frage: Müss ich stetig über SPI die Bytes für jeden Kanal
schicken oder merkt sich der µC die letzten Settings?
Output wird wohl TxD sein?
Bin schon gespannt auf die Bilder und vielleicht einen groben
Schaltplan.
Unterstützt der ATMEGA8 eigentlich Hardware-Multiplikation und Addition?
mfg Simon
Der µC merkt sich die Kanalwerte. Mit dem Code, wie er jetzt ist, hat
man 128 Kanäle. Der Mega8 hat einen Hardwaremultiplizierer. Addieren
kann er auch. Wenn du einen MAC (Multiply an Accumulate) meinst, den hat
er nicht. Da der ATMega aber sehr schnell multiplizieren und addieren
kann, kann man das in Software nachbilden.
z.B. in C:
1
uint16_tsumme;
2
uint8_twert[8],faktor[8];
3
//Werte auffüllen
4
summe=0;
5
for(uint8_ti=0;i<8;i++){
6
summe+=((wert[i]*faktor[i])>>8);
7
}
Wobei man bei einem Lichtpult wohl eher Kanalwerte gewichtet addieren
und dann den Kanalwert auf 255 begrenzen möchte:
1
if(summe>0xff)
2
sume=0xff;
Das .hex-File hänge ich mal an.
Lade dir aber mal am besten WinAVR runter.
Dann musst du nur noch in das Verzeichnis zu wechseln und "make"
eingeben.
Wobei man das ggf. mit Bitschieben schneller machen kann. Allerdings ist
255*255 um 8 Bits nach rechts geschoben nur 254. Aber das kann man wohl
trotzdem als 255 gelten lassen. Dann sieht das so aus:
Geht jedenfalls schneller al erst mal eine richtige Division
auszuführen.
Man könnte auch erstmal die beiden Werte in einen Vorzeichenfreien
16-Bit Integer addieren und den dann 8 Bits nach rechts schieben. Das
ist dann noch etwas schneller, da nur einmal um 8 Bits schieben nötig
ist, bzw. man einfach das high-byte nimmt und gut ist. Spart wohl ein
paar Takte.