Hat schon einmal jemand einen DTMF Decoder mit einer Atmega
programmiert?
Mir scheint die Aufgabe sportlich interessant.
Als möglicher Ansatz sehe ich entweder
signal ==> mischer ==> LP ==> FFT 8 Werte
oder 8 einzelne Filter.
Es gibt Applikationen von Analog Devices u.a. für Fixkomma-DSP und DTMF
Z.B. hier unter "Aplikace_1.pdf" ab Seite 471:
http://radio.feld.cvut.cz/courses/X37ASP/materialy.php
der Goertzel-Algorithmus ist anscheinend die übliche Methode
>hier unter "Aplikace_1.pdf" ab Seite 471:
Uhh... und das wo mein Tschechisch so schlecht ist ... ich glaub, ich
kann gar keins ;-)
Aber Scherz bei Seite. Es ist zwar für einen echten DSP ( ADSP21xx,
24Bit MAC, bis 160MHz ) was eine ganz anderen
Signalverarbeitungsleistungsklasse als einem Atmega entspricht, aber
vielleicht lässt sich ja der Algorithmus auf einen AVR quetschen.
Hier gibt es zumindest ein Goerzel Beispiel:
https://github.com/jacobrosenthal/Goertzel/blob/master/Goertzel.cpp
Vielleicht lässt sich das bezüglich der Geschwindigkeit noch etwas
optimieren ...
Ich hatte mal einen Test mit einem ATMega168 gemacht:
8 Frequenzen
8000 Samples pro Sekunde (12Bit je Sample)
50 Durchgänge pro Sekunde (also 160 Samples je Durchgang)
Die Kernroutine ("int32_t = int32_t * uint16_t / 65535") war in
Assembler, der Rest in GCC. Ich kam auf rund 6 Millionen Takte pro
Sekunde. Also Kinderkram für einen ATMega. :-)
Aber selbst mit einem ATTiny@1MHz scheint das (ohne Goertzel!) zu gehen:
http://www.elo-web.de/elo/mikrocontroller-und-programmierung/avr-anwendungen/dtmf-decoder
Marcus schrieb
>>Hat schon einmal jemand einen DTMF Decoder mit einer Atmega>>programmiert?
Autor: Horst (Gast)
>oder einen MT8870
Eigentlich dachte ich, meine Frage sei relativ eindeutig formuliert,
aber scheinbar kann man die Frage auch anders verstehen, nachdem es
jetzt schon zwei solche Antworten gab.
Deshalb versuche ich das jetzt mal zu präzisieren: Es soll ein DTMF
Dekoder im Atmega implementiert werden, also die
Signalverarbeitungsalgorithmen in Software. Das Anschließen eines
externen Hardware DTMF Dekoders war nicht die Frage.
>Aber selbst mit einem ATTiny@1MHz scheint das (ohne Goertzel!) zu gehen:>http://www.elo-web.de/elo/mikrocontroller-und-prog...
Aus der Überschrift:
ohne FFT und Goertzel-Algorithmus!
- Analyse der Interferenzmuster
- 16-bit Frequenzzähler
Witzige Idee, ganz auf die Frequenzanalyse zu verzichten. Ich vermute
aber mal, dass das Verfahren im Punkt Störanfälligkeit nicht ganz mit
der Frequenzanalyse mithalten kann.
>Ich hatte mal einen Test mit einem ATMega168 gemacht:>> 8 Frequenzen>8000 Samples pro Sekunde (12Bit je Sample)> 50 Durchgänge pro Sekunde (also 160 Samples je Durchgang)>Die Kernroutine ("int32_t = int32_t * uint16_t / 65535") war in>Assembler, der Rest in GCC. Ich kam auf rund 6 Millionen Takte pro>Sekunde. Also Kinderkram für einen ATMega. :-)
Heißt das 37%@16Mhz Auslastung?
Klingt gut. Vielleicht könnte man auch auf Assembler verzichten.
Marcus schrieb:> Ich vermute> aber mal, dass das Verfahren im Punkt Störanfälligkeit nicht ganz mit> der Frequenzanalyse mithalten kann.
Aus dem Text geht hervor, daß der Algorithmus 500ms braucht, ein DTMF
Zeichen zu erkennen. Die minimale Länge eines Zeichens ist aber ca. 50ms
mit einer Pause von ebenfalls 50ms (10 Zeichen pro Sekunde). Er
funktioniert also nicht bei automatischer Wahl.
MfG Klaus
Marcus schrieb:> Heißt das 37%@16Mhz Auslastung?
Ja.
Marcus schrieb:> Vielleicht könnte man auch auf Assembler verzichten.
Sicherlich. Es gäbe auch noch Optimierungsmöglichkeiten. Zum Beispiel
könnte man statt 32 Bit nur 16 Bit für die Goertzel-Berechnung
verwenden. Aber wozu?
Fin schrieb:> Bernd K. schrieb:>>> Vielleicht gehts auch mit 4 IIR Bandpässen?>> Wie stellst du dir das vor?
Naja, vier Bandpässe halt für die 4 Frequenzen und dann schaun hinter
welchen beiden die Amplitude am höchsten (und ausreichend höher als
hinter den anderen beiden) ist.
Marcus schrieb:> Eigentlich dachte ich, meine Frage sei relativ eindeutig formuliert,> aber scheinbar kann man die Frage auch anders verstehen, nachdem es> jetzt schon zwei solche Antworten gab.>> Deshalb versuche ich das jetzt mal zu präzisieren: Es soll ein DTMF> Dekoder im Atmega implementiert werden, also die> Signalverarbeitungsalgorithmen in Software. Das Anschließen eines> externen Hardware DTMF Dekoders war nicht die Frage.
Ja dann mach doch und zeig mal, was herausgekommen ist :-)
Marcus schrieb:> Als möglicher Ansatz sehe ich entweder>> signal ==> mischer ==> LP ==> FFT 8 Werte>> oder 8 einzelne Filter
Na, dann teste da mal aus und berichte bitte über dié Ergebnisse.
Oh, ich hab da was verwechselt, sind ja 8 und nicht 4 Frequenzen. Also 8
Bandpässe. Wird eng, aber der Atmega kann doch immerhin 8*8
Multiplikation in Hardware, vielleicht gehts ja doch.
Ich hab noch ne Idee:
Es ist ja so daß wenn ich mich für eine Frequenz f interessiere und dann
exakt mit 4f sample, also 4 Samples pro Periode dann kann ich fast ohne
nennenswerten Aufwand einen extrem schmalbandigen IIR Bandpass für f
bauen (die 4 Samples nennen wir mal q, i, q', i', und dann rechnen wir
einmal
Q = q - q'
und
I = i - i'
I und Q filtern wir jeweils mit einem simplen IIR Tiefpass und der
Betrag dieses Vektors ist die Amplitude von f.
Oder mit anderen Worten: wir haben einen I-Q-Direktmischer gebaut und es
direkt ins Basisband (0Hz, Gleichspannung) runtergemischt und dort mit
einem Tiefpass gefiltert.
Soweit so gut.
Wenn wir jetzt aber den ADC des ATmega bis an die Schmerzgrenze
übertakten und sagen wir mal mit 50kS/s samplen und dann für jede
einzelne der 8 Frequenzen einzeln knallhart per nearest neighbor auf
jeweils 4f resamplen und jeweils nach 4 Samples für die jeweilige
Frequenz die obige Rechnung anwenden dann haben wir nach ein paar
Millisekunden für alle 8 Frequenzen jeweils I und Q und können deren
Amplitude ausrechnen (oder das Quadrat der Amplitude wenn wir keine
Wurzel ziehen wollen).
Das müsste der ATmega noch mitmachen sag ich mal aus dem Bauch raus, bei
50kS/s hätten wir noch 320 Takte pro Sample, man muss die Rechnung ja
auch nicht im IRQ machen sondern kann das auch für die Abarbeitung in
der main einreihen weil ja oft mehr als einer (und alle Schaltjahre auch
mal alle 8) gleichzeitig auf einen einzigen Samplezeitpunkt fallen
könnten.
Wir bekommen durch das krude krumme Dezimieren zwar einen immensen
Jitter auf die einzelnen Sampleraten aber wir können die Tiefpässe für
die ganzen I und Q Werte ja so lang machen bis das nicht mehr stört.
Und wenn noch Luft ist und der ADC das mitmacht kann man evtl auch noch
höher gehen mit der Samplerate, je höher desto weniger Jitter.
Moin,
> Mir scheint die Aufgabe sportlich interessant.
Frisch auf - ans Werk ;-)
> Als möglicher Ansatz sehe ich entweder>> signal ==> mischer ==> LP ==> FFT 8 Werte
Ich fuercht' mal, durchs Runtermischen gewinnt man nicht viel, die
Filter werden dann nur "langsamer" aber insgesamt ist glaub' ich die
Bandbreite doch nicht so schmal, dass runtermischen mehr spart als es
kostet.
> oder 8 einzelne Filter.
Da bin ich mir ziemlich sicher, dass das mit einem 8fach Goertzel gut
machbar ist. Wenn man's nicht gerade in Java oder Basic programmiert.
Vermutlich wirds gut sein, wenn der 2*cos(bla) Faktor beim Goertzel
moeglichst klein ist, d.h. - da die Signale im Frequenzband 697-1633Hz
liegen, waere da die Mitte bei 1165Hz. Davon das 4fache waere dann eine
"schoene" Samplingfrequenz - also 4.66KHz. Hm - da wird ein analoges
Antialiasingfilter, das noch 1633Hz durchlaesst, aber ab 2.33kHz
ordentlich daempft, schon etwas bloed.
Koennte man sich ueberlegen, mit dem AVR dann mit zB. ca. 9.32kHz oder
ca. 13.98kHz abzutasten und schonmal vor der ganzen Goertzelei
entsprechend zu dezimieren. Damit muesste mein analoger Tiefpass noch
1633Hz durchlassen und kurz vor 7Khz dann ordentlich sperren -das sind
dann gut 2 Oktaven - Naja, koennte grad' so klappen.
Wenn der AVR mit 16MHz laeuft; dann haett' ich also zwischen 2 Samples
ueber 16e6/14e3=1143 Takte Zeit. Wenn ich fuer mein 3:1
Dezimationsfilter dann die Haelfte der Zyklen vertroedeln wuerde; haett
ich also fuer die 8 Goertzels immernoch 1143/2*3, also ueber 1700 Takte
- also pro Goertzel pro Sample ueber 200 Takte.
Davon wuerd' ich jetzt 190 Takte hernehmen, um die Multiplikation und 2
Additionen und das Sampleschieben zu machen; die anderen 10 Takte spar'
ich mir, um dann jeweils nach vielleicht 64 Goertzeln mir die
Momentanleistung im entsprechenden Kanal zu berechnen - das sind dann ja
nochmal 4 Multiplikationen und 2 Additionen.
Dann bin ich auch schon fast durch - muss halt die 8 Werte fuer die
Leistung im entsprechenden Frequenzband noch auswerten -ob da jetzt was
gehupt hat oder nicht...
Also ich sag': Das geht.
Gruss
WK
Ich hätte spontan auch gesagt, das es geht, zumal ich DSP-mässig auch
schon Ähnliches hingebaut habe. Aber, in der Praxis sind weitere Punkte
zu beachten:
1) Das Signal ist meistens real ziemlich verdreckt, wenn es gesampelt
wurde und das kummuliert mit den einkalkulierten Fehlern einer
vereinfachten Prozessierung. Am Ende hat man Fehlerkennung ohne Ende.
2) Prozessoren haben meist noch andere Dinge zu tun und es ist selten
so, dass man einen spendiert, für nur eine solche Aufgabe. Das wäre
ineffektiv. Daher muss man genau rechnen, was der wirklich erübrigen
kann. Solche Sachen sind gfs in einem PLD besser aufgehoben.
Ohne Assembler braucht man etwa doppelt soviel CPU-Leistung (12MHz). Der
unten stehende Code ist ein von mir verworfener Testcode, da ich die
Tastencodes letztendlich digital (DTMF-Datentyp beim SIP) auslesen
konnte. Der Code ist also weder mathematisch noch programmtechnisch
sauber bzw. fehlerfrei. Ich habe mal beispielhaft Testdaten per
'cos(2*...' erzeugt und das Ergebnis hier angehängt. Die eigentlichen
Tasten müssten natürlich noch aus Amp[] dekodiert werden (den Code dazu
konnte ich aber nicht mehr finden).
Der Code funktionierte zwar 1a auch mit realen Telefonatmitschnitten,
aber der Spezialbaustein MT8870 ist perfekt und kostet keinen Euro.
Hallo Daniel,
vielen Dank für das Codebeispiel. Interessant ist Deine Multiplikation.
Aus Deinem vorigen Post habe ich entnommen, dass die Multiplikation in
Assembler geschrieben ist. Macht der GCC die Optimierung automatisch?
Würde es etwas bringen, "inline" davor zu schreiben?
>Der Code funktionierte zwar 1a auch mit realen Telefonatmitschnitten,>aber der Spezialbaustein MT8870 ist perfekt und kostet keinen Euro.
Bei mir ist diese Aufgabenstellung reiner Spieltrieb. Ich habe
eigentlich gar keine richtige Anwendung, experimentiere aber gerne mit
Signalverarbeitungsproblemen. Von daher ist die Performance für mich
erst mal zweitrangig.
Die Multiplikation in meinem Post ist nicht in Assembler sondern in C
geschrieben. Deswegen sind auch 12MHz nötig. Der Compiler fügt diese
zwar automatisch inline ein, es bringt aber nicht sehr viel. Erst mit
der (hoffentlich) äquivalenten Assembler-Multiplikation aus dem Anhang
werden es 6MHz.
Hallo Daniel,
danke für den Code. Mir war gar nicht bewusst, dass man für die 32Bit
Multiplikation so viele Befehle braucht ( 41, wenn ich mich nicht
verzählt habe ).
Irgendwann habe ich mal einen Arduuino DUE ( ARM Cortex M3, 84Mhz )
gegen einen AVR 16Mhz getestet. Ich hätte da erwartet, dass die
Geschwindigkeit mindestens um den Faktor 10 höher ist. Aber im Schnitt
lag es eher bei Faktor 4..5. Bei der Signalverarbeitung könnte der ARM
hier dank der längeren Wortbreite aber vielleicht doch eine deutlich
höhere Geschwindigkeit erreichen.
Vor längerer Zeit habe ich auch mal AVR-Assembler in C eingebunden. Die
Schwierigkeit dort war, herauszufinden, welche Register von C reserviert
werden und welche man auf vorher auf den Stack retten muss.
Es gibt auch eine Möglichkeit, den Assembler-Code direkt ins C-File
aufzunehmen, so dass man kein extra *.s File braucht.
Marcus schrieb:> Deshalb versuche ich das jetzt mal zu präzisieren: Es soll ein DTMF> Dekoder im Atmega implementiert werden, also die> Signalverarbeitungsalgorithmen in Software. Das Anschließen eines> externen Hardware DTMF Dekoders war nicht die Frage.
Aha, also eine Schulaufgabe, die Du nicht selber lösen willst,
sondern von anderen gelöst bekommen möchtest?
Es muss wohl sehr einfach gehen einen DTMF Signal auszuwerten.
Sonst wär das in den 70er Jahren nicht gegangen.
Ich habe da schon ein paar abhandlungen gelesen, die aus der
Telekommunikation kamen.
Ich habe auch schon görtzel umgesetzt, ist aber nicht immer die optimale
Lösung. Man braucht dahinter noch eine Kreuzkorrelation. Auch FFT ist ja
letztendlich auch nichts anderes.
Der Trick mit dem Interreferenz-Muster muss doch sehr gut gehen. Das
wurde anscheinend in den meisten Chips angewandt.
An diesem Thema bin ich auch noch interessiert eine einfache Lösung zu
finden.
Gruß Sascha
Sascha schrieb:> Es muss wohl sehr einfach gehen einen DTMF Signal auszuwerten.> Sonst wär das in den 70er Jahren nicht gegangen.
Das ist auch einfach, sofern man es analog macht. Für "faule"
Zeitgenossen gab (und gibt) es spezielle Decoder-ICs, damit man kein
Transistorgrab bauen muss.
Hier ist die Zielsetzung allerdings das ganze auf einem lahmen µC per
Software zu erledigen.
Autor: Sascha (Gast)
>Ich habe auch schon görtzel umgesetzt, ist aber nicht immer die optimale>Lösung. Man braucht dahinter noch eine Kreuzkorrelation.
Wieso Kreuzkorrelation? Der Code von Daniel oben benutzt den Görzel
Algorithmus. Das sogar mit nur einer Multiplikation pro Filter und
Sample bis auf den letzten Sample mit der Betragsbildung.
Das Ganze ist hier graphisch gezeichnet ( Figure 3 ):
https://www.dsprelated.com/showarticle/495.php
Marcus schrieb:> Das Ganze ist hier graphisch gezeichnet ( Figure 3 ):
Gibt es hier jemanden der google nicht kennt? Warum legst Du nicht mal
vor? hier sind viele gespannt auf Deine Lösung :-)
Moin,
Harald W. schrieb:> Aha, also eine Schulaufgabe, die Du nicht selber lösen willst,> sondern von anderen gelöst bekommen möchtest?
Also wenns so waere, wuerd's mich doch interessieren, welcher
Ausbilder/Uebungsleiter/Prof/Baumschulleerer sich das antut, dann die
Loesungen zu bewerten ;-)
Ansonsten wuerd' ich in Anbetracht der umfangreichen 32x32bit
Multiplikation stark dafuer plaedieren, in Assembler jeweils nur genau
die Genauigkeit herzunehmen, die man tatsaechlich braucht. also z.b. nur
eine 24x16bit Multiplikation oder sowas in der Art.
Muss man halt vorher mal sowas in einer Hochsprache mit floatingpoint
aufm PC programmieren, dann sieht man schon, welche Wertebereiche
tatsaechlich noetig werden.
Bei der engl. Wikipedia gibts unter Goertzel_Algorithm die Abteilung
"Power-spectrum terms" mit abschreibfertigem Pseudocode fuer genau das,
was hier eigentlich interessiert.
Gruss
WK
>Ansonsten wuerd' ich in Anbetracht der umfangreichen 32x32bit>Multiplikation stark dafuer plaedieren, in Assembler jeweils nur genau>die Genauigkeit herzunehmen, die man tatsaechlich braucht.
Das hat Daniel in seiner Assemblerroutine gemacht, deshalb gewinnt er ja
so einen großen Geschwindigkeitsvorteil:
Beitrag "Re: DTMF decoder"
Eine Idee wäre, ob der C-Compiler die Optimierung nicht auch schaffen
könnte, wenn man ihm die richtige Hilfestellung gibt. Man könnte die
Multiplikation eventuell in 16x16 Multiplikationen und Summen zerlegen
und die 32=16x16 Multiplikation damit realisieren.
Moin,
Die Frage ist erstmal: Welche Genauigkeit brauchts denn ueberhaupt? Was
ist denn das Teilziel:
Gucken obs hupt. Oder nicht. Also Informationsgehalt 1bit - Die gesuchte
Frequenz ist eben mit ausreichender Amplitude da oder nicht.
Das heisst doch: Bei der Berechnung der Leistung, wo's 3
Multiplikationen braucht, interessiert mich am Schluss nur eine Info,
die in 1bit passt. Da geh' ich doch mal davon aus, dass selbst wenn die
einzelnen Produkte recht gross werden - also z.b. 32bit - ich lange
nicht alle 32bit beruecksichtigen muss. Sondern mich von einer eventuell
anstehenden 32x32bit Multiplikation eh' nur die hoechstwertigsten paar
Bit interessieren, weil ich nur gucken will, obs hupt oder nicht. Also
reichen mir doch da sicherlich jeweils 8x8 bit Multiplikationen.
Genauso bei den einzelnen Schritten vor der einmaligen
Leistungsberechnung. Das wird wahrscheinlich drauf rauslaufen, dass man
vielleicht 64x oder 128x vor sich hin goertzelt und danach die
Leistungsberechnung vornimmt.
Also hab' ich 64 oder 128 Samples vorliegen, beim AVR bestenfalls mit
10bit Aufloesung. Da kann ich mir gut vorstellen, dass da auch 8bit
Aufloesung reichen. Mehr gibt ein Telefon eh' nicht her. Also wird's
interessant, welchen Wertebereich die einzelnen s, sprev, und sprev2 so
durchlaufen. Wahrscheinlich nicht die vollen 32bit, wahrscheinlich
nichtmal die vollen 24bit - mit Glueck vielleicht nur 16bit? Muss man
halt mal gucken. Und dann entsprechend die Laengen der "variablen" und
der Berechnungen waehlen.
Dabei fuercht' ich, wird Zeugs rauskommen, was dem C-Compiler nicht mehr
so leicht beizubringen ist - zumindest nicht mehr so, dass es sinnvoll
ist in C zu programmieren...
Das sind halt diese Bereiche, wo man sagen muss: Da kann man mit
handgedengeltem Assembler noch ordentlich was rausholen - es ist aber
nicht mehr wirklich wirtschaftlich, sondern nur noch mit "Spass an der
Freud'" zu rechtfertigen.
Gruss
WK
Dergute W. schrieb:> es ist aber> nicht mehr wirklich wirtschaftlich
Es sei denn auf der Platine (und in der Marge) ist kein Platz um für
jede einzelne Teilaufgabe einen separaten Chip zu spendieren wenn diese
Aufgaben auch alle zusammen genauso gut (ausreichend gut) von einem
einzigen kleinen µC erledigt werden könnten.
Und wenn man dafür in großen Mengen und in schneller Folge 16x16 Bit
multiplizieren müsste wählt man halt aus der riesigen Zahl verfügbarer
Controller einen aus der sowas aus dem Handgelenk macht und trotzdem
nicht teurer ist als ein ATmega.
Unwirtschaftlich wird es nur wenn man auf Teufel komm raus einen ATMega
dort einbauen will. Und noch unwirtschaftlicher wird es wenn der
schweineteure ATmega dann 98% Däumchen dreht weil man dem altehrwürdigen
Chip keine schweren Aufgaben mehr zumuten will und daher noch
tonnenweise zusätzliches Zeug auf die Platine pflastern muss.
Ursprünglich ging es doch um die Frage wie sportlich es sein könnte,
einen DTMF-Decoder auf einen ATMega zu kodieren. Die Antwort ist ja
beantwortet. Mit Goertzel gehts, wenn man statt float integer
verwendet. Und selbst mit einer (256 Punkt) FFT gehts
(Beitrag "Schnelle FFT in Assembler"), wenn der ATMega genügend
RAM Speicher hat. Wenn es aber um die Frage geht, wieviel CPU man
mindestens braucht, dann hätte ich noch eine schmutzige Lösung
anzubieten:
Man könnte die Fourier-Koeffizienten auch native (ohne Goertzel oder
FFT) berechnen, wenn das Ergebnis auch 'etwas fehlerhafter' sein dürfte.
Wenn ein paar Oberwellen zulässig sind, könnte man nämlich statt einer
Summe aus Sinusprodukten eine Summe aus Rechteckprodukten bilden. Die
gesamte Berechnung bestände dann nur noch aus zwei Summen ohne
Multiplikation.
Im Ergebnis ergibt sich ziemlich das gleiche Spektrum wie ich es bereits
in der Goerzel-Variante (siehe Post vom 13.12.2016 23:00) hatte. Der
Unterschied ist jedoch, dass der Filter auch beim Dreifachen,
Fünffachen, usw. der Grundfrequenz anspricht. Beispielsweise erhält man
bei 2090Hz ein Ansprechen des 697 HZ Filters:
1
650 Hz 45 149 50 7 65 7 22 59
2
660 Hz 692 29 22 35 15 0 8 3
3
670 Hz 1705 29 22 35 1 0 8 3
4
680 Hz 4658 29 114 7 8 0 43 3
5
690 Hz 6616 297 22 59 8 3 1 0
6
700 Hz 8581 304 8 7 15 0 15 3
7
710 Hz 5639 149 8 31 65 3 29 28
8
720 Hz 3294 8 128 14 15 7 8 3
9
730 Hz 1722 240 149 3 29 3 65 0
10
740 Hz 228 1942 93 35 22 182 1 45
11
750 Hz 45 3819 29 14 15 0 8 3
12
760 Hz 284 5633 93 35 1 0 65 3
13
770 Hz 312 10696 261 70 1 0 15 3
14
780 Hz 203 5802 402 87 8 3 43 14
15
790 Hz 0 3911 261 3 1 3 1 14
16
800 Hz 3 2329 22 14 8 91 1 3
17
810 Hz 3 747 149 140 1 14 1 3
18
...
19
2030 Hz 3 22 240 14 93 7 1 17
20
2040 Hz 3 86 93 0 22 0 1 3
21
2050 Hz 17 15 107 7 1 7 43 87
22
2060 Hz 158 22 65 0 43 63 1 17
23
2070 Hz 597 22 8 17 15 3 43 7
24
2080 Hz 597 8 15 3 8 3 15 28
25
2090 Hz 1019 65 8 3 8 3 29 7
26
2100 Hz 594 1 8 0 1 56 22 31
27
2110 Hz 457 22 8 3 72 17 8 14
28
2120 Hz 87 1 1 0 22 7 29 945
29
2130 Hz 35 8 15 3 114 3 8 351
30
2140 Hz 3 1 29 0 72 0 1 3
Ich habe diesen Filter anhand von einigen Stunden Musik als Testdaten
untersucht. Überraschenderweise erhielt ich nicht mehr fehlerhafte
DTMF-Werte als mit dem Goerzelfilter. Wenn man zusätzlich noch die
Datentypen ausreizt, dann erhält man eine sehr schnelle Berechnung. Es
reicht ein Controller ohne Hardware-Multiplikation. Der Code unten
benötigt nur noch einen ATTiny mit etwa 1.5 MHz!
1
#include<avr/io.h>
2
#include<avr/pgmspace.h>
3
4
#define nBuff (uint16_t)160 // 160 Samples pro Block -> 20ms
Korrektur:
Das Spektrum stimmt nicht. Ich hatte die falsche Zeile in main()
einkommentiert und die Testdaten waren damit Rechteckdaten. Das Ergebnis
sieht mit den Sinusdaten schöner aus:
Moin,
Hier mal ein Vergleich der Filterfrequenzgaenge.
blau: Goertzel mit 128 Berechnungen fuer 697Hz/8kHz Sample
rot : Ein FIR Filter mit 128 taps, die entweder +1 oder -1 sind, so das
eben 697Hz als Bandpass angenaehrt wird.
Gruss
WK
>https://forum.arduino.cc/index.php?topic=121540.0
An den Arduino hatte ich auch schon gedacht, damit würde die Software
eine weite Verbreitung finden.
Allerdings nutzt die vorne im ZIP-File gepostete Version schamlos die
einfache Float-Multiplikation und Addition. Die kann in Punkto
Geschwindigkeit bei weitem nicht mit Daniels Version mithalten.
>Man könnte die Fourier-Koeffizienten auch native (ohne Goertzel oder>FFT) berechnen, wenn das Ergebnis auch 'etwas fehlerhafter' sein dürfte.>Wenn ein paar Oberwellen zulässig sind, könnte man nämlich statt einer>Summe aus Sinusprodukten eine Summe aus Rechteckprodukten bilden. Die>gesamte Berechnung bestände dann nur noch aus zwei Summen ohne>Multiplikation.
Mit einem Rechteckfilter hatte ich auch schon mal vor einer Weile als
Bandpass-Ersatz experimentiert.
So was ähnliches wird seit langem beim Ringmodulator gemacht:
https://de.wikipedia.org/wiki/Ringmodulator
Meine Ergebnisse damals hatten mich nicht so recht überzeugt, deshalb
habe ich das dann nicht weiter verfolgt.
Deine Ergebnisse sehen besser aus ;-)
>Hier mal ein Vergleich der Filterfrequenzgaenge.>blau: Goertzel mit 128 Berechnungen fuer 697Hz/8kHz Sample>rot : Ein FIR Filter mit 128 taps, die entweder +1 oder -1 sind, so das>eben 697Hz als Bandpass angenaehrt wird.
Der Peak ist ganz gut zu erkennen. Man müsste sich vielleicht einen Test
überlegen, mit dem man die Praxistauglichkeit überprüfen kann.
Marcus schrieb:>>Hier mal ein Vergleich der Filterfrequenzgaenge.>>blau: Goertzel mit 128 Berechnungen fuer 697Hz/8kHz Sample>>rot : Ein FIR Filter mit 128 taps, die entweder +1 oder -1 sind, so das>>eben 697Hz als Bandpass angenaehrt wird.>> Der Peak ist ganz gut zu erkennen. Man müsste sich vielleicht einen Test> überlegen, mit dem man die Praxistauglichkeit überprüfen kann.
Man könnte einen Online-Radio-Stream auf verschiedene Filter anwenden
und die Fehlerquoten für irrtümlich erkannte DTMF-Code vergleichen.
Würde mich auch interessieren. Teste das doch mal.
>Teste das doch mal.
Mal schauen ... vielleicht stelle ich hier mal ein Test-Wav ein und
mache es mit Octave.
Als Erklärung für das gute Funktionieren Deines Rechteck-Filters hätte
ich folgendes anzubieten:
Das Spektrum eines Rechtecks verhält sich 1, 1/3, 1/5 usw.
https://de.wikipedia.org/wiki/Rechteckschwingung
Bei einer Filterauslegung für 700Hz würde die erste Oberwelle bei 2100
Hz liegen. Eine Frequenz bei 2100Hz müsste dann vermutlich 3 mal so
stark sein um den gleichen Filteroutput zu erzeugen wie die eigentlich
gesuchte Frequenz. Ich vermute, dass in Sprache und Musik eher die
tieferen Frequenzen vermehrt über den relativ langen
Integrationszeitraum auftreten. Deshalb hat der Rechteckfilter trotzt
seiner Ungenauigkeit eine relativ gute Erkennungsrate.
Ich habe mich früher immer gewundert, warum die DTMF Töne so schräg
unharmonisch klingen und gedacht, die hätten sich auch schönere Töne
aussuchen können.
Der Grund wird aber in der Wikipedia erklärt:
"MFV ist ein In-Band-Signalisierungsverfahren, das heißt, die Signale
befinden sich innerhalb des normalen Sprachfrequenzbandes und können vom
Telefonierenden mitgehört werden. Daher könnten natürliche Geräusche
(zum Beispiel Musik) von der Vermittlungsstelle ebenfalls als Signal
aufgefasst werden. Die Frequenzen von MFV-Signalen wurden daher so
gewählt, dass sie Dissonanzen erzeugen, die mit sehr geringer
Wahrscheinlichkeit in der Umgebung eines Telefons auftreten."
@Daniel
Kleiner Nachtrag:
Ich nehme mal die Zwei Maxima des ersten Filters aus deinen Testdaten:
700 Hz 4445 175 3 8 6 0 7 0
2090 Hz 504 5 3 0 1 1 8 14
Das ist ~ Faktor 9. Ich habe Faktor 3 vorher gesagt. Das dürfte daran
liegen dass der Output in Deiner Berechnung quadratisch ist und die
Wurzel nicht gezogen wird ( Was ja für die Signalerkennung nicht
relevant wäre ).