Construa um Decodificador DTMF Usando Apenas um Arduino – Sem CIs Externos
Componentes e Materiais
| Arduino UNO | × | 1 |
| LED (genérico) | × | 10 |
| Protoboard (genérica) | × | 1 |
| Jumpers (genéricos) | × | 20 |
Aplicativos e Serviços Online
- Arduino IDE
Sobre o Projeto
Durante a seleção do meu projeto de semestre, encontrei um carro controlado por DTMF que utilizava o CI CM8870 como decodificador. O sinal binário decodificado era enviado ao Arduino para comandar movimentos de frente, trás, esquerda e direita. A principal dificuldade estava na integração do CI decodificador externo. Busquei por códigos ou bibliotecas que pudessem substituir o CI por software, mas não encontrei uma solução satisfatória.
Foi então que descobri a biblioteca Goertzel.h, baseada no algoritmo de Goertzel. Este algoritmo detecta a presença de uma frequência específica em um sinal de áudio, calculando o número de pulsos por unidade de tempo e sua contribuição de amplitude. Utilizei o exemplo básico da biblioteca como base e desenvolvi um código capaz de detectar as frequências DTMF dominantes no tom e decodificá-las, identificando qual tecla foi pressionada do outro lado da linha telefônica.
Código
Código Arduino para Decodificador DTMF
Compile e faça o upload do código na Arduino IDE. Não se esqueça de instalar a biblioteca primeiro.
Link da biblioteca: https://github.com/jacobrosenthal/Goertzel
/* Implementação básica de um decodificador DTMF para detectar os 16 caracteres DTMF
* a partir do pino analógico A0 e fornece a saída decodificada verificando todos os
* tons superiores e inferiores na matriz DTMF.
* Baseado no código de Kevin Banks (https://www.embedded.com/design/embedded/4024443/The-Goertzel-Algorithm)
* e no algoritmo Goertzel (https://en.wikipedia.org/wiki/Goertzel_algorithm).
* Modificado por Mian Mohammad Shoaib - Domínio público.
* Dúvidas: MMSHOAIB8452@GMAIL.COM
*/
#include <Goertzel.h>
int sensorPin = A0;
const int N = 100; // Número de amostras (ajuste para sensibilidade/velocidade)
const float threshold = 2000; // Amplitude mínima do tom para ser considerado
const float sampling_freq = 8900; // Frequência de amostragem (máx. detectável = sampling_freq/2)
float x_frequencies[4]; // Frequências das colunas (tons altos)
float y_frequencies[4]; // Frequências das linhas (tons baixos)
void setup() {
pinMode(13, OUTPUT); // LED indicador de detecção de tom
// Pinos 2 a 12 como saída para exibir números 0-9 via LEDs
for (int i = 2; i <= 12; i++) pinMode(i, OUTPUT);
Serial.begin(9600);
// Frequências das colunas (Hz)
x_frequencies[0] = 1209;
x_frequencies[1] = 1336;
x_frequencies[2] = 1477;
x_frequencies[3] = 1633;
// Frequências das linhas (Hz)
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); // Captura N amostras
float magnitude = goertzel.detect(); // Verifica presença da frequência alvo
if (magnitude > threshold) {
digitalWrite(13, HIGH); // Pisca LED no pino 13
delay(250);
digitalWrite(13, LOW);
Serial.print(freq);
Serial.print("\n");
return true;
}
return false;
}
void print_number(int row, int column) {
int number = 0;
// Mapeia linha/coluna para tecla DTMF
if (row == 0) {
if (column == 0) number = 1;
else if (column == 1) number = 2;
else if (column == 2) number = 3;
else if (column == 3) 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 if (column == 3) 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 if (column == 3) 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 if (column == 3) number = 13; // D
}
// Acende LED correspondente (pinos 2-11 para números 0-9)
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.print("\n");
delay(800);
// Apaga todos os LEDs
for (int i = 2; i <= 12; i++) digitalWrite(i, LOW);
}
void loop() {
int column = 0, row = 0;
int i = 0;
// Detecta tom de coluna (frequência alta)
while (1) {
if (detect_tone(x_frequencies[i])) {
column = i;
break;
}
i++;
if (i == 4) i = 0;
}
i = 0;
// Detecta tom de linha (frequência baixa)
while (1) {
if (detect_tone(y_frequencies[i])) {
row = i;
break;
}
i++;
if (i == 4) i = 0;
}
print_number(row, column);
}
Esquemático
O circuito utiliza 10 LEDs conectados dos pinos digitais 2 a 12, que acendem quando as teclas 0-9 são pressionadas. Um LED de detecção de pulso no pino 13 pisca brevemente quando um sinal é detectado. Os caracteres especiais (A, B, C, D, *, #) são exibidos via Serial Monitor.
A entrada de áudio (via conector P10/AUX) deve ser conectada ao pino analógico A0 com um capacitor de 1µF em série para filtrar componentes DC e baixas frequências.
Processo de manufatura
- Crie um Sistema Ambilight Impressionante para Monitor com Arduino
- Construa um Dispositivo de Levitação Ultrassônica com Arduino – Guia Passo a Passo
- SERENA: Sistema de Alarme Personalizado Arduino Mega 2560 com Touchscreen TFT LCD
- Construa um Voltímetro Inteligente com Arduino e Smartphone – Projeto DIY Fácil
- Monitor de Frequência Cardíaca IoT em Tempo Real com Arduino e MAX30100
- Comunicação em Código Morse com Módulo Laser – Projeto Arduino de Dois Lados
- Servidor Web Arduino Uno WiFi: Controle LED via Navegador
- Contador Inteligente de Vagas: Rastreamento de Veículos em Tempo Real com Arduino, Processing e PHP
- Automatize o Jogo do Dinossauro do Chrome com Arduino e LDR
- Python 3 para Arduino UNO: Controle de Comandos Fácil e Demo com LED