Arduino Forum

Using Arduino => Audio => Topic started by: el_supremo on Sep 05, 2012, 03:19 am

Title: DTMF decoder library
Post by: el_supremo on Sep 05, 2012, 03:19 am
I have modified the Goertzel algorithm implementation here:
https://github.com/jacobrosenthal/Goertzel (https://github.com/jacobrosenthal/Goertzel)
so that it can be used to detect DTMF tones. The new version, like the original, is not interrupt driven.
It is provided AS IS for you to play with.
There are two sample audio files in the zip which, when the windows audio is turned up full, the sample code detects with no errors.
There is also a circuit diagram of how I connected the audio from the computer's headphone output to the Arduino's analog Pin 0. Use at your own risk.
Unzip the attached file into your libraries directory.

UPDATED 2016/12/19. I've attached the most recent version of the library to this message. Later messages (#6, #29) had a link to the zip file but those links will die soon - my ISP is withdrawing the webspace service.
Also, see message #42 for a link to another DTMF library. I haven't tried it but it is probably better than this one.

Pete
Title: Re: DTMF decoder library
Post by: SexualMoose on Sep 06, 2012, 03:49 am
So, I took a look and it works beautifully. Their are 2 things I have questions about though. The tone length is very strict. If the tone is too short it wont work and if it plays too long it will put print the number multiple times. Is their any chance you could make it modifiable? Also, the goertzel algorithm  is supposed to compensate for magnitude on its own. Is there anyway to account for that?

Again, great job and thanks for your help!

Moose
Title: Re: DTMF decoder library
Post by: retrolefty on Sep 06, 2012, 03:53 am

So, I took a look and it works beautifully. Their are 2 things I have questions about though. The tone length is very strict. If the tone is too short it wont work and if it plays too long it will put print the number multiple times. Is their any chance you could make it modifiable? Also, the goertzel algorithm  is supposed to compensate for magnitude on its own. Is there anyway to account for that?

Again, great job and thanks for your help!

Moose


I believe the official (original ATT specs?) DTMF specs for minimum recognition time (shortest tone period) for a valid digit is around 40 msec if I recall correctly. Decoding multiple repeated digits for a single tone of any length sounds like just a 'feature' of the library.  ;)
Title: Re: DTMF decoder library
Post by: el_supremo on Sep 06, 2012, 04:37 am
Quote
The tone length is very strict. If the tone is too short it wont work

How short a tone are you trying? The dialabc example uses 50ms tones. The example code uses a sample length of 128 which means that a sample block is 14 milliseconds long. It should have 3 good blocks in one 50ms tone and might detect tones down to around 30ms - I haven't tried that. You could try making the sample length shorter (try 64) so that the algorithm samples the tone more times. If you do that, you'll have to reduce the threshold amplitude as well.

Quote
and if it plays too long it will put print the number multiple times.

When the code detects a tone it won't return it again until it sees something that is not a tone. If for any reason the amplitude drops a bit to just below the threshold it can think it has seen the end of the tone when there's actually still more to come. Try lowering the threshold amplitude just a bit.

Quote
Is their any chance you could make it modifiable?

Make what modifiable?

Quote
Also, the goertzel algorithm  is supposed to compensate for magnitude on its own.

I saw one implementation which divided the resulting magnitude by the number of samples. I don't know if that's actually part of the Goertzel algorithm itself.
I'll play with it in the next day or so.

Quote
Again, great job and thanks for your help!

You're welcome ;-)

Pete
Title: Re: DTMF decoder library
Post by: el_supremo on Sep 06, 2012, 06:29 pm
Quote
Also, the goertzel algorithm  is supposed to compensate for magnitude on its own.

This can be done without changing the library.
The dtmf_test sketch originally had this code:
Code: [Select]
  dtmf.detect(d_mags,512);

  thischar = dtmf.button(d_mags,1800);


Change it to this:
Code: [Select]
  dtmf.detect(d_mags,512);
 
  for(int i = 0;i < 8;i++) {
    d_mags[i] /= n;
  }
 
  thischar = dtmf.button(d_mags,20.);

The "for" loop normalizes the magnitudes. I determined the threshold value of 20 empirically but it works for values of n from 55 up to 160 when using either of the sample audio files.
I prefer to leave this outside the library but if you want to build it in, in the method DTMF::detect change this statement:
Code: [Select]
    dtmf_mag[i] = sqrt(Q1[i]*Q1[i] + Q2[i]*Q2[i] - coeff[i]*Q1[i]*Q2[i]);
to this:
Code: [Select]
    dtmf_mag[i] = sqrt(Q1[i]*Q1[i] + Q2[i]*Q2[i] - coeff[i]*Q1[i]*Q2[i])/N;

Pete
Title: Re: DTMF decoder library
Post by: corolla9 on Jan 14, 2013, 09:58 am
is there a way to make the link alive again?
Title: Re: DTMF decoder library
Post by: el_supremo on Jan 14, 2013, 05:24 pm
The most recent version of the library is attached to the first message in this thread.

Pete
Title: Re: DTMF decoder library
Post by: corolla9 on Jan 15, 2013, 11:18 am
Hi Pete

thanks for the new link, but i fail to understand how the code work .
i dont have any expriance in arduino but i want to give it a shot....

as described i built the neccesery cirucit and connected it to my audio output of my pc.
when i upload the code to my (MEGA2560) i dont see any feedback from the circuit exept from when i opening the serial monitor and the led on pin 13 go ON.  i tried to open the serial monitor
put it on 115200 baud and wait and see the detction working but its seems to do nothing.

how can i adavnce and make it work (sorry for my bad english)
my audio output in full volume and my divider is on 512 please help.
Title: Re: DTMF decoder library
Post by: corolla9 on Jan 15, 2013, 03:57 pm
hi i have an update its working.
is there a way that can i decode 6 inputs in parallel?
Title: Re: DTMF decoder library
Post by: el_supremo on Jan 15, 2013, 05:03 pm
The code could be modified to handle six inputs but it would slow down the sampling rate quite substantially which would change the characteristics of the detection.
A better way to handle the audio sampling is to use a timer interrupt and do the detection on-the-fly but in either case you would probably need a faster processor to handle six channels.

Pete
Title: Re: DTMF decoder library
Post by: bowline77 on Jan 25, 2013, 10:11 am
I have an issue with the detection of the DTMF tones. When I try with audio archives through my computer, I have no problem, but when I connect my phone, nothing is detected. I don´t know why.

What I have in mind is to connect one phone to my arduino board, with voicemail active, then if there is an incoming call, the voice mail pick up the call and because of this is allowed to dial the tones. For example 001 wich turns on the heating.

But without detection through my mobile I am blocked, what can I do?

