Sisukord:
Video: DTMF -detektor: 4 sammu
2024 Autor: John Day | [email protected]. Viimati modifitseeritud: 2024-01-30 08:48
Ülevaade
Mind inspireeris selle seadme loomine digitaalse signaalitöötluse veebikursuse kodusest ülesandest. See on DTMF -dekooder, mis on rakendatud koos Arduino UNO -ga, tuvastab helitugevuse režiimis telefoni klaviatuuril vajutatud numbri.
Samm: mõistke algoritmi
DTMF -is on iga sümbol kodeeritud kahe sagedusega vastavalt pildil olevale tabelile.
Seade salvestab mikrofonist sisendi ja arvutab kaheksa sageduse amplituudid. Kaks maksimaalse amplituudiga sagedust annavad kodeeritud sümboli rea ja veeru.
Andmete kogumine
Spektrianalüüsi tegemiseks tuleks proove koguda teatud prognoositava sagedusega. Selle saavutamiseks kasutasin maksimaalse täpsusega vabalt käivitatavat ADC-režiimi (eelskaala 128), mis annab diskreetimissageduse 9615 Hz. Allolev kood näitab, kuidas konfigureerida Arduino ADC.
tühine initADC () {
// Init ADC; f = (16MHz/prescaler)/13 tsüklit/teisendus ADMUX = 0; // Kanal sel, parem-adj, kasutage AREF-i tihvti ADCSRA = _BV (ADEN) | // ADC lubamine _BV (ADSC) | // ADC algus _BV (ADATE) | // Automaatne päästik _BV (ADIE) | // Katkestamise lubamine _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Vabakäigu režiim DIDR0 = _BV (0); // Lülita ADC pin pinge sisend välja TIMSK0 = 0; // Taimer0 väljas} Ja katkestuste käitleja näeb välja selline ISR (ADC_vect) {uint16_t sample = ADC; sample [samplePos ++] = sample - 400; if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Puhver täis, katkestus välja}}
Spektri analüüs
Pärast proovide kogumist arvutan sümboleid kodeeriva 8 sageduse amplituudid. Selleks ei pea ma täielikku FFT -d käivitama, seega kasutasin Goertzeli algoritmi.
tühine goertzel (uint8_t *proovid, ujuk *spekter) {
ujuk v_0, v_1, v_2; float re, im, amp; jaoks (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k]))); float s = pgm_read_float (& (sin_t [k]))); ujuk a = 2. * c; v_0 = v_1 = v_2 = 0; jaoks (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (hõljuk) (proovid ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spekter [k] = amp; }}
2. samm: kood
Ülaloleval pildil on näide numbri 3 kodeerimisest, kus maksimaalne amplituud vastab sagedustele 697Hz ja 1477Hz.
Kogu eskiis näeb välja järgmine
/** * Ühendused: * [Mic to Arduino] * - Out -> 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
#kaasake
#define CS_PIN 9
#define N 256
#define IX_LEN 8 #define THRESHOLD 20
LEDMatrixDriver lmd (1, CS_PIN);
uint8_t proovid [N];
lenduv uint16_t samplePos = 0;
ujuv spekter [IX_LEN];
// Sagedused [697,0, 770,0, 852,0, 941,0, 1209,0, 1336,0, 1477,0, 1633,0]
// Arvutatud 9615 Hz 256 proovi jaoks Const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.634393284163645619566056 const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.8314696123025456 0.48
typedef structure {
sümbol; indeks uint8_t; } number_t;
digit_t tuvastatud_digit;
const char tabel [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} };
baitide font [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, 0x04 }, // 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} // *};
tühine initADC () {
// Init ADC; f = (16MHz/prescaler)/13 tsüklit/teisendus ADMUX = 0; // Kanal sel, parem-adj, kasutage AREF-i tihvti ADCSRA = _BV (ADEN) | // ADC lubamine _BV (ADSC) | // ADC algus _BV (ADATE) | // Automaatne päästik _BV (ADIE) | // Katkestamise lubamine _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Vabakäigu režiim DIDR0 = _BV (0); // Lülita ADC pin pinge sisend välja TIMSK0 = 0; // Taimer0 välja lülitatud}
tühine goertzel (uint8_t *proovid, ujuk *spekter) {
ujuk v_0, v_1, v_2; float re, im, amp; jaoks (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k]))); float s = pgm_read_float (& (sin_t [k]))); ujuk a = 2. * c; v_0 = v_1 = v_2 = 0; jaoks (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (hõljuk) (proovid ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spekter [k] = amp; }}
float avg (float *a, uint16_t len) {
ujukitulemus =.0; jaoks (uint16_t i = 0; i <len; i ++) {tulemus+= a ; } tagastamise tulemus / len; }
int8_t get_single_index_above_threshold (float *a, uint16_t len, float künnis) {
if (lävi <THRESHOLD) {return -1; } int8_t ix = -1; jaoks (uint16_t i = 0; i lävi) {if (ix == -1) {ix = i; } muu {tagastamine -1; }}} return ix; }
tühine detekteerimisnumber (ujuk *spekter) {
ujuk avg_row = keskm (spekter, 4); float avg_col = keskm. (& spekter [4], 4); int8_t rida = get_single_index_above_threshold (spekter, 4, keskm. rida); int8_t col = get_single_index_above_threshold (& spekter [4], 4, keskm.) if (rida! = -1 && col! = -1 && avg_col> 200) {tuvastatud_digit.digit = pgm_read_byte (& (tabel [rida] [col])); tuvastatud_dig.index = pgm_read_byte (& (char_indexes [rida] [col])); } muu {tuvastatud_dig.digit = 0; }}
void drawSprite (bait* sprite) {
// Maski kasutatakse veerbiti saamiseks sprite rea baidimaskilt = B10000000; jaoks (int iy = 0; iy <8; iy ++) {jaoks (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & mask));
// nihutage maski ühe piksli võrra paremale
mask = mask >> 1; }
// veergumaski lähtestamine
mask = B10000000; }}
tühine seadistus () {
cli (); initADC (); sei ();
Seriaalne algus (115200);
lmd.setEnabled (tõene); lmd.setIntensity (2); lmd.clear (); lmd.display ();
tuvastatud_digit.digit = 0;
}
allkirjata pikk z = 0;
void loop () {
samas (ADCSRA & _BV (ADIE)); // Oodake, kuni heliproovide võtmine goertzel lõpetab (proovid, spekter); detect_digit (spekter);
kui (tuvastatud_dig.digit! = 0) {
drawSprite (font [tuvastatud_dig.index]); lmd.display (); } kui (z % 5 == 0) {jaoks (int i = 0; i <IX_LEN; i ++) {jadatrükk (spekter ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) tuvastatud_digit.digit); } z ++;
samplePos = 0;
ADCSRA | = _BV (ADIE); // Proovivõtmise katkestamise jätkamine
}
ISR (ADC_vect) {
uint16_t proov = ADC;
proovid [samplePos ++] = proov - 400;
if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Puhver täis, katkestus välja}}
3. samm: skeemid
Tuleb teha järgmised ühendused:
Mikrofon Arduinole
Väljas -> A0
Vcc -> 3.3V Gnd -> Gnd
Oluline on ühendada AREF 3.3V -ga
Kuva Arduinole
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
4. samm: järeldus
Mida saaks siin parandada? Kasutasin N = 256 proovi sagedusel 9615Hz, millel on mõningane spektri leke, kui N = 205 ja sagedus on 8000Hz, langevad soovitud sagedused kokku diskreetimisvõrguga. Selleks tuleks ADC -d kasutada taimeri ülevoolu režiimis.
Soovitan:
DTMF VIDEO STREAMING ROVER: 3 sammu
DTMF VIDEO STREAMING ROVER: tere pärast minu LINUX TERMINAL JUHTITAVAT ROVERIT ja WIFI DTMF PC JUHTITUD ROBOTI, see on minu kolmas robot. ja nagu teised kaks siin, ei kasutanud ma ka ühtegi mikrokontrollerit ega programmeerimist, et seda oleks lihtne ja lihtne teha. see voogesitab ka otsevideot WiFi kaudu
Lihtsa DTMF (toon) telefoniliini dekoodri tegemine: 3 sammu
Lihtsa DTMF (toon) telefoniliini dekoodri tegemine: see on lihtne projekt, mis võimaldab dekodeerida DTMF -signaale põhimõtteliselt igal telefoniliinil. Selles õpetuses kasutame dekoodrit MT8870D. Me kasutame eellahitatud toonide dekoodrit, sest uskuge mind, tagantpoolt on valus proovida seda teha
WIFI DTMF ROBOT: 5 sammu
WIFI DTMF ROBOT: Tere selles õpetuses, ma näitan teile, kuidas saate arvutiga juhitavat roverit teha ilma mikrokontrollerit kasutamata, see tähendab, et selles projektis pole kõrgetasemelist koodi vaja, vajate lihtsalt põhiteadmisi html -lehe tegemise kohta. saab täis vaadata
Kuidas teha mobiiliga juhitavat robotit DTMF -põhine - Ilma mikrokontrollerita ja programmeerimiseta - Juhtimine kõikjal maailmas - RoboGeeks: 15 sammu
Kuidas teha mobiiliga juhitavat robotit DTMF -põhine | Ilma mikrokontrollerita ja programmeerimiseta | Juhtimine kõikjal maailmas | RoboGeeks: Tahad teha roboti, mida saab juhtida kõikjalt maailmast, teeme ära
DTMF ja žestidega juhitav robootiline ratastool: 7 sammu (piltidega)
DTMF ja žestidega juhitav robootiline ratastool: selles maailmas on paljud inimesed puudega. Nende elu keerleb rataste ümber. See projekt tutvustab lähenemist ratastooli liikumise juhtimiseks, kasutades nutitelefoni käeliigutuvastust ja DTMF -i