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.
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.
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
Step 2: Signal Processing Algorithm Description
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 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
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 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
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
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
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 *.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:
*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")
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.