Բովանդակություն:

DTMF դետեկտոր ՝ 4 քայլ
DTMF դետեկտոր ՝ 4 քայլ

Video: DTMF դետեկտոր ՝ 4 քայլ

Video: DTMF դետեկտոր ՝ 4 քայլ
Video: GSM/GPRS-модуль SIM800L (#4) - все о DTMF: парсинг, управление, безопасность 2024, Հուլիսի
Anonim
Image
Image

Ակնարկ

Այս սարքը ստեղծելու համար ինձ ոգեշնչեց թվային ազդանշանի մշակման առցանց դասընթացի տնային առաջադրանքը: Սա DTMF- ի ապակոդավորիչ է, որն իրականացվել է Arduino UNO- ի հետ: Այն ձայնային ստեղնաշարի վրա սեղմված թվանշանը հայտնաբերում է հնչերանգի ռեժիմում `դրա արտադրած ձայնով:

Քայլ 1. Ալգորիթմի իմացություն

Օրենսգիրքը
Օրենսգիրքը

DTMF- ում յուրաքանչյուր խորհրդանիշ կոդավորված է երկու հաճախականությամբ `ըստ նկարի աղյուսակի:

Սարքը գրավում է խոսափողի մուտքը և հաշվարկում ութ հաճախականությունների ամպլիտուդներ: Առավելագույն ամպլիտուդներով երկու հաճախականություններ տալիս են կոդավորված խորհրդանիշի տող և սյունակ:

Տվյալների ձեռքբերում

Սպեկտրի վերլուծություն կատարելու համար նմուշները պետք է վերցվեն որոշակի կանխատեսելի հաճախականությամբ: Դրան հասնելու համար ես օգտագործեցի անվճար գործարկվող ADC ռեժիմը առավելագույն ճշգրտությամբ (նախալեզվիչ 128), որը տալիս է նմուշառման արագություն 9615 Հց: Ստորև բերված ծածկագիրը ցույց է տալիս, թե ինչպես կարգավորել Arduino- ի ADC- ն:

void initADC () {

// Init ADC; f = (16 ՄՀց/նախալեզվիչ)/13 ցիկլ/փոխակերպում ADMUX = 0; // Channel sel, right-adj, use AREF pin ADCSRA = _BV (ADEN) | // ADC միացնել _BV (ADSC) | // ADC սկիզբ _BV (ADATE) | // Ավտոմատ ձգան _BV (ADIE) | // Ընդհատել միացնել _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Հց ADCSRB = 0; // Անվճար գործարկման ռեժիմ DIDR0 = _BV (0); // Անջատել թվային մուտքագրումը ADC կապի համար TIMSK0 = 0; // erամաչափը անջատված է} Եվ ընդհատումների կարգավորիչը նման է այս ISR (ADC_vect) {uint16_t sample = ADC; sample [samplePos ++] = sample - 400; եթե (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Բուֆերն ամբողջությամբ, ընդհատումը անջատված է}}

Սպեկտրի վերլուծություն

Նմուշներ հավաքելուց հետո ես հաշվարկում եմ 8 հաճախականությունների ամպլիտուդներ, որոնք ծածկագրում են խորհրդանիշներ: Ես դրա համար կարիք չունեմ լրիվ FFT գործարկելու, այնպես որ ես օգտագործեցի Գոերտցելի ալգորիթմը:

void goertzel (uint8_t *նմուշներ, float *սպեկտր) {

բոց v_0, v_1, v_2; float re, im, amp; համար (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k]))); float s = pgm_read_float (& (sin_t [k])); բոց a = 2. * c; v_0 = v_1 = v_2 = 0; համար (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (բոց) (նմուշներ ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); սպեկտրը [k] = ուժեղացուցիչ; }}

Քայլ 2: Կոդ

Վերը նկարը ցույց է տալիս 3 -րդ թվանշանի կոդավորման օրինակը, որտեղ առավելագույն ամպլիտուդը համապատասխանում է 697 Հց և 1477 Հց հաճախականություններին:

Ամբողջական ուրվագիծը հետևյալն է

/** * Միացումներ. * [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 */ #ներառել #ներառել

#ներառում

#սահմանել CS_PIN 9

#սահմանի N 256

#սահմանել IX_LEN 8 #սահմանել THRESHOLD 20

LEDMatrixDriver lmd (1, CS_PIN);

uint8_t նմուշներ [N];

անկայուն uint16_t samplePos = 0;

բոց սպեկտր [IX_LEN];

// Հաճախականություններ [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]

// Հաշվարկված 9615 Հց 256 նմուշների համար const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.6343963985, 0.634396393, 0.634396393, 0.63439.36393, 0.63439. const float sin_t [IX_LEN] GՐԱԳԻՐ = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.831914696, 0.831914696, 0.831914696, 0.831914696, 0.831914696, 0.831914696, 0.831914696, 0.831914696, 0.831914696, 0.831912696, 0.83191469

typedef struct {

տառանշան; uint8_t ինդեքս; } թվանշան_թ;

թվանշան_ հայտնաբերված_ թվանշան;

const char սեղան [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} };

բայթ տառատեսակ [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, 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} // *};

void initADC () {

// Init ADC; f = (16 ՄՀց/նախալեզվիչ)/13 ցիկլ/փոխակերպում ADMUX = 0; // Channel sel, right-adj, use AREF pin ADCSRA = _BV (ADEN) | // ADC միացնել _BV (ADSC) | // ADC սկիզբ _BV (ADATE) | // Ավտոմատ ձգան _BV (ADIE) | // Ընդհատել միացնել _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Հց ADCSRB = 0; // Անվճար գործարկման ռեժիմ DIDR0 = _BV (0); // Անջատել թվային մուտքագրումը ADC կապի համար TIMSK0 = 0; // erամաչափը անջատված է}

void goertzel (uint8_t *նմուշներ, float *սպեկտր) {

բոց v_0, v_1, v_2; float re, im, amp; համար (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k]))); float s = pgm_read_float (& (sin_t [k])); բոց a = 2. * c; v_0 = v_1 = v_2 = 0; համար (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (բոց) (նմուշներ ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); սպեկտրը [k] = ուժեղացուցիչ; }}

բոց միջին (float *a, uint16_t len) {

բոց արդյունքը =.0; համար (uint16_t i = 0; i <len; i ++) {result+= a ; } վերադարձի արդյունք / լեն; }

int8_t get_single_index_above_threshold (float *a, uint16_t len, float threshold) {

եթե (շեմը <THRESHOLD) {վերադարձ -1; } int8_t ix = -1; համար (uint16_t i = 0; i շեմ) {if (ix == -1) {ix = i; } else {վերադարձ -1; }}} վերադարձ ix; }

դատարկ dete_digit (float *spectrum) {

բոց avg_row = միջին (սպեկտր, 4); բոց avg_col = միջին (& սպեկտր [4], 4); int8_t տող = get_single_index_above_threshold (սպեկտր, 4, avg_row); int8_t col = get_single_index_above_threshold (& spectrum [4], 4, avg_col); if (տող! = -1 && col! = -1 && avg_col> 200) {dete_digit.digit = pgm_read_byte (& (աղյուսակ [տող] [col])); dete_digit.index = pgm_read_byte (& (char_indexes [տող] [col])); } else {dete_digit.digit = 0; }}

void drawSprite (բայթ* sprite) {

// Դիմակը օգտագործվում է սփրեյթ շարքի բայթ դիմակի սյունակի բիթը ստանալու համար = B10000000; համար (int iy = 0; iy <8; iy ++) {for (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & դիմակ));

// դիմակը մեկ պիքսելով տեղափոխել աջ

դիմակ = դիմակ >> 1; }

// վերականգնել սյունակի դիմակը

դիմակ = B10000000; }}

void setup () {

cli (); initADC (); sei ();

Serial.begin (115200);

lmd.setEnabled (ճշմարիտ); lmd.setIntensity (2); lmd. հստակ (); lmd.display ();

dete_digit.digit = 0;

}

անստորագիր երկար z = 0;

դատարկ շրջան () {

իսկ (ADCSRA & _BV (ADIE)); // Սպասեք աուդիո նմուշառման ավարտին goertzel (նմուշներ, սպեկտր); dete_digit (սպեկտր);

եթե (dete_digit.digit! = 0) {

drawSprite (տառատեսակ [dete_digit.index]); lmd.display (); } if (z % 5 == 0) {for (int i = 0; i <IX_LEN; i ++) {Serial.print (սպեկտրը ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) dete_digit.digit); } z ++;

samplePos = 0;

ADCSRA | = _BV (ADIE); // Վերսկսել ընտրանքի ընդհատումը

}

ISR (ADC_vect) {

uint16_t նմուշ = ADC;

նմուշներ [samplePos ++] = նմուշ - 400;

եթե (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Բուֆերն ամբողջությամբ, ընդհատումը անջատված է}}

Քայլ 3: Սխեմաներ

Սխեմաներ
Սխեմաներ

Հետևյալ կապերը պետք է կատարվեն.

Խոսափողը Arduino- ին

Դուրս -> A0

Vcc -> 3.3V Gnd -> Gnd

Կարևոր է AREF- ը միացնել 3.3 Վ -ին:

Displayուցադրել Arduino- ին

Vcc -> 5V

Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9

Քայլ 4: Եզրակացություն

Ի՞նչը կարելի է բարելավել այստեղ: Ես օգտագործել եմ N = 256 նմուշ 9615 Հց արագությամբ, որն ունի որոշակի սպեկտրի արտահոսք, եթե N = 205 և արագությունը 8000 Հց է, ապա ցանկալի հաճախականությունները համընկնում են դիսկրետացիոն ցանցի հետ: Դրա համար ADC- ն պետք է օգտագործվի ժմչփի արտահոսքի ռեժիմում:

Խորհուրդ ենք տալիս: