This project contains the details of using a Microchip PIC12F683 8 bit microprocessor to detect DTMF tones. The completed program allows the processor to be programmed with a string of DTMF tones to detect. If the programmed string is detected in the audio applied the audio input, the output will turn on (go high), and can be used to control other circuitry of the users design.

UPDATE! 11/2/2010:
Due to requests for the source code, I have attached it. I have created a new step (Step 9) containing the *.asm file, along with some important notes.

UPDATE! 10/12/2010:
The HEX file for progdramming that I originally attached to this instructable had a bug that prevented successful programing of the tone sequence, unless the microprocessor was in serial output mode while in programming mode. The HEX file attached now works properly. Sorry for any inconveniene caused for those who may have tried the original code.

I have included the *.hex file needed to program the microprocessor, 12F683_DTMF_DECODE_01A.HEX. You will need a programmer for PIC microprocessors. I have seen instructions on this site for building your own, but I cannot speak for any of them. The programmer I use came from a company called Micro Engineer Labs, Inc at www.melabs.com.

The only other parts needed are the electronic components, as shown in the schematic in step 3, Circuit Details. Digikey (www.digikey.com) is an excellent source for electronic components .

A telephone or other means of generating DTMF tones is also needed for programming the microprocessor with the the sequence of tones you want to detect. This is described in more detail in step 4.

Step 1: Quick DTMF Overview

There are a total of 8 tones used to represent DTMF or "touch tone" numbers. The tones are in two groups of four, often referred to as the low and high tones. A number is represented by an audio waveform consisting of the sum of one of the low tones and one of the high tones. This can easily be visualized in a matrix format, as shown in the figure. Note that the DTMF system actually allows a total of 16 different tone pairs. The A, B, C, and D tones shown on the right hand column of the keypad in the figure are not included on a normal telephone, but they are often included on two way radios that have a DTMF keypad. They are sometimes used by two way radios for business or ham radio. The software for the project will also detect these additional 4 tone pairs.

Step 2: Signal Processing Algorithm Description

The PIC 12F683 microprocessors built in A/D converter is used to sample an input audio waveform. The samples are analyzed using the Goertzel algorithm to detect whether any of the 8 tones are present.

The Goertzel algorithm is a signal processing algorithm which is used for detecting a single frequency. It acts as a very narrow bandpass filter.  It produces a very sharp response to frequencies within the pass band, and a much lower response for frequencies outside the pass band.

In my implementation of the algorithm, the samples are taken at a rate of 4 times the frequency to be detected. Using a sample rate of 4 times the target frequency makes coefficients used in the algorithm be equal to 1 or 0. This eliminates the need to perform complicated and time consuming multiplication on an 8 bit micro.  I haven't included all the mathematical details of the algorithm here, but  a Google search will produce articles on the topic if you are interested in learning more about the algorithm itself.

Due to the restriction that the sampling rate must be 4 times the target frequency, the sample rate required will be different for each of the 8 tones that are used for DTMF. So, the algorithm must be run once for each of the 8 frequencies . This means that a separate set of samples must be taken for each frequency of interest, as each frequency will be tested at a different sample rate.

The sharpness of the filter response versus frequency is proportional to the number of samples taken. The response of the algorithm must be sharp enough that it responds to the target frequency, but does not respond to any of the other 7 frequencies. A value of 120 samples was found to produce a reasonably narrow response in experimentation. There is of course a tradeoff between number of samples and the execution time. In order to detect short tones, the execution time should be as short as possible. But, to make a narrow response the number of samples must be larger, resulting in a longer execution time. The number of samples becomes the limiting factor in how short of a tone can be detected.

Once the algorithm has processed 120 samples, it outputs a value. The magnitude of this value is proportional to the amplitude of the frequency of interest. This resulting value is compared against a threshold to determine if target frequency is present.
Once the algorithm has been run for all 8 frequencies, the microprocessor performs logic on the results to determine if a valid DTMF pair is present. A valid DTMF pair is considered to be present only if 1 row freq and 1 col freq is detected. Other combinations are regarded as invalid.

The graph shows the actual response measured using this algorithm running on a PIC 12F683.  The graph shows the frequency response of all 8 times the algorithm is run.  The x axis is frequency, in Hz.  The vertical axis is the value output by the algorithm.  The input was a 1V sine wave, swept from 600Hz to 1800Hz.  Note that the width of the response is wider for the higher frequency filters.  This is due to the fact that the width of the response is proportional to the sample rate, divided by the number of samples taken.  In this implementation of the algorithm, the sample rate is always four times the target frequency, to simply and speed up the math.  However, the same number of samples is used for each of the 8 target frequencies.  The to make the width of the response the same for each would require using the same sample frequency for each, which would involve more time consuming mathematics, or it would require that the number of samples taken at the higher frequencies be greater, which would lengthen the execution time.  If you were using a microprocessor with real DSP functionality, the extra math could be performed very fast and so it would be something that you would most likely include.

Despite the differences in the width of the response, the operation has been very robust at detecting tones, even in the presence of significant noise.

Step 3: Circuit Details

The schematic for the circuit is shown below.  The connection labeled +5V must connect to a regulated 5V power supply, such as the output of LM7805  5 volt regulator circuit.

The A/D converter measures voltages between 0V and 5V. The audio input will be a signal that swings above and below 0 volts, so its waveform will have positive and negative portions. In order to sample the input audio waveform with the A/D converter, the input signal needs to be shifted.

The voltage divider created by resistors R1 and R2 sets the bias at half of the A/D input range (2.5 Volts).  The capacitor C1 couples the AC input signal to the A/D input, so now the input waveform swings about 2.5 Volts instead of swinging about 0 volts, as shown in the graphs.

The microprocessor requires an 8 MHz crystal X1 and two capacitors C2 and C3 as shown.  LED1 is a status indicator used for visual feedback. R3 is used to limit the current from the output of the microprocessor that drives the LED. C4 is a decoupling capacitor used with the microprocessor.

The functions of the pins on the microprocessor U1 are as follows:
1)VDD.  Apply +5V to this pin
2)Crystal circuit connection, as shown in schematic
3)Crystal circuit connection, as shown in schematic
4)Programming mode input.  When this line is connected high via JMP1, the processor will be in programming mode after the power to the circuit is cycled and the processor resets.  If JMP1 is removed, the pin is pulled low via R4 and the unit will wake up in tone sequence detect mode after a power cycle.
5)Output.  This is the line that goes high when the programmed sequence of tones is detected.
6)LED indicator output.  This pin is also used for a special serial output, as described in step7.
7)A/D input.  This is where the audio input is sampled by the microprocessors internal analog to digital converter.
8)VSS.  Connect this pin to ground.

Step 4: Programming the Sequence of Tones to Detect

Programming mode is used to program the micro with the string of tones to be detected. To place the micro into programming mode, the programming mode input must be jumpered to +5V via JMP1, placing the programming mode pin in the logic HIGH state when the microprocessor powers up. (refer to the schematic).  Shortly after power up, the programming mode input is sampled by the micro to determine if programming mode has been selected.

The LED will issue 2 slow blinks when it powers up in programming mode, and 3 slow blinks when it powers up in decode mode.

Programming is accomplished by applying audio to the input containing the string of tones to be decoded. The audio must be of sufficient amplitude to be detected, but not of such great amplitude that the input signal is clipped and distorted. Any source of audio can be used. The tones must be of a long enough duration to be detected by the algorithm. The LED will turn on while a valid tone is detected. The sequence of tones is stored in the microprocessors internal EEPROM. The tone string can be as long as 100 digits.

The schematic shows a simple arrangement that allows almost any common touch tone telephone to be used to generate tones for programming and experimentation. Note that the circuit shown here is not meant to connect to the telephone line! The 9v battery provides power to the telephone, and the 330 ohm resistor limits the current in the circuit.  The two terminals on the left  connect to a telephone set, and the terminals on the right connect to the audio input of the detector circuit and ground

When a button is pressed on the phone, you should be able to hear it in the receiver. The graph shows a waveform I captured with an oscilloscope at the input to the microprocessor. The waveform shown was generated by a phone that was connected to the microprocessor using this circuit.

The output of a computer soundcard could also be used for programming. Connect the soundcard line out to the audio input of the circuit, and play a wave file containing each tone to be programmed. You will have to experiment with the output volume to ensure that the signal level into the audio input of the microprocessor is such that the detector will work correctly.