Thanks for your help in advanced
Title: Re: DTMF decoder library
Post by: retrolefty on Jan 25, 2013, 02:49 pm

I have an issue with the detection of the DTMF tones. When I try with audio archives through my computer, I have no problem, but when I connect my phone, nothing is detected. I don´t know why.

What I have in mind is to connect one phone to my arduino board, with voicemail active, then if there is an incoming call, the voice mail pick up the call and because of this is allowed to dial the tones. For example 001 wich turns on the heating.

But without detection through my mobile I am blocked, what can I do?

Thanks for your help in advanced


You would probably have to show us how you are attempting to connect to your telephone line. Actually most countries/telephone companies have laws and rules about how equipment can be wired to the local subscribers loop, as it's a balance line and you are not free to ground either the tip or ring wire. Normally equipment manufactures use approved chips/modules/components to do such electrical interfacing to the line called DAA modules. These usually involve a 600 ohm 1:1 transformer as well as ring detection/protection components. Keep in mind that the ring voltage when your phone rings is a 90 VAC 20Hz signal that can easily blow up components wired directly to the phone pair.

So I would suggest you do a little goggling for telephone interfacing circuits to see what you should be using.

Lefty
Title: Re: DTMF decoder library
Post by: bowline77 on Jan 28, 2013, 06:10 pm
I have used El_supremo offered drawing and I connected a mobile phone with the audio jack so I don´t have the issue of a landline connetion (this is another point that I want to check out)

Thaks for your help
Title: Re: DTMF decoder library
Post by: rinkrides on Feb 17, 2013, 06:21 pm

hi i have an update its working.
is there a way that can i decode 6 inputs in parallel?

The code could be modified to handle six inputs but it would slow down the sampling rate quite substantially which would change the characteristics of the detection.
A better way to handle the audio sampling is to use a timer interrupt and do the detection on-the-fly but in either case you would probably need a faster processor to handle six channels.

Pete

Parallax Propeller could decode to 7 parallel channels with little external circuitry & leaving one of the COG's for serial back to an arduino.. A propeller chip (P8X32A) has 32 I/O, fully digital, analog input can be accomplished via sigma-delta conversion. There are actually 8 separate MCU's called cog's inside of one chip, this is how the propeller can do real-time parallel processing
Title: Re: DTMF decoder library
Post by: Docedison on Feb 23, 2013, 04:03 am
There is an IC part# MT8870. It is a DTMF decoder that will provide a Data Valid signal and 4 bit binary output. all it requires is about 100 MV of clean audio, 5 V and a 3.58 MHz color burst crystal.
Here is a link from "Futurlec"that " appears to do a great deal.. and cheaper too @$12.98..

http://www.futurlec.com/Mini_MT8870.shtml (http://www.futurlec.com/Mini_MT8870.shtml).

Bob
Title: Re: DTMF decoder library
Post by: rinkrides on Mar 31, 2013, 07:33 am
i did buy 6 of these chips $6 ea. haven't tried them yet but im sure they will work fine.
Title: Re: DTMF decoder library
Post by: DaAwesomeP on Jul 17, 2013, 08:01 pm
Hi,
I'm trying to use el_supremo's DTMF library. No matter what I do, I can't get a reading/signal from it.
I am wiring up the handset output of my telephone with this schematic:
(https://coolarduino.files.wordpress.com/2011/02/dc_bias11.png)
Taken from: https://coolarduino.files.wordpress.com/2011/02/dc_bias11.png (https://coolarduino.files.wordpress.com/2011/02/dc_bias11.png)
I know this circuit is working because other libraries that do different things correctly analyze the audio.

Is there something I need to change? I would prefer not to by a DTMF Decoder.
Title: Re: DTMF decoder library
Post by: el_supremo on Jul 17, 2013, 09:05 pm
Which other libraries, what do they do?

Pete
Title: Re: DTMF decoder library
Post by: DaAwesomeP on Jul 17, 2013, 09:47 pm
This is a basic speech recognition software: https://github.com/arjo129/uSpeech (https://github.com/arjo129/uSpeech). It worked great.
This gave a response, but because it can only detect one tone at once, it didn't work: https://github.com/jacobrosenthal/Goertzel (https://github.com/jacobrosenthal/Goertzel)
Title: Re: DTMF decoder library
Post by: hb3ywu on Oct 14, 2013, 05:47 pm
Hello,

Works very well for me to display the code on the computer.

For cons, I can not seem to use a DTMF to turn an LED on output.

How to make the LED lights up when you press the button 5.

thank you
Title: Re: DTMF decoder library
Post by: el_supremo on Oct 14, 2013, 05:58 pm
Post your code (using code tags).

Pete
Title: Re: DTMF decoder library
Post by: hb3ywu on Oct 14, 2013, 07:00 pm
Thank you for the reply,

I took your code and have just added this:

Code: [Select]
if(thischar == 5) {
digitalWrite(led, HIGH);
}

I know (thischar == 5) is not fair. But I do not know what to put.

with this code
Code: [Select]
if(thischar) {
digitalWrite(led, HIGH);
}

The LED lights up, but with all the DTMF.

Code complet:
Code: [Select]
//DTMF Remote
//Led pin 13
//Audio IN A0


#include <DTMF.h>

int sensorPin = A0;
int led = 13;
float n=128.0;

// sampling rate in Hz
float sampling_rate=8926.0;

// Instantiate the dtmf library with the number of samples to be taken
// and the sampling rate.
DTMF dtmf = DTMF(n,sampling_rate);

void setup(){
  pinMode(led, OUTPUT);     
  Serial.begin(115200);

}

int nochar_count = 0;
float d_mags[8];



void loop()
{
  char thischar;
 

  /* while(1) */

  dtmf.sample(sensorPin);
  dtmf.detect(d_mags,506);
  thischar = dtmf.button(d_mags,1800.);

// Led ON receive DTMF "5"
//??? no (thischar) fonction
  if(thischar == 5) {
digitalWrite(led, HIGH);
}

  if(thischar) {
    Serial.print(thischar);
    nochar_count = 0;
    // Print the magnitudes for debugging
//#define DEBUG_PRINT
#ifdef DEBUG_PRINT
    for(int i = 0;i < 8;i++) {
      Serial.print("  ");
      Serial.print(d_mags[i]);
    }
    Serial.println("");
#endif
  } else {
    // print a newline
    if(++nochar_count == 50)Serial.println("");
    // don't let it wrap around
    if(nochar_count > 30000)nochar_count = 51;
  }
}


I started, but you've probably noticed ...

thank you very much

Title: Re: DTMF decoder library
Post by: el_supremo on Oct 15, 2013, 02:16 am
The code returns the detected button as a character so you need to use:
Code: [Select]
if(thischar == '5') {
  digitalWrite(led, HIGH);
}

This allows it to also return the symbols such as '*', '#' and, if you have the full 16 button pad,  'A', 'B' etc.

Pete
Title: Re: DTMF decoder library
Post by: hb3ywu on Oct 15, 2013, 12:52 pm
The simplest things are the most obvious.

Thank you, now it works fine.

FYI, perfect decoding at a speed of 50ms, but only with the wiring you suggested.

thank you very much for the help and the job.

HB3YWU / Mike
Title: Re: DTMF decoder library
Post by: griff2a on Feb 13, 2014, 08:29 pm
DTMF.cpp gets compile errors for me. I use the current version of the 'arduino' package  from the Fedora 'updates' repository on Fedora 20. Perhaps something has changed in the avr-gcc compiler.  I get error message:
    unable to find a register to spill in class 'POINTER_REGS'
The line causing the error is:
   dtmf_mag = sqrt(Q1*Q1 + Q2*Q2 - coeff*Q1*Q2);
I fixed the problem by splitting up this expression into 3 lines:
    float tmp;
     tmp = Q1*Q1 + Q2*Q2;
     tmp = tmp - coeff*Q1*Q2;
     dtmf_mag = sqrt(tmp);

Griff

Title: Re: DTMF decoder library
Post by: wojciech_69 on May 16, 2014, 02:13 pm
Pete, it is possible that your library can decode CTCSS tone? this guy make something that : http://whatcomradio.wordpress.com/2013/05/28/dtmf-decoding-with-arduino/ (http://whatcomradio.wordpress.com/2013/05/28/dtmf-decoding-with-arduino/)
but this radio can't read DTMF tone or i made a mistake ?
Title: Re: DTMF decoder library
Post by: el_supremo on May 16, 2014, 07:10 pm
The library is specifically designed to decode the 8 DTMF tones. Decoding CTCSS tones is much more difficult because in some cases they are less than 3Hz apart whereas the DTMF tones are at least 70Hz apart.
If you were aiming to decode only a few of the tones and could choose a few that were much further apart, it can be done, but trying to decode all of them is probably impossible on an Arduino without external hardware.

Pete
Title: Re: DTMF decoder library
Post by: Fuellhase on Mar 18, 2015, 03:29 pm
When I try to compile the example dtmf_test I get the following and some more error-messages:


C:\Users\Peter\Documents\Arduino\libraries\DTMF\DTMF.cpp: In member function 'void DTMF::detect(float*, int)':

C:\Users\Peter\Documents\Arduino\libraries\DTMF\DTMF.cpp:179:1: error: unable to find a register to spill in class 'POINTER_REGS'


Arduino: 1.6.1 (Windows 7), Platine: "Arduino Uno"

Has anyone an idea how to fix this?

 
Title: Re: DTMF decoder library
Post by: el_supremo on Mar 18, 2015, 06:04 pm
The code compiles with Arduino version 1.0.6 but it appears that there is a bug of some sort in the compiler in versions 1.6.0 and 1.6.1 - probably related to the -Os flag.
I have a workaround. Replace the entire DTMF:detect function in the DTMF.cpp library file with this:
Code: [Select]

// return the magnitudes of the 8 DTMF frequencies
void DTMF::detect(float dtmf_mag[],int adc_centre)
{
  int index;
  float d_tmp;

  /* Process the samples. */
  for (index = 0; index < N; index++)
  {
    ProcessSample(testData[index],adc_centre);
  }
  // Calculate the magnitude of each tone.
  for(int i=0;i < 8;i++) {
// El_Supremo 150318 the compilers in Arduino verisons 1.6.0 and 1.6.1
// generated "unable to find a register to spill" error in the original statement
// here. Breaking it into pieces worked around the problem.
//     dtmf_mag[i] = sqrt(Q1[i]*Q1[i] + Q2[i]*Q2[i] - coeff[i]*Q1[i]*Q2[i]);

  // This is the equivalent of sqrt(real*real + imag*imag)
  d_tmp = Q1[i]*Q1[i];
  d_tmp += Q2[i]*Q2[i];
  d_tmp -= coeff[i]*Q1[i]*Q2[i];

    dtmf_mag[i] = sqrt(d_tmp);
  }
  ResetDTMF();
}


I didn't notice/remember the report of the same problem in message #24 by griff2a until after I'd found a fix. My first attempt at splitting up the statement was similar to his but it didn't help so I had to split it even further.

Let me know if this works for you. I will update the link to the library.

Pete
Title: Re: DTMF decoder library
Post by: el_supremo on Mar 18, 2015, 06:23 pm
The most recent version of the library is attached to the first message in this thread.

Pete
Title: Re: DTMF decoder library
Post by: Fuellhase on Mar 20, 2015, 12:45 am
Everything works fine now. Thank You !!!
Title: Re: DTMF decoder library
Post by: starstuff on Mar 20, 2015, 08:08 am
I've uploaded the updated version to http://members.shaw.ca/el.supremo/DTMF.zip (http://members.shaw.ca/el.supremo/DTMF.zip).

Pete
Hey Pete,

The above link seems to be pointing to the previous version... still the same detect function.

rob
Title: Re: DTMF decoder library
Post by: el_supremo on Mar 20, 2015, 04:25 pm
Hi Rob,
Thanks for the heads up. I've uploaded the correct version this time.

Pete
Title: Re: DTMF decoder library
Post by: Fuellhase on Mar 21, 2015, 08:45 am
I realized the wrong link by myself. Thanks to everybody. My application, the detection of given 4 alarmtones between 580 and 820 Hz, works very fine!
Title: Re: DTMF decoder library
Post by: iWantaFanta on Apr 21, 2015, 02:17 am
Hey everybody,

I'm so glad this DTMF library exists.  To add to the posted code in this thread. Any ideas on how to select 2 or 4 dtmf tones sequentially to flip the LED on? 


I'm looking for:
 
if(thischar == '55') {
  digitalWrite(led, HIGH);
}


Or:


if(thischar == '55AB') {
  digitalWrite(led, HIGH);
}


I'm thinking of having a counter that counts until 2 or 4.  Once the count gets up to 2 or 4, 'thischar' would be reset to 0.  I'm having trouble expressing that as code that works. 


Thanks!
Title: Re: DTMF decoder library
Post by: ngunduc on Jul 01, 2015, 10:19 pm
Hi Everybody,

I am trying to make a simple comminicator by landline which will use DTMF signals on both sides problem is , I am looking for detecting the Line busy, Call in process , other party didnt answer , Does any one can help me how to make this or which IC. can be used or is there any other way to make.

Best Regards
Title: Re: DTMF decoder library
Post by: Emersentian on Aug 06, 2015, 06:12 pm
Hi Pete,

When I tried "Verify" of the "dtmf_test.ino"

I get this error message:

Quote
Arduino: 1.6.5 (Windows 8.1), Board: "Arduino Uno"

C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp: In member function 'void DTMF::detect(float*, int)':
C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp:179:1: error: unable to find a register to spill in class 'POINTER_REGS'
 }
 ^
