Taula de continguts:
Vídeo: Detector DTMF: 4 passos
2024 Autora: John Day | [email protected]. Última modificació: 2024-01-30 08:14
Visió general
Em va inspirar construir aquest dispositiu amb una assignació a casa al curs en línia de processament de senyal digital. Es tracta d’un descodificador DTMF implementat amb Arduino UNO, que detecta un dígit premut en un teclat del telèfon en mode de to pel so que produeix.
Pas 1: entendre l'algorisme
En DTMF cada símbol es codifica amb dues freqüències segons la taula de la imatge.
El dispositiu capta l'entrada del micròfon i calcula amplituds de vuit freqüències. Dues freqüències amb amplituds màximes donen una fila i una columna del símbol codificat.
Adquisició de dades
Per realitzar anàlisis d'espectre, s'han de capturar mostres a una freqüència previsible determinada. Per aconseguir-ho, he utilitzat el mode ADC de funcionament lliure amb la màxima precisió (prescaler 128) que proporciona una freqüència de mostreig de 9615Hz. El codi següent mostra com configurar l’ADC d’Arduino.
void initADC () {
// Iniciar ADC; f = (16 MHz / prescaler) / 13 cicles / conversió ADMUX = 0; // Selecció de canal, ajustat a la dreta, utilitza el pin AREF ADCSRA = _BV (ADEN) | // ADC habilita _BV (ADSC) | // Inici ADC _BV (ADATE) | // Activador automàtic _BV (ADIE) | // Interrupt habilitar _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Mode de funcionament lliure DIDR0 = _BV (0); // Desactiveu l'entrada digital per al pin ADC TIMSK0 = 0; // Temporitzador0 desactivat} I el controlador d'interrupcions té aquest aspecte ISR (ADC_vect) {uint16_t sample = ADC; samples [samplePos ++] = sample - 400; if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer ple, interrupció desactivada}}
Anàlisi de l'espectre
Després de recollir mostres, calculo amplituds de 8 freqüències que codifiquen símbols. No necessito executar FFT complet per a això, així que he utilitzat l'algorisme de Goertzel.
voertz goertzel (mostres uint8_t *, espectre flotant *) {
flotador v_0, v_1, v_2; float re, im, amp; per a (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k])); float s = pgm_read_float (& (sin_t [k])); flotar a = 2. * c; v_0 = v_1 = v_2 = 0; per a (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (samples ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); espectre [k] = amplificador; }}
Pas 2: el codi
La imatge superior mostra l'exemple de codificació del dígit 3 on l'amplitud màxima correspon a les freqüències 697Hz i 1477Hz.
L’esbós complet té el següent aspecte
/ ** * Connexions: * [Mic a Arduino] * - Sortida -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - Arduino: AREF -> 3.3V * [Visualització a Arduino] * - Vcc - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 * / #include #include
#incloure
#defineix CS_PIN 9
#define N 256
#define IX_LEN 8 #define THRESHOLD 20
LEDMatrixDriver lmd (1, CS_PIN);
uint8_t mostres [N];
volàtil uint16_t samplePos = 0;
espectre flotant [IX_LEN];
// Freqüències [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]
// Calculat per a 9615Hz 256 mostres const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.6343932841636456, 0.5555, 0.5555; const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.83146961230252456, 0.88
typedef struct {
dígit de caràcter; índex uint8_t; } dígit_t;
dígit_t dígit_ detectat;
taula de const const [4] [4] PROGMEM = {
{'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', ' C '}, {' * ',' 0 ',' # ',' D '}};
const uint8_t char_indexes [4] [4] PROGMEM = {
{1, 2, 3, 10}, {4, 5, 6, 11}, {7, 8, 9, 12}, {15, 0, 14, 13} };
font de bytes [16] [8] = {
{0x00, 0x38, 0x44, 0x4c, 0x54, 0x64, 0x44, 0x38}, // 0 {0x04, 0x0c, 0x14, 0x24, 0x04, 0x04, 0x04, 0x04}, // 1 {0x00, 0x30, 0x48, 0x04, 0x04, 0x38, 0x40, 0x7c}, // 2 {0x00, 0x38, 0x04, 0x04, 0x18, 0x04, 0x44, 0x38}, // 3 {0x00, 0x04, 0x0c, 0x14, 0x24, 0x7e, 0x04, 0x0 }, // 4 {0x00, 0x7c, 0x40, 0x40, 0x78, 0x04, 0x04, 0x38}, // 5 {0x00, 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38}, // 6 {0x00, 0x7c, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10}, // 7 {0x00, 0x3c, 0x44, 0x44, 0x38, 0x44, 0x44, 0x78}, // 8 {0x00, 0x38, 0x44, 0x44, 0x3c, 0x04, 0x04, 0x78}, // 9 {0x00, 0x1c, 0x22, 0x42, 0x42, 0x7e, 0x42, 0x42}, // A {0x00, 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x7c}, / / B {0x00, 0x3c, 0x44, 0x40, 0x40, 0x40, 0x44, 0x7c}, // C {0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x44, 0x78}, // D {0x00, 0x0a, 0x7f, 0x14, 0x28, 0xfe, 0x50, 0x00}, // # {0x00, 0x10, 0x54, 0x38, 0x10, 0x38, 0x54, 0x10} // *};
void initADC () {
// Iniciar ADC; f = (16 MHz / prescaler) / 13 cicles / conversió ADMUX = 0; // Selecció de canal, ajustat a la dreta, utilitza el pin AREF ADCSRA = _BV (ADEN) | // ADC habilita _BV (ADSC) | // Inici ADC _BV (ADATE) | // Activador automàtic _BV (ADIE) | // Interrupt habilitar _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Mode de funcionament lliure DIDR0 = _BV (0); // Desactiveu l'entrada digital per al pin ADC TIMSK0 = 0; // Temporitzador0 desactivat}
voertz goertzel (mostres uint8_t *, espectre flotant *) {
flotador v_0, v_1, v_2; float re, im, amp; per a (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k])); float s = pgm_read_float (& (sin_t [k])); flotar a = 2. * c; v_0 = v_1 = v_2 = 0; per a (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (samples ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); espectre [k] = amplificador; }}
float avg (float * a, uint16_t len) {
resultat flotant =, 0; for (uint16_t i = 0; i <len; i ++) {result + = a ; } retornar el resultat / len; }
int8_t get_single_index_above_threshold (float * a, uint16_t len, llindar float) {
if (llindar <LIMI) {return -1; } int8_t ix = -1; per a (uint16_t i = 0; llindar i) {if (ix == -1) {ix = i; } else {return -1; }}} tornar ix; }
void detect_digit (float * spectre) {
float avg_row = avg (espectre, 4); float avg_col = avg (& spectre [4], 4); int8_t fila = get_single_index_above_threshold (espectre, 4, avg_row); int8_t col = get_single_index_above_threshold (& spectre [4], 4, avg_col); if (fila! = -1 && col! = -1 && avg_col> 200) {digit_digit.digit = pgm_read_byte (& (taula [fila] [col])); digital_digit.index = pgm_read_byte (& (char_indexes [fila] [col])); } else {detectat_digit.digit = 0; }}
void drawSprite (byte * sprite) {
// La màscara s’utilitza per obtenir el bit de columna de la màscara de bytes de fila sprite = B10000000; for (int iy = 0; iy <8; iy ++) {for (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & mask));
// canvieu la màscara per un píxel cap a la dreta
màscara = màscara >> 1; }
// restableix la màscara de columna
màscara = B10000000; }}
configuració nul·la () {
cli (); initADC (); sei ();
Serial.begin (115200);
lmd.setEnabled (cert); lmd.setIntensity (2); lmd.clear (); lmd.display ();
digital_digit.digit = 0;
}
llarg sense signe z = 0;
bucle buit () {
mentre que (ADCSRA & _BV (ADIE)); // Espereu que el mostreig d’àudio acabi el goertzel (mostres, espectre); detect_digit (espectre);
if (digital_digit.digit! = 0) {
drawSprite (font [detectat_digit.index]); lmd.display (); } if (z% 5 == 0) {for (int i = 0; i <IX_LEN; i ++) {Serial.print (espectre ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) digital_digit.digit); } z ++;
samplePos = 0;
ADCSRA | = _BV (ADIE); // Reprèn la interrupció de mostreig
}
ISR (ADC_vect) {
uint16_t sample = ADC;
samples [samplePos ++] = sample - 400;
if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer ple, interrupció desactivada}}
Pas 3: Esquemes
Cal establir les connexions següents:
Micròfon a Arduino
Fora -> A0
Vcc -> 3,3 V Gnd -> Gnd
És important connectar AREF a 3,3V
Mostra a Arduino
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
Pas 4: Conclusió
Què es podria millorar aquí? He utilitzat N = 256 mostres a una velocitat de 9615Hz, que té alguna fuita d’espectre, si N = 205 i la velocitat és de 8000Hz, les freqüències desitjades coincideixen amb la graella de discretització. Per a això, s'ha d'utilitzar ADC en mode de desbordament del temporitzador.
Recomanat:
DTMF VIDEO STREAMING ROVER: 3 passos
DTMF VIDEO STREAMING ROVER: hola després del meu LINUX TERMINAL CONTROLLED ROVER i WIFI DTMF PC CONTROLLED ROBOT aquest és el meu tercer robot. i com altres dos aquí, tampoc he utilitzat cap microcontrolador ni programació perquè sigui senzill i fàcil de fer. També emet vídeo en directe per wifi
Com fer un descodificador de línia telefònica DTMF (to) simple: 3 passos
Com fer un descodificador de línia telefònica DTMF simple (de to): es tracta d’un projecte senzill que us permet descodificar senyals DTMF bàsicament en qualsevol línia telefònica. En aquest tutorial, fem servir el descodificador MT8870D. Estem utilitzant un descodificador de to preconstruït perquè, creieu-me, és un dolor a la part posterior provar de fer-ho amb el
ROBOT WIFI DTMF: 5 passos
WIFI DTMF ROBOT: hola en aquest tutorial us mostraré com podeu fer un rover controlat per PC sense fer servir micro controlador, això significa que en aquest projecte no hi ha cap codi d’alt nivell que necessiteu només coneixements bàsics sobre la creació de pàgines html. es pot veure complet
Com fer un robot controlat per mòbil Basat en DTMF - Sense microcontrolador i programació - Control des de qualsevol lloc del món - RoboGeeks: 15 passos
Com fer un robot controlat per mòbil Basat en DTMF | Sense microcontrolador i programació | Control des de qualsevol lloc del món | RoboGeeks: Voleu fabricar un robot que es pugui controlar des de qualsevol part del món, Lets do It
Detector de fum IOT: actualitzeu el detector de fum existent amb IOT: 6 passos (amb imatges)
Detector de fum IOT: actualitzeu el detector de fum existent amb IOT: Llista de col·laboradors, Inventor: Tan Siew Chin, Tan Yit Peng, Tan Wee Heng Supervisor: Dr. Chia Kim Seng Departament d'Enginyeria Mecatrònica i Robòtica, Facultat d'Enginyeria Elèctrica i Electrònica, Universiti Tun Hussein Onn Malaysia.Distribut