Once the string has been entered, remove the jumper JMP1. This signals the micro that programming mode is complete. The LED will now blink two fast blinks, followed by 2 seconds off, followed by two fast blinks, and then repeat that blink sequence indefinitely to indicate that the programming was successfully completed. If you do not remove the jumper JMP1 before powering down, the programming is not complete and you will have to repeat the process.

Step 5: Detecting the Programmed Sequence of Tones

If the microprocessor has been successfully programmed with a string of tones to detect, then decode mode can be used. To place the micro into decode mode, make sure the jumper JMP1 on the programming mode input has been removed, (which puts this pin at the logic LOW state)  and reset the micro by removing and reapplying power. If there is no valid program, the LED will show 4 fast blinks, followed by 2 seconds off, and this will repeat indefinitely to show that no program is present.

If a valid program exists, the microprocessor will now listen for tones, and if the sequence of tones received matches that stored in the eeprom, the output will go high for 1 second. The microprocessor will then return and listen for the string again, and the output will be turned on for one second if the correct tone sequence is detected again. The micro repeats this as long as it is powered up and it is in decode mode and a valid program is present.

This output can be used by other circuitry. For example, the output could be connected to the gate of a MOSFET, which then turns on a light as shown in the schematic. The output can be detected by another microprocessor which can then take whatever actions the user desires.

Step 6: Serial Output Mode

As a debugging aid, I have added a serial output mode that contains some useful information for the experimenter.

There were no extra pins available to use as a dedicated serial output, so it has to share a pin with the LED indicator. In serial mode, the LED no longer functions as an indicator of a valid DTMF tone. The LED will appear illuminated all the time, with noticeable flickering when serial data is being transmitted.  The LED will still indicate conditions such as successful power up (2 or 3slow blinks, depending on mode), succesfullprogramming (2 fast blinks, repeated indefinitely), and no valid program (4 fast blinks, repeated indefinitely)

To invoke the serial output mode, you will need to short the A/D input pin of the microprocessor used for audio input (pin 7 of U1 in the schematic) to ground. Then, cycle power to the circuit.  When the microprocessor resets, it will check the state of the audio input line and see that it is sitting close to 0 volts, whereas it will sit close to +2.5 volts normally.   Of course, you will need to then remove the short to ground on the audio input, otherwise any audio input will be shorted to ground. It is only necessary that the audio input be shorted to ground during the microprocessor reset.  It can be removed immediately after the LED blinks twice after power up.

You will know that the serial output is active if you see the LED flickering and you can read the serial stream on your computer.

To monitor the serial output with a PC, you will need to convert the 5 volt output of the microprocessor to RS-232 levels that can be read by a computers serial port. A circuit using the MAX232 chip can be used for this purpose.

One line of output is transmitted each time the frequencies are swept. The fields of information are separated by commas. This output can be easily recorded by a terminal program like Hyperterminal and then imported to Microsoft Excel for further processing if desired.

When configuring a terminal to view the output, the settings to use are 9600 baud, 8N1, no parity, no flow control.

The debug output contains the following information, from left to right:
*The output value for each of the 8 frequencies, expressed in decimal. The values are 5 digits long, and include any leading zeros.
*The output of the logic. This will either be 0-9,#,*,A,B,C,D for valid tone pairs, "S" if no tones are detected, or "?" if some invalid combination of tones are detected.

A sample of the serial output is included below:


In this sample, the digit "1" was detected. Notice that the filter output values for the first row frequency and the first column frequency are much larger than the other 6 frequencies, as would be expected for DTMF digit "1".

The code looks for the same digit to be detect in two consecutive sweeps before considering that tone to be detected, for both programming and decoding.  The serial output will create a new line showing only the digit detected, so that it stands out to the user, as shown in the sample serial output below:


If the microprocessor resets in tone detect mode while the serial mode is also enabled, The first thing that will be transmitted is the tone sequence to detect that is currently programmed into the microprocessor.  This will look like "PROGXXX...X".  If no valid program exists, it will transmit "NO PROG".  If the microprocessor resets in programming mode with the serial mode enabled, it will transmit the programmed sequence one the programming mode pin is brought from high to low.  Again, this will look like  "PROGXXX...X".  These provisions are useful for verifying that the sequence you tried to program into the micro was programmed correctly.

Step 7: Limitations