C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp:179:1: error: this is the insn:
(insn 42 40 44 6 (set (reg:SF 50 [ D.4208 ])
        (mem:SF (post_inc:HI (reg:HI 63 [ ivtmp.118 ])) [2 MEM[base: _50, offset: 0B]+0 S4 A8])) C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp:175 99 {*movsf}
     (expr_list:REG_INC (reg:HI 63 [ ivtmp.118 ])
        (nil)))
C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp:179: confused by earlier errors, bailing out
Error compiling.

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.
Do I need to have the arduino uno plugged in and running the program? I thought "verify" would compile without.



Thanks,
Emerson
Title: Re: DTMF decoder library
Post by: el_supremo on Aug 06, 2015, 06:32 pm
See messages 24, 28 and 29 in this thread. Let me know if that doesn't help.

Pete
Title: Re: DTMF decoder library
Post by: edprado on Sep 11, 2015, 02:41 pm
Hi,  I would like to use the keypad cellphone near the microphone to recognize the tones, what kind of microphone do you suggest?


edit:

Electret Microphone Amplifier - MAX4466 with Adjustable Gain - https://www.adafruit.com/products/1063

Electret Microphone Amplifier - MAX9814 with Auto Gain Control - https://www.adafruit.com/products/1713

or another in aliexpress ?
Title: Re: DTMF decoder library
Post by: PChuma on Oct 21, 2015, 01:48 pm
hi

my arduino keeps reading the DTMF decoder outputs as high, what might be the problem
Title: Re: DTMF decoder library
Post by: ulises2012 on Nov 26, 2015, 01:04 pm
hello from Argentina, I am a rookie, you can use Arduino Uno 328 and Dtmf Dt8870 to use as joystick pc
Title: Re: DTMF decoder library
Post by: surbyte on Nov 26, 2015, 02:37 pm
Yes, of course. 
Use Google: Arduino USB Joystick, there is a lot of info.
Title: Re: DTMF decoder library
Post by: pjrc on Nov 27, 2015, 11:19 am
Oh, so painful seeing floating point... so slow, times 7 tones!

You also need some relative signal strength comparisons and handling dropouts and other timing issues that occur in real-world reception of DTMF tones in the presence of noise and interference.

Here, use this if you must stay on 8 bit AVR.

https://github.com/PaulStoffregen/AVR_DTMF (https://github.com/PaulStoffregen/AVR_DTMF)

If you have a 32-bit Teensy 3.x, I wrote a much better version (https://github.com/PaulStoffregen/Audio/blob/master/examples/Analysis/DialTone_Serial/DialTone_Serial.ino) is available in the audio library.
Title: Re: DTMF decoder library
Post by: dvk1 on Dec 03, 2015, 08:20 pm
Hello, el_supremo . Please tell me whether it is possible to work your library with ATmega8 internal clock 8MHz ?
Title: Re: DTMF decoder library
Post by: AquaRovGuy on May 10, 2016, 09:44 pm
Hi, I have been trying to use your code, but I keep getting the following errors:

Code: [Select]

Arduino: 1.6.5 (Windows 7), Board: "Arduino/Genuino Uno"

Build options changed, rebuilding all

Using library DTMF in folder: C:\Program Files (x86)\Arduino\libraries\DTMF (legacy)



C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10605 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard -IC:\Program Files (x86)\Arduino\libraries\DTMF C:\Users\Owner\AppData\Local\Temp\build6193173364618605693.tmp\dtmf_test.cpp -o C:\Users\Owner\AppData\Local\Temp\build6193173364618605693.tmp\dtmf_test.cpp.o

C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10605 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard -IC:\Program Files (x86)\Arduino\libraries\DTMF -IC:\Program Files (x86)\Arduino\libraries\DTMF\utility C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp -o C:\Users\Owner\AppData\Local\Temp\build6193173364618605693.tmp\DTMF\DTMF.cpp.o

C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp: In member function 'void DTMF::detect(float*, int)':
C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp:179:1: error: unable to find a register to spill in class 'POINTER_REGS'
 }
 ^
C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp:179:1: error: this is the insn:
(insn 42 40 44 6 (set (reg:SF 50 [ D.4208 ])
        (mem:SF (post_inc:HI (reg:HI 63 [ ivtmp.118 ])) [2 MEM[base: _50, offset: 0B]+0 S4 A8])) C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp:175 99 {*movsf}
     (expr_list:REG_INC (reg:HI 63 [ ivtmp.118 ])
        (nil)))
C:\Program Files (x86)\Arduino\libraries\DTMF\DTMF.cpp:179: confused by earlier errors, bailing out
Error compiling.





I am very new to all this, so any help would be great. Thanks!
Title: Re: DTMF decoder library
Post by: el_supremo on May 10, 2016, 09:47 pm
That has already been covered earlier in this thread. See message #28 and a few of the earlier ones.

Pete
Title: Re: DTMF decoder library
Post by: AquaRovGuy on May 12, 2016, 05:06 pm
That worked. Thanks! :)
Title: Re: DTMF decoder library
Post by: aleksandr-zh on Jul 16, 2016, 04:38 pm
hi all, hi el_supremo!

I want to do caller ID. But I live in Russia. We have most of the telephone exchanges of old, they were made in the USSR. In the old telephone exchanges not used for FSK or DTMF, but own Soviet standard transmission of the calling subscriber.
The old standard differs by the algorithm, and frequencies. For example, here's the frequencies, they are transmitted without a pause between digits.

I found the code for Goertzel algorithm, but I can't figure out how to obtain the necessary data from this program and how to connect the signal to the ADC input.

code "2 of 6".

f, Hz   The level dB
700   -6.5 To 27.4
900   -6.5 To 29.0
1100   -6.5 To 31.0
1300   -6.5 To 32.6
1500   -6.5 To 34.3
1700   -6.5 To 36.0

Combinations of two of the six frequencies above means:
f1 + f2, Hz The code "2 6"

The number
1 700 + 900 000011
2 700 + 1100 000101
3 900 + 1100 000110
4 700 + 1300 001001
5 900 + 1300 001010
6 1100 + 1300 001100
7 700 + 1500 010001
8 900 + 1500 010010
9 1100 + 1500 010100
0 1300+ 1500 011000
"Start" 1100 + 1700 100100
"Repeat" 1300+ 1700 101000

"Start" - represents the start and end of the two-frequency chip package (multi-frequency sequence is repeated several times a packet of information, the beginning and end of which points to this combination).
"Repeat" - it means that another figure repeats the previous (in the absence of the combination of decoding two series following the same numbers would be extremely difficult).
information package contains 10 two-frequency packages for 38-42 ms


I want to try to use your library to determine the desired frequencies me. But I do not understand how you carded these values?

DTMF.cpp

const unsigned char dtmf_map[16] = {
 0x11,
 0x21,
 0x41,
 0x12,
 0x22,
 0x42,
 0x14,
 0x24,
 0x44,
 0x28,
 0x81,
 0x82,
 0x84,
 0x88,
 0x18,
 0x48
};

Info:
The telephone exchange transmits the calling number after the subscriber request - 500 Hz, 100-200 milliseconds. To improve the reliability of the signals can be transmitted 2-9 times.
https://upload.wikimedia.org/wikipedia/commons/3/38/ANI-signals.wav

info: https://translate.google.ru/translate?sl=ru&tl=en&js=y&prev=_t&hl=ru&ie=UTF-8&u=https%3A%2F%2Fru.wikipedia.org%2Fwiki%2F%25D0%2590%25D0%259E%25D0%259D&edit-text=

https://translate.google.ru/translate?sl=ru&tl=en&js=y&prev=_t&hl=ru&ie=UTF-8&u=http%3A%2F%2Fradio.cybernet.name%2Fshem%2Ftel%2Faon.html&edit-text=
Title: Re: DTMF decoder library
Post by: el_supremo on Jul 16, 2016, 06:47 pm
With DTMF, the code is 2 of 8 consisting of one tone from the "row" frequencies and one tone from the "column" frequencies. The code uses the Goertzel algorithm to detect each of the 8 frequencies. The DTMF frequencies are arranged like this on a touchtone phone:
Code: [Select]

          1209  1336  1477  1633
 697,       1     2     3     A
 770,       4     5     6     B
 852,       7     8     9     C
 941,       *     0     #     D

So hitting the number '8' will send tones 852 and 1366 together. When receiving these tones, the code looks for them in the order they are listed in the dtmf_tones array. The code then maps them into two hex digits, one for the rows and one for the columns.
Code: [Select]

int dtmf_tones[8] = {
// Row tones (low order hex digit)
 697,     //1
 770,     //2
 852,     //4
 941,     //8
// Column tones (high order hex digit)
1209,    //1
1336,    //2
1477,    //4
1633     //8
};

If tones 852 and 1366 are received together, they will be converted into hex 24. This is then looked up in the dtmf_map array and the index where it is found (7) is then used to map into the dtmf_char array which translates it to the character '8'.

In your case, there are only six tones which aren't in a convenient row/column arrangement but it shouldn't be too hard to modify the code to read it provided that the individual tones are long enough for the Goertzel algorithm to reliably detect them.

Pete
Title: Re: DTMF decoder library
Post by: aleksandr-zh on Jul 16, 2016, 08:35 pm
Pete, I understand!!! :)
terrible not to know English...

but then I don't understand how the program is allocated a desired frequency... :(
Title: Re: DTMF decoder library
Post by: el_supremo on Jul 16, 2016, 09:18 pm
The easiest way to add the frequencies would be to change the array like this:
Code: [Select]
int dtmf_tones[8] = {
 700,
 900,
1100,
1300,
1500,
1700,
0,
0
};


The code will still look for eight tones but two of them will be zero and you can ignore them. You should only see pairs of tones with an index of 0 to 5. Anything else is not valid.
Then you will have to change the code which translates these into their corresponding digits.
But you'll also have to handle the start and repeat codes which don't occur in DTMF.

Pete
Title: Re: DTMF decoder library
Post by: aleksandr-zh on Jul 16, 2016, 09:29 pm
I read discovery method by sines and cosines (tabular correlation method) and the program in assembler before, so I waited a difficult code.

Well, Pete. I will try this option this week, and then report the results.
I use the Bascom compiler. Arduino used a little, experience not have. And always Arduino proved to be very positive. Probably will have to learn this IDE also :)

Thank you for help and detailed explanations!
Title: Re: DTMF decoder library
Post by: aleksandr-zh on Jul 17, 2016, 09:58 pm
the problem is solved, but not completely: I took the program from Arduino for DTMF receiving and remade it for its task. Signals are received, but there are some unpleasant moments.

the device is not fast enough: I successfully received signals with a duration of 40-45 ms, but bad receive or not taking all signals shorter than 40 ms

I'm writing a program for Arduino for the first time...
Title: Re: DTMF decoder library
Post by: el_supremo on Jul 18, 2016, 03:29 am
Can you post the code you have so far (in code tags please) and I'll have a look at it?

Pete
Title: Re: DTMF decoder library
Post by: aleksandr-zh on Jul 18, 2016, 08:29 am
Yes, of course!
I sped up the algorithm by removing the two "useless for me" dimension. The algorithm is written to the 8 frequencies. I reduced the measurement of up to 6 frequencies.
after these improvements, the program is well receive signals from the telephone station. Telephone station 3 times transmits data about the subscriber number. And I at least 2 times successfully to receive the data. if the program is incorrectly received symbol, then I see "-"

some parts of the code is bad - the first time I write on Arduino... I don't know the language, so doing everything by trial and error

The signal of russian CID:
https://upload.wikimedia.org/wikipedia/commons/3/38/ANI-signals.wav



Title: Re: DTMF decoder library
Post by: el_supremo on Jul 18, 2016, 07:42 pm
First just a "cosmetic" change to your code. Replace the entire DTMF::button method with this:
Code: [Select]

// The low order bit corresponds to the lowest frequency (700Hz)
unsigned char dtmf_map[12] = {
  B000011, //1
  B000101, //2
  B000110, //3
  B001001, //4
  B001010, //5
  B001100, //6
  B010001, //7
  B010010, //8
  B010100, //9
  B011000, //0
  B100100, //start
  B101000, //repeat
};

char dtmf_char[12] = {
  '1',
  '2',
  '3',
  '4',
  '5',
  '6',
  '7',
  '8',
  '9',
  '0',
  'S',
  'R'
};

char last_dtmf = 0;
char DTMF::button(float mags[], float magnitude)
{
  int bit = 1;
  int j;
  int dtmf = 0;

  for (int i = 0; i < 6; i++) {
    if (mags[i] > magnitude) {
      dtmf |= bit;
    }
    bit <<= 1;
  }

  if (dtmf > 0)  {
    for(j = 0;j < 12;j++) {
      if(dtmf == dtmf_map[j]) {      
        return(dtmf_char[j]);
      }
    }
    return('-');
  }
  return(0);
}


This will remove the "goto" statements :) It also returns the detected character, which your version wasn't doing.

The button method still needs some fixing though. In the Russian CID system, the same digit can't appear twice in a row. Your code needs to be able to detect whether the currently detected digit is the same as the last one and, if it is, ignore it (return zero instead). This will remove the occasional duplicated digits that show up in your example output. You will also have to handle the Repeat code properly - if 'R' is detect, return the last valid digit instead of 'R'.

Pete
Title: Re: DTMF decoder library
Post by: aleksandr-zh on Jul 18, 2016, 07:59 pm
thanks! I'll do it tomorrow
Title: Re: DTMF decoder library
Post by: SHTIRLITZ on Dec 10, 2016, 07:12 am
Hello, i try to launch scecth on IDE 1.16.11, compilation was not complete:
Arduino: 1.6.11 (Windows 10), Плата:"Arduino/Genuino Uno"

C:\Users\oberw\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.15\cores\arduino\main.cpp: In function 'main':

C:\Users\oberw\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.15\cores\arduino\main.cpp:51:1: error: unable to find a register to spill in class 'POINTER_REGS'

 }

 ^

C:\Users\oberw\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.15\cores\arduino\main.cpp:51:1: error: this is the insn:

(insn 262 260 264 16 (set (reg:SF 144 [ D.2206 ])

        (mem:SF (post_inc:HI (reg:HI 164 [ ivtmp.110 ])) [10 MEM[base: _142, offset: 0B]+0 S4 A8])) C:\Users\oberw\Documents\Arduino\libraries\DTMF\DTMF.cpp:175 100 {*movsf}

     (expr_list:REG_INC (reg:HI 164 [ ivtmp.110 ])

        (nil)))

C:\Users\oberw\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.15\cores\arduino\main.cpp:51: confused by earlier errors, bailing out

lto-wrapper: C:\Users\oberw\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2/bin/avr-gcc returned 1 exit status

c:/users/oberw/appdata/local/arduino15/packages/arduino/tools/avr-gcc/4.9.2-atmel3.5.3-arduino2/bin/../lib/gcc/avr/4.9.2/../../../../avr/bin/ld.exe: lto-wrapper failed

collect2.exe: error: ld returned 1 exit status

exit status 1

Title: Re: DTMF decoder library
Post by: el_supremo on Dec 10, 2016, 05:58 pm
Post your code (in code tags </>)

Pete
Title: Re: DTMF decoder library
Post by: SHTIRLITZ on Dec 15, 2016, 12:53 pm
Post your code (in code tags </>)

Pete
Code the original from your library:

Code: [Select]

// The library toggles digital pin 4 in the sampling loop which allows
// measurement of the actual sampling frequency.
// If you call .sample() continuously like this:
// while(1)dtmf.sample(sensorPin);
// you can put a frequency counter on pin 4 to determine what the
// sampling frequency is on your Arduino. Note that the frequency
// counter will show half the actual rate. My meter showed 4.463kHz
// so the sampling rate is 8926Hz
#include <DTMF.h>

int sensorPin = A0;
int led = 13;


// NOTE that N MUST NOT exceed 160
// This is the number of samples which are taken in a call to
// .sample. The smaller the value of N the wider the bandwidth.
// For example, with N=128 at a sample rate of 8926Hz the tone
// detection bandwidth will be 8926/128 = 70Hz. If you make N
// smaller, the bandwidth increases which makes it harder to detect
// the tones because some of the energy of one tone can cross into
// an adjacent (in frequency) tone. But a larger value of N also means
// that it takes longer to collect the samples.
// A value of 64 works just fine, as does 128.
// NOTE that the value of N does NOT have to be a power of 2.
float n=128.0;
// sampling rate in Hz
float sampling_rate=8926.0;

// Instantiate the dtmf library with the number of samples to be taken
// and the sampling rate.
DTMF dtmf = DTMF(n,sampling_rate);

void setup(){
  pinMode(led, OUTPUT);     
  Serial.begin(115200);
}

int nochar_count = 0;
float d_mags[8];
void loop()
{
  char thischar;
 
  // This reads N samples from sensorpin (must be an analog input)
  // and stores them in an array within the library. Use while(1)
  // to determine the actual sampling frequency as described in the
  // comment at the top of this file
  /* while(1) */dtmf.sample(sensorPin);
 
  // The first argument is the address of a user-supplied array
  // of 8 floats in which the function will return the magnitudes
  // of the eight tones.
  // The second argument is the value read by the ADC when there
  // is no signal present. A voltage divider with precisely equal
  // resistors will presumably give a value of 511 or 512.
  // My divider gives a value of 506.
  // If you aren't sure what to use, set this to 512
  dtmf.detect(d_mags,506);

  // detect the button
  // If it is recognized, returns one of 0123456789ABCD*#
  // If unrecognized, returns binary zero

  // Pass it the magnitude array used when calling .sample
  // and specify a magnitude which is used as the threshold
  // for determining whether a tone is present or not
  //
  // If N=64 magnitude needs to be around 1200
  // If N=128 the magnitude can be set to 1800
  // but you will need to play with it to get the right value
  thischar = dtmf.button(d_mags,1800.);
  if(thischar) {
    Serial.print(thischar);
    nochar_count = 0;
    // Print the magnitudes for debugging
//#define DEBUG_PRINT
#ifdef DEBUG_PRINT
    for(int i = 0;i < 8;i++) {
      Serial.print("  ");
      Serial.print(d_mags[i]);
    }
    Serial.println("");
#endif
  } else {
    // print a newline
    if(++nochar_count == 50)Serial.println("");
    // don't let it wrap around
    if(nochar_count > 30000)nochar_count = 51;
  }
}
Title: Re: DTMF decoder library
Post by: el_supremo on Dec 15, 2016, 05:12 pm
That code compiles with no errors or warnings with Arduino 1.6.13 on Win 7 Pro.

I don't understand how your code managed to produce an error in function main(). I've never had that happen.

The error "unable to find a register to spill" has occurred before with this code but it was in the DTMF sketch itself, not main(), and it was solved by splitting a complicated calculation into two statements.

Pete
Title: Re: DTMF decoder library
Post by: SHTIRLITZ on Dec 19, 2016, 01:33 pm
Ok, it seems was my mistake...

First time I download sketch from post #1, than i have a errors during compilation.
Afterwards, i got a files from link in post #6, compilation was passed OK!
Title: Re: DTMF decoder library
Post by: S1sm1x on Mar 04, 2017, 04:09 pm
With DTMF, the code is 2 of 8 consisting of one tone from the "row" frequencies and one tone from the "column" frequencies. The code uses the Goertzel algorithm to detect each of the 8 frequencies. The DTMF frequencies are arranged like this on a touchtone phone:
Code: [Select]

          1209  1336  1477  1633
 697,       1     2     3     A
 770,       4     5     6     B
 852,       7     8     9     C
 941,       *     0     #     D

So hitting the number '8' will send tones 852 and 1366 together. When receiving these tones, the code looks for them in the order they are listed in the dtmf_tones array. The code then maps them into two hex digits, one for the rows and one for the columns.
Code: [Select]

int dtmf_tones[8] = {
// Row tones (low order hex digit)
 697,     //1
 770,     //2
 852,     //4
 941,     //8
// Column tones (high order hex digit)
1209,    //1
1336,    //2
1477,    //4
1633     //8
};

If tones 852 and 1366 are received together, they will be converted into hex 24. This is then looked up in the dtmf_map array and the index where it is found (7) is then used to map into the dtmf_char array which translates it to the character '8'.

In your case, there are only six tones which aren't in a convenient row/column arrangement but it shouldn't be too hard to modify the code to read it provided that the individual tones are long enough for the Goertzel algorithm to reliably detect them.

Pete
Hi, before the most, I would like to congratulate for the great job.

Before posting this comment, I read a lot aboud Goertzel algorithm and I think that I can understand its fundamentals. Anyway, I have a basic questions which hasn't been fully approached by now.

I'm interested on recognizing more than one frequency from a single channel (ADC / analogic Arduino pin) and, if possible, even tracking more than 1 analogic pin connected to microphones.
Is there any clear implementation for that you may have? Can I use something from the Pete's above quoted article ?

By that time, I'm using successfully this Goertzel Algorithm implementation: https://github.com/jacobrosenthal/Goertzel .
I use an Arduino Mega instead of Uno preventing any RAM problems :)

Hoping for answers.
Have a nice day !

s1sm1x


Title: Re: DTMF decoder library
Post by: el_supremo on Mar 04, 2017, 05:20 pm
Quote
I'm interested on recognizing more than one frequency from a single channel
That is what the DTMF code does. But it only looks for two out of eight possible frequencies. When you want to detect more frequencies, there's a point where you might as well do an FFT instead of using Goertzel.
What are you trying to detect?

Quote
even tracking more than 1 analogic pin
That might be possible but I think you'll quickly run out of cpu time on a Mega.

Pete
Title: Re: DTMF decoder library
Post by: S1sm1x on Mar 04, 2017, 07:15 pm
That is what the DTMF code does. But it only looks for two out of eight possible frequencies. When you want to detect more frequencies, there's a point where you might as well do an FFT instead of using Goertzel.
What are you trying to detect?
Yes, I know that's what dtmf code does, but isn't it restricted to that freqs? For instance, how can I change the code to detect 2 freqs that aren't necessarily a tone ( like 800 Hz and 950Hz or any other pair conveniently separated in the spectrum)?
Going for FFT on Arduino Mega seems feasible? I haven't even tried it because I felt Mega was too weak for that.

That might be possible but I think you'll quickly run out of cpu time on a Mega.
I wonder if it was possible to apply simultaneously the Goertzel Algorithm to more than 1 analog pin. After analysing the real time calculus, it seemed kind a fast as long as the number of samples is kept below 200, am I wrong?

Thank you for the time :D

s1sm1x
Title: Re: DTMF decoder library
Post by: el_supremo on Mar 04, 2017, 09:43 pm
In DTMF.cpp there is an array of 8 integers called dtmf_tones. These are the eight DTMF tones that the library decodes. When the library is instantiated, it converts these tones into a coefficient that is used by the Goertzel algorithm. The code which does this is in the for loop which immediately follows this comment:
Code: [Select]
  // Calculate the coefficient for each DTMF tone

Quote
as long as the number of samples is kept below 200
You don't have a choice about the number of samples you get. You have to sample at a rate that is at least twice as high as the highest frequency you wish to detect. If you don't use all of those samples, you are just adding noise to your signal which will make the detection much more difficult.

You can do FFT on Mega but the size of the FFT (number of bins) will be restricted by how much processing time it takes. If the tones you wish to detect are widely spaced, you might be able to use, for example, an FFT with 64 bins or even only 32 bins. But if you want to detect tones that are, say, 10 or 20Hz apart it will require more bins which in turn requires a lot more cpu time and the Mega won't be able to handle it.

Pete
Title: Re: DTMF decoder library
Post by: S1sm1x on Mar 06, 2017, 05:16 am
In DTMF.cpp there is an array of 8 integers called dtmf_tones. These are the eight DTMF tones that the library decodes. When the library is instantiated, it converts these tones into a coefficient that is used by the Goertzel algorithm. The code which does this is in the for loop which immediately follows this comment:
Code: [Select]
  // Calculate the coefficient for each DTMF tone

Thank you! :D I tested and It's true!

You don't have a choice about the number of samples you get. You have to sample at a rate that is at least twice as high as the highest frequency you wish to detect. If you don't use all of those samples, you are just adding noise to your signal which will make the detection much more difficult.

You can do FFT on Mega but the size of the FFT (number of bins) will be restricted by how much processing time it takes. If the tones you wish to detect are widely spaced, you might be able to use, for example, an FFT with 64 bins or even only 32 bins. But if you want to detect tones that are, say, 10 or 20Hz apart it will require more bins which in turn requires a lot more cpu time and the Mega won't be able to handle it.


Pete
I know how to work with Nyquist Frequency, but to recognize some frequencies separated by 50 / 100 Hz (that I will specify on the d_mags array), how much bin size you think it is sufficient to plug more than 1 microphone (maybe 2,3,4 )?  I know that a larger bin size can slow the process , but don't have yours practical experience :)


Thank you for your time!

Pedro
Title: Re: DTMF decoder library
Post by: el_supremo on Mar 06, 2017, 05:19 pm
Quote
Yes, I know that's what dtmf code does,
Quote
I know how to work with Nyquist Frequency,
OK. I don't know what you don't know.

Code: [Select]
how much bin size you think it is sufficient
If you know "what dtmf code does" and you know "how to work with Nyquist Frequency" then you should be able to answer this yourself.

And, BTW, I have never used multiple microphones. Good luck with that.

Pete
Title: Re: DTMF decoder library
Post by: pjrc on Mar 06, 2017, 08:30 pm
Acquiring multiple signal streams at high enough (and low jitter) sample rates *and* performing real-time FFT or even Goertzel analysis on all them seems like quite a tall task for an 8 bit AVR like Arduino Mega.

This sort of thing is pretty achievable on more powerful 32 bit boards where DMA can efficiently acquire the samples.  But to do it on AVR would be quite a feat!
Title: Re: DTMF decoder library
Post by: fatpat on Aug 13, 2017, 09:30 pm
Hello

I'd like to thanks "el_supremo" for his work on the DTMF decoder. I'm using it for activating a led strip through a MOSFET remotely using a HAM radio using DTMF code. It's very simple but I had to modify a bit the DTMF library to be able to detect signal without DTMF code. In my case I wanted to activate the led strip at signal detection (without DTMF code) and then I added the possibility to shutdown the strip or change its brightness. But I must activate the led strip when a signal is received (just push the PTT button of the emitter as it is used as a security element and I prefer having the led to be up even if not necessary insted of having a shutdown led when it must be turned on).

The goal was to:
- have a great range
- reusing everything possible that I have at home
- cheap and simple
- must be turned of quickly and efficiently
- after 5 minutes, it shutdowns


Anyway, I have uploaded the code github: https://github.com/fatpat/arduino-remote-switch-dtmf (https://github.com/fatpat/arduino-remote-switch-dtmf)


Thanks you for your work !!!
Title: Re: DTMF decoder library
Post by: Adrianotiger on Aug 09, 2019, 06:21 pm
I am trying to implement it on the ESP32 but I am not able to see any DTMF result.

I have 2 problems:
1 - even if it is powered with 3.3V, the signal is between 1.2V and 1.8V. Can I amplify the signal, just with an amplify variable in this line: Q0 = coeff * Q1 - Q2 + (float) (sample - adc_centre) * amplify; ??

2 - New processors have much more than 16MHz, how can I calculate the sampleFrequency? For example, I can execute the readAnalog(pin) up to 24.000 times each second. Can I write 240000 or is there a formula (I read somewhere sample rate / 2 = frequency)? Or can I still write 8900 as samplefrequency?
Title: Re: DTMF decoder library
Post by: jremington on Aug 10, 2019, 04:08 am
1. That won't help. External amplifiers will help.

2. Read the documentation on the readAnalog() function to determine the possible sampling rates and examine your code to determine the actual sampling rate.

Quote
Or can I still write 8900 as samplefrequency?
No. The sampling rate is absolutely critical and you must know what it is, or adjust it correctly, in order for the algorithm to work at all.
Title: Re: DTMF decoder library
Post by: Adrianotiger on Aug 22, 2019, 03:36 pm
Thank you very much  el_supremo for this library.
It helped me alot with my project. I uploaded it to GitHub too:

https://github.com/Adrianotiger/phoneDTMF (https://github.com/Adrianotiger/phoneDTMF)

My scope was to make it working on the ESP32 to detect the DTMF landline phone, so I made some changes:
- this library will detect the frequency automatically. On some microcontroller the analogRead can be executed 50.000 times each second, but internally it is still sampled with 6000Hz. So this library will check if 6000Hz can be reached.
- ADC center is detected at beginning, when you init the library, so you don't need to set a center anymore.
- Magnitude is also set automatically (hope my algorithm will work everywhere) if you want

It still use floats, but the intent was to write a library for processors like on the Arduino Due, ESP and Teensy boards, not 8-bit processors.
(https://github.com/Adrianotiger/phoneDTMF/raw/master/circuits/oled.jpg)

Title: Re: DTMF decoder library
Post by: Tombays on Aug 29, 2019, 09:13 pm
How i can connect thelephone? I mean not smartphone, i mean phone that stays at home. I connected in parallel a telephone, a transformer and a 12 volt power supply. When I connect the headphones to the secondary coil of the transformer - everything is audible ... But when I connect telephone to arduino through the circuit drawn in the image, it does not determine anything. analog output - 0 when nothing and 15-30 when I dial the number.
Title: Re: DTMF decoder library
Post by: 6v6gt on Sep 13, 2019, 01:52 pm
Here is yet another software DTMF decoder based on the https://github.com/jacobrosenthal/Goertzel (https://github.com/jacobrosenthal/Goertzel) library. The main differences are that this version does not control the sample frequency by calling analogRead() in a loop but uses a timer to drive the ADC at any user-selected frequency. The sample buffer is filled by the ISR of the ADC. Also, the bit resolution is 8 bits instead of the normal 10 to optimise the calculation speed.
It appears quite reliable even at quite high rates (50mS tone burst, 50mS space) although I need it only for detecting tones generated by a phone keypad which is far less demanding.
I also made a few other minor changes to the library because the original did not support multiple instances due to its use of global instead of instance variables. The solution described here uses 8 Goertzel objects, one for each detection frequency. However, there is only a single sample buffer.
In addition, in the test sketch, I have added a validation parameter to control the number of required identical consecutive repetitions of the detection of a tone before it is considered valid.

In principle, it works like this:
8 Goertzel objects are created, one for each detection frequency.
The shared sample buffer is initiated and a pointer is passed to the class.
The coefficients are then calculated for each Goertzel object.

During operation, the sample buffer is filled with the specified number of samples.
The 4 "row" Goertzel objects test the sample and the "winner" frequency is determined, that is the one which yields the highest magnitude.
The same applies to the 4 "column" Goertzel objects. At the end, the received DTMF character is determined.
The operation is repeated.
When the exact required number of identical consecutive detections is reached, the result is delivered together with a quality statistic.


There are a number of parameters to play with:
The number of samples: 64 is good with 9600sps. 128 is good with 19200sps.
The sample frequency (sps): see above
The ADC prescaler:  ( /8 or /16 seems OK)
The number of consecutive matches required to validate a result: This however can be slow. For large numbers of samples and high DTMF rates, this parameter must be low, say 1 or even 0.
The magnitude threshold (this is now non-critical because the highest magnitude row and column matches are selected, but it must be low enough to ensure that no valid matches are lost). 500 is good for 8 bit ADC resolution. 2000 is good if you revert to 10 bits

On the hardware side, attempt to match the 2 resistors between Vcc and Ground to ensure that the the midpoint voltage is Vcc/2.
For testing, I use an old telephone, some online resources like http://dialabc.com/sound/generate/ (http://dialabc.com/sound/generate/) and https://www.audiocheck.net/audiocheck_dtmf.php (https://www.audiocheck.net/audiocheck_dtmf.php) and the el_supremo test files contained in the zip file in the OP of this thread).
Do NOT use the supplied circuit to connect directly to a telephone network where voltages up 90VAC may be encountered.

To use, simply copy the 2 library parts (.h and .cpp) into the folder containing the .ino file.


Notes:
1. This solution uses ATmega328P (Arduino Uno etc.) hardware registers and may have to be adapted for other boards.
2. Since the ADC is connected to a timer, the simultaneous use of analogRead() may cause problems.
3. Timer1 is used by this application.

Future:
1. attempt to drop floats to optimize calculations
2. Allow the timer driving the ADC to run only during the capture of the sample to free these resources for other purposes.