INHOUDSOPGAWE:
Video: DTMF -detektor: 4 stappe
2024 Outeur: John Day | [email protected]. Laas verander: 2024-01-30 07:26
Oorsig
Ek is geïnspireer om hierdie toestel te bou deur 'n tuisopdrag oor die digitale kursus van digitale seinverwerking. Dit is 'n DTMF -dekodeerder wat met Arduino UNO geïmplementeer word, en dit ontdek 'n syfer wat op die telefoonklavier in die klankmodus gedruk word deur die klank wat dit produseer.
Stap 1: Begrip van die algoritme
In DTMF is elke simbool gekodeer met twee frekwensies volgens die tabel op die prent.
Die toestel vang insette vanaf die mikrofoon op en bereken amplitudes van agt frekwensies. Twee frekwensies met 'n maksimum amplitude gee 'n ry en 'n kolom van die gekodeerde simbool.
Data -verkryging
Om spektrumanalise uit te voer, moet monsters teen 'n sekere voorspelbare frekwensie geneem word. Om dit te bereik, gebruik ek die vryloop-ADC-modus met maksimum akkuraatheid (prescaler 128), dit gee 'n monsternemingstempo van 9615Hz. Die onderstaande kode wys hoe u die ADC van Arduino kan opstel.
ongeldig initADC () {
// Init ADC; f = (16MHz/prescaler)/13 siklusse/omskakeling ADMUX = 0; // Kanaal sel, regs-adj, gebruik AREF-pen ADCSRA = _BV (ADEN) | // ADC aktiveer _BV (ADSC) | // ADC begin _BV (ADATE) | // Outomatiese sneller _BV (ADIE) | // Onderbreek aktiveer _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Hz ADCSRB = 0; // Vryloopmodus DIDR0 = _BV (0); // Skakel digitale invoer uit vir ADC -pen TIMSK0 = 0; // Timer0 af} En die interrupt -hanteerder lyk soos hierdie ISR (ADC_vect) {uint16_t sample = ADC; samples [samplePos ++] = sample - 400; as (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer vol, onderbreek af}}
Spektrum analise
Nadat ek monsters versamel het, bereken ek amplitudes van 8 frekwensies wat simbole kodeer. Ek hoef nie volledige FFT hiervoor uit te voer nie, so ek het die algoritme van Goertzel gebruik.
leegte goertzel (uint8_t *monsters, float *spektrum) {
dryf v_0, v_1, v_2; float re, im, amp; vir (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k]))); float s = pgm_read_float (& (sin_t [k]))); dryf a = 2. * c; v_0 = v_1 = v_2 = 0; vir (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (monsters ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektrum [k] = amp; }}
Stap 2: Die kode
Die foto hierbo toon die voorbeeld van kodering van syfer 3 waar die maksimum amplitude ooreenstem met die frekwensies 697Hz en 1477Hz.
Die volledige skets lyk soos volg
/** * Verbindings: * [Mic na Arduino] * - Uit -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - Arduino: AREF -> 3.3V * [Display to Arduino] * - Vcc - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 */ #include #include
#insluit
#definieer CS_PIN 9
#definieer N 256
#definieer IX_LEN 8 #definieer DREMPEL 20
LEDMatrixDriver lmd (1, CS_PIN);
uint8_t monsters [N];
vlugtige uint16_t samplePos = 0;
dryfspektrum [IX_LEN];
// Frekwensies [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]
// Bereken vir 9615Hz 256 monsters const float cos_t [IX_LEN] PROGMEEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.6343932841636456, 0.5365 const float sin_t [IX_LEN] PROGMEEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.8314696123025451, 0.88
typedef struct {
char syfer; uint8_t indeks; } syfer_t;
syfer_t opgespoor_syfer;
const char tabel [4] [4] PROGMEEM = {
{'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', ' C '}, {'*',' 0 ','#',' D '}};
const uint8_t char_indexes [4] [4] PROGMEEM = {
{1, 2, 3, 10}, {4, 5, 6, 11}, {7, 8, 9, 12}, {15, 0, 14, 13} };
greep lettertipe [16] [8] = {
{0x00, 0x38, 0x44, 0x4c, 0x54, 0x64, 0x44, 0x38}, // 0 {0x04, 0x0c, 0x14, 0x24, 0x04, 0x04, 0x04, 0x04}, // 1 {0x00, 0x30, 0x48, 0x0, 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} // *};
ongeldig initADC () {
// Init ADC; f = (16MHz/prescaler)/13 siklusse/omskakeling ADMUX = 0; // Kanaal sel, regs-adj, gebruik AREF-pen ADCSRA = _BV (ADEN) | // ADC aktiveer _BV (ADSC) | // ADC begin _BV (ADATE) | // Outomatiese sneller _BV (ADIE) | // Onderbreek aktiveer _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Hz ADCSRB = 0; // Vryloopmodus DIDR0 = _BV (0); // Skakel digitale invoer uit vir ADC -pen TIMSK0 = 0; // Timer0 af
leegte goertzel (uint8_t *monsters, float *spektrum) {
float v_0, v_1, v_2; float re, im, amp; vir (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k]))); float s = pgm_read_float (& (sin_t [k]))); dryf a = 2. * c; v_0 = v_1 = v_2 = 0; vir (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (monsters ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektrum [k] = amp; }}
float gemiddelde (float *a, uint16_t len) {
vlot resultaat =.0; vir (uint16_t i = 0; i <len; i ++) {resultaat+= a ; } opbrengs resultaat / len; }
int8_t get_single_index_above_threshold (float *a, uint16_t len, float drumpel) {
as (drempel <DREMPEL) {opgawe -1; } int8_t ix = -1; vir (uint16_t i = 0; i drempel) {if (ix == -1) {ix = i; } anders {opgawe -1; }}} terugkeer ix; }
leemte detect_digit (float *spektrum) {
float avg_row = gemiddelde (spektrum, 4); float avg_col = gemiddelde (& spektrum [4], 4); int8_t ry = get_single_index_above_threshold (spektrum, 4, avg_row); int8_t col = get_single_index_above_threshold (& spektrum [4], 4, avg_col); as (ry! = -1 && col! = -1 && avg_col> 200) {detect_digit.digit = pgm_read_byte (& (tabel [ry] [col])); detect_digit.index = pgm_read_byte (& (char_indexes [ry] [kol])); } anders {detect_digit.digit = 0; }}
void drawSprite (byte* sprite) {
// Die masker word gebruik om die kolombit uit die sprite ry byte masker te kry = B10000000; for (int iy = 0; iy <8; iy ++) {for (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & masker));
// skuif die masker met een pixel na regs
masker = masker >> 1; }
// stel kolommasker terug
masker = B10000000; }}
ongeldige opstelling () {
cli (); initADC (); sei ();
Serial.begin (115200);
lmd.setEnabled (waar); lmd.setIntensity (2); lmd.clear (); lmd.display ();
detect_digit.digit = 0;
}
ongetekende lang z = 0;
leemte -lus () {
terwyl (ADCSRA & _BV (ADIE)); // Wag totdat die klankmonster klaar is met goertzel (monsters, spektrum); detect_digit (spektrum);
as (detect_digit.digit! = 0) {
drawSprite (font [detect_digit.index]); lmd.display (); } if (z % 5 == 0) {for (int i = 0; i <IX_LEN; i ++) {Serial.print (spektrum ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) detect_digit.digit); } z ++;
samplePos = 0;
ADCSRA | = _BV (ADIE); // Hervat die steekproefonderbreking
}
ISR (ADC_vect) {
uint16_t monster = ADC;
monsters [samplePos ++] = monster - 400;
as (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer vol, onderbreek af}}
Stap 3: Skema's
Die volgende verbindings moet gemaak word:
Mikrofoon na Arduino
Uit -> A0
Vcc -> 3.3V Gnd -> Gnd
Dit is belangrik om AREF aan te sluit op 3.3V
Vertoon vir Arduino
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
Stap 4: Gevolgtrekking
Wat kan hier verbeter word? Ek gebruik N = 256 monsters met 'n snelheid van 9615Hz, wat 'n mate van spektrumlek het, as N = 205 en die snelheid 8000Hz is, val die gewenste frekwensies saam met die diskretiseringsrooster. Hiervoor moet ADC gebruik word in die timer -oorloopmodus.
Aanbeveel:
DTMF VIDEO STREAMING ROVER: 3 stappe
DTMF VIDEO STREAMING ROVER: hallo na my LINUX TERMINAL CONTROLLED ROVER en WIFI DTMF PC CONTROLLED ROBOT, dit is my derde robot. en soos die ander twee hier, het ek ook geen mikrobeheerder of programmering gebruik om dit eenvoudig en maklik te maak nie. dit stroom ook lewendige video via wifi
Hoe om 'n eenvoudige DTMF (toon) telefoonlyn -dekodeerder te maak: 3 stappe
Hoe om 'n eenvoudige DTMF (toon) telefoonlyn -dekodeerder te maak: Dit is 'n eenvoudige projek waarmee u DTMF -seine op basies enige telefoonlyn kan dekodeer. In hierdie handleiding gebruik ons die dekodeerder MT8870D. Ons gebruik 'n voorafgeboude toondekodeerder, want glo my, dit is 'n pyn aan die agterkant om dit te probeer doen met die
WIFI DTMF ROBOT: 5 stappe
WIFI DTMF ROBOT: hallo in hierdie tutoriaal, ek gaan jou wys hoe jy 'n rekenaarbeheerde rover kan maak sonder om 'n mikrobeheerder te gebruik; dit beteken dat daar in hierdie projek geen hoëvlakkode betrokke is nie; jy benodig net basiese kennis oor die maak van HTML -bladsye. kan vol kyk
Hoe om 'n mobiele beheerde robot te maak - Gebaseer op DTMF - Sonder mikrobeheerder en programmering - Beheer van oral in die wêreld - RoboGeeks: 15 stappe
Hoe om 'n mobiele beheerde robot te maak | Gebaseer op DTMF | Sonder mikrobeheerder en programmering | Beheer van oral in die wêreld | RoboGeeks: wil u 'n robot maak wat van oral in die wêreld beheer kan word, laat ons dit doen
DTMF en gebaargestuurde robotstoel: 7 stappe (met foto's)
DTMF en gebare -beheerde robotiese rolstoel: In hierdie wêreld is 'n aantal mense gestrem. Hulle lewe draai om wiele. Hierdie projek bied 'n benadering vir die beheer van rolstoelbewegings met behulp van handgebaarherkenning en DTMF van 'n slimfoon