Due to the number of samples that have to be taken to ensure a sharp response, the shortest tone that can be detected is approximately 0.5 seconds.  Therefore, the micro will not be able to reliably detect short tones, such as those generated by speed dial.  Also, some phones, especially most cordless phones, do not produce a continuous tone when pressed, rather they generate only a short tone.  Cell phones may also not allow the generation of a longer tone.  You will have to check the capabilities of whatever equipment you are using.  

For programming and decoding, the tones applied should be at least 0.5 seconds long, preferably longer to ensure detection in marginal conditions.

Step 8: Applications

There are many possible applications for a circuit that can decode a string of DTMF tones.  These are generally remote control applications.  For example, you could construct a circuit to use the output of this decoder to control appliances remotely via your home phone.   This will require an additional interface between the phone line and the audio input of the decoder circuit.  Do not connect it directly to a phone line, as there are large DC voltages and transient voltages due to ringing that would damage the circuit.  Search on the internet for an appropriate interface circuit if you need to connected the detector to a land line telephone.  There is an article on www.epanorama.net that covers the topic of telphone interfacing in detail.

Another application would be to connect the audio input of the decoder circuit to the output of a two way radio for a wireless remote control.  I have successfully detected a string transmitted via handheld FRS type radios.  This type of arrangement requires a means of generating DTMF tones and applying them to the microphone input.

As for the Goertzel tone decoding algorithm in general, there are many more interesting applications.  A processor could be programmed to detect musical notes or any other specific frequency, and trigger an action.  The software attached to this instructable is for DTMF only. 

Step 9: Source Code

The source code is written in assembly, using the free MPASM tool from Microchip.

The *.asm file contains the entire code used to create the *.hex file attached to Step 1. You should be able to assembly the *.asm file and get a *.hex file that will work exactly like the one I attached originally.

At a high level, the program contains code to do the following:

*Code for the programming process.
*Code for detecting that receipt of the programmed string of DTMF digits.
*Code for the simplified Goertzel algorithm.
*Code for analyzing the results of the Goertzel algorithm to determine if a valid DTMF tone is present.


The code uses the following peripherals of the PIC 12F683 processor:
*A/D converter
*Timer1 (16 bit timer)
*Internal EEPROM, for storaging the programmed DTMF sequence.

There is no harware serial peripheral on this processor, so I had to implement it in software ("bit banged")

Other Details:

The code is designed for use with an 8MHz external crystal oscillator.
This gives a 2MHz instruction cycle frequency, so each instruction cycle is 0.5 microseconds long. The internal 8MHz oscillator has too high a tolerance (up to 2%) to use for this application.

If you intend to port this to a different PIC processor, you will have to make sure that all the peripherals, registers, and other details are configured properly. There can be slight differences between other very similar PICs.

<p>HI</p><p>CORRECTION!</p><p>I am looking for a programmer that can produce something similar to this to the extent of detecting a DTMF tone from an audio signal and sending a signal high when a correct digit has been detected and also sending the correct digit via an 8 bit port on the processor. Is this something you would be interested in doing?</p><p></p><p><a rel="nofollow">[delete]</a></p>
<p>HI </p><p>I am looking for a programmer that can produce something similar to this to the extent of detecting a DTMF tone from an audio signal and sending a signal high when a correct digit has been detected and also sending the correct digit to a 7 segment display. Is this something you would be interested in doing?</p>
<p>very nice writing i will study it.</p>
What is the best way of giving input.... <br> <br> <br>Thank you.. <br> <br>
what can i put on the output pins? <br> <br>thank you! <br>marC:)
The output that goes high once the sequence of tones is detected is just a logic level signal from the microprocessor. Like other digital outputs, it will be around 0 volts when &quot;LOW&quot; and around &quot;5V&quot; when high in the circuit shown. The output can only source a small amount of current, usually several milliamps. This output can then be used as an input by other logic ciruitry which may process or act on it. If the output is to controll a load that operates at a higher current or voltage, such as turning on a lamp, then the signal from the microprocessor would need to drive a transistor. Really the possibilities are wide open as to how the output can be used.
what is a practical use of this? <br> <br>thank you! <br>marC:)
The practical use is to dected a specific string of DTMF tones in an audio signal and turn something on (or signal another circuit) when the string is detected.
Great utilisation of an inexpensive microprocessor. <br>I am working on a project requiring similar functionality, the only different is that it requires the learning function of a single tone (not DTMF). <br>Would you be able to point in the right direction of modifying the ASM file ? <br>Thanks,
If you are looking for something that can detect a single tone, I have another project on this site which might work for you: <br> <br>https://www.instructables.com/id/Frequency-Detector-using-PIC-12F683-Processor/ <br> <br>That project detects a single frequency between 148Hz and 2148Hz. The frequency to be detected is set using a potentiometer.
The frequency range is perfect. <br> <br>My project requires the learning feature, is it easier to modify the codes so the detected frequency is set by capturing the tone into the EEPROM instead of the use of potentiometer ?
The way the code works is that the potentiometer is read, and based on that the software looks for a specific frequency. It would be a fair amout of extra code to detect what the frequency is first, and then look only for that frequency after that. It would involve sweeping through the whole frequency range to see what the input frequency is, which would be somewhat time consuming. <br> <br>You could just adjust the potentiometer while the frequency is applied and leave it in the position where the frequency is detected. <br> <br>So, there isn't a real straightforward way to train the device by having it determine the input frequency with the present revision of the code.
Can you program a CTCSS decoder 12F683? <br>Included learning function of the CTCSS tone. <br>Frequencies: 67Hz, 71.9Hz, 77Hz, 82.5Hz, 88.5Hz, 94.8Hz, 100Hz, 103.5Hz, 110.9Hz, 118.8Hz and 74.4Hz, 79.7Hz, 85.4Hz, 91.5Hz, 97.4Hz, 123.0Hz <br>
Would this idea (subtone decoder) work with the 12F683: <br> <br>There are only 4 dual - frequency. These will only be changed: <br> <br>697 Hz: replace = 28 Hz <br>Delete: 770 Hz <br>Delete: 852 Hz <br>941 Hz: replace = 38 Hz <br> <br>and <br> <br>1209 Hz: replace = 48 Hz <br>Delete: 1336 Hz <br>Delete: 1477 Hz <br>1633 Hz: replace = 58 Hz <br> <br>
I've never worked with CTCSS before, but I am familiar with the general principle. Using code similar to that in the asm file included in the instructable, one could scan for the 16 tones you listed, and then determine if any are present. It would take some modification to the code, as the logic that would be needed would be different from that used with the DTMF. Also, the code would take longer to sweep through the list of frequencies, as there are 16 in your list versus 8 for DTMF. On top of that, I see that these frequencies are much more closely spaced than DTMF, so the algorithm would have to be configured to give a much sharper response to differentiate them. This would likely increase the overall detection time even further. I think that your application is getting to the point where a real DSP processor is needed, and not the general purpose 12F683 or similar PIC processor. In my own research into the Goertzel algorithm, one artical I came across describes using it for CTCSS applications. Here is a link:&nbsp;<br> <br> <a href="http://www.eetindia.co.in/STATIC/PDF/200604/EEIOL_2006APR04_EMS_RFD_SIG_TA.pdf?SOURCES=DOWNLOAD">http://www.eetindia.co.in/STATIC/PDF/200604/EEIOL_2006APR04_EMS_RFD_SIG_TA.pdf?SOURCES=DOWNLOAD</a><br> <br> The article doesn't use a PIC processor, but it does give a good amount of detail about using this approach for CTCSS.<br>
To those who requested the source code, it has been added. Refer to step 9 of the instructable. <br> <br>I can answer a few questions if you have any. I'd be interested in any cool applications that anyone come up with. <br> <br>Enjoy.
Thanks for the code. I had issues downloading it because it saved as a weird .tmp file. But I searched it and found that if you rename the file that it will work then. again thanks for the code.
No problem. I hope it works out for your senior design project.
Would you be willing to post your assembly code? I am working on a senior design project and am trying to learn how to write the code for the dtmf detection part of our project. Any help would be much appreciated. I know I can use a chip like the MT8870 but want to encode it on our microprocessor.
I recently had another request for the source code. I did not attach it to the instructable originally, as I had not commented it very thoroughly. I am wrapping up the comments and should be able to update the instructalbe with the attachment in about a week. <br> <br>You can check back with this instructable in the future, to see whether I have updated the intro section with a notice stating that the source code has been added. <br>

About This Instructable




Bio: "But I was going to Toshi station to pick up some power converters!"
More by LargeMouthBass:Rugged R2D2 Pinata Audio Delay Module Reverse Engineering an Electric Fence Charger 
Add instructable to: