Een DTMF-decoder bouwen met alleen een Arduino – Geen extra IC's nodig
Onderdelen en benodigdheden
| Arduino UNO | 1 |
| LED (standaard) | 10 |
| Breadboard (standaard) | 1 |
| Draadjes (standaard) | 20 |
Apps en online diensten
- Arduino IDE
Over dit project
Tijdens het doorlopen van mijn semesterprojecten kwam ik een DTMF-gestuurde auto tegen die de CM8870-IC gebruikte als DTMF-decoder. De gedecodeerde binaire data werd doorgegeven aan de Arduino voor besturing (links, rechts, vooruit, achteruit). Het gebruik van een externe IC voor de decoder vond ik lastig te integreren, en ik was op zoek naar code of een bibliotheek die de IC kon vervangen. Uiteindelijk vond ik de Goertzel.h-bibliotheek, gebaseerd op het Goertzel-algoritme. Deze kan bepalen of een specifieke frequentie aanwezig is in een toon door het aantal pulsen per tijdseenheid en hun amplitudebijdrage te berekenen.
Ik gebruikte de basisvoorbeeldcode als uitgangspunt en schreef een programma dat de dominante DTMF-frequenties in de toon detecteert en decodeert naar het ingedrukte cijfer tijdens een telefoongesprek.
Code
Arduino-code voor DTMF-decoder
Compileer en upload de code in de Arduino IDE. Vergeet niet eerst de bibliotheek te installeren via: GitHub - Goertzel bibliotheek
/* De basis van deze implementatie is de code van Kevin Banks (https://www.embedded.com/design/embedded/4024443/The-Goertzel-Algorithm).
Volledige credits aan hem voor de generieke implementatie en uitleg.
Het Goertzel-algoritme is al lang bekend, zie https://en.wikipedia.org/wiki/Goertzel_algorithm.
Het wordt vaak gebruikt voor DTMF-tonedetectie als alternatief voor de FFT, omdat het sneller is en minder overhead heeft
(alleen zoeken naar één frequentie in plaats van alle frequenties).
Aangepast door Mian Mohammad Shoaib – vrijgegeven in het publieke domein.
Vragen? mmshoaib8452@gmail.com */
#include <Goertzel.h>
int sensorPin = A0;
const int N = 100; // Aantal samples (gevoeligheid/ snelheid)
const float threshold = 2000; // Minimale amplitude voor detectie
const float sampling_freq = 8900; // Max detecteerbare frequentie = sampling_rate/2
float x_frequencies[4]; // Kolom-frequenties (hoge tonen)
float y_frequencies[4]; // Rij-frequenties (lage tonen)
void setup() {
pinMode(13, OUTPUT); // Detectie-LED
for (int i = 2; i <= 12; i++) pinMode(i, OUTPUT); // Output pinnen voor cijfers 0-9
Serial.begin(9600);
// DTMF frequentiematrix
x_frequencies[0] = 1209; x_frequencies[1] = 1336;
x_frequencies[2] = 1477; x_frequencies[3] = 1633;
y_frequencies[0] = 697; y_frequencies[1] = 770;
y_frequencies[2] = 852; y_frequencies[3] = 941;
}
bool detect_tone(float freq) {
Goertzel goertzel = Goertzel(freq, N, sampling_freq);
goertzel.sample(sensorPin);
float magnitude = goertzel.detect();
if (magnitude > threshold) {
digitalWrite(13, HIGH);
delay(250);
digitalWrite(13, LOW);
Serial.println(freq);
return true;
}
return false;
}
void print_number(int row, int column) {
int number = 0;
// DTMF keypad mapping
if (row == 0) {
if (column == 0) number = 1;
else if (column == 1) number = 2;
else if (column == 2) number = 3;
else number = 10; // A
} else if (row == 1) {
if (column == 0) number = 4;
else if (column == 1) number = 5;
else if (column == 2) number = 6;
else number = 11; // B
} else if (row == 2) {
if (column == 0) number = 7;
else if (column == 1) number = 8;
else if (column == 2) number = 9;
else number = 12; // C
} else if (row == 3) {
if (column == 0) number = 14; // *
else if (column == 1) number = 0;
else if (column == 2) number = 15; // #
else number = 13; // D
}
if (number < 10) {
digitalWrite(number + 2, HIGH);
Serial.print(number);
} else if (number == 10) Serial.print('A');
else if (number == 11) Serial.print('B');
else if (number == 12) Serial.print('C');
else if (number == 13) Serial.print('D');
else if (number == 14) Serial.print('*');
else if (number == 15) Serial.print('#');
Serial.println();
delay(800);
for (int i = 2; i <= 12; i++) digitalWrite(i, LOW);
}
void loop() {
int column = 0, row = 0, i = 0;
// Detecteer kolom (hoge toon)
while (true) {
if (detect_tone(x_frequencies[i])) { column = i; break; }
i = (i + 1) % 4;
}
// Detecteer rij (lage toon)
i = 0;
while (true) {
if (detect_tone(y_frequencies[i])) { row = i; break; }
i = (i + 1) % 4;
}
print_number(row, column);
}
Schema
De schakeling gebruikt 10 LED's aangesloten op digitale pinnen 2 tot 12. Deze branden wanneer de overeenkomende cijfers (0-9) worden gedetecteerd. Een detectie-LED op pin 13 knippert kort bij elk gedetecteerd signaal. Speciale tekens (*, #, A, B, C, D) worden via de seriële monitor weergegeven.
De audio-input (van een AUX-kabel of telefoon) wordt aangesloten op analoge pin A0, met een 1µF condensator in serie om DC-offset en lage frequenties te filteren.

Productieproces
- Bouw een indrukwekkend monitor Ambilight-systeem met Arduino
- Bouw een Ultrasonische Zweefapparaat met Arduino – Stap-voor-stap Handleiding
- SERENA: Een Aangepast Arduino Mega 2560 Alarmsysteem Met TFT LCD Touchscreen
- Een slimme voltmeter bouwen met Arduino en smartphone – Eenvoudig DIY-project
- Real-time IoT hartslagmonitor met Arduino en MAX30100
- Morsecode-communicatie met lasermodule – Tweezijdig Arduino-project
- Arduino Uno WiFi Webserver: LED aan/uit schakelen via browser
- Slimme Parkeer Teller: Real-time Voertuigvolging met Arduino, Processing en PHP
- Bouw een geautomatiseerde Google Chrome Dino Game met Arduino
- Python 3 naar Arduino UNO: Eenvoudige Commando Besturing en LED Demo
- Bouw een compacte FM-radio met Arduino Nano en RDA5807M