Mundarija:

DTMF detektori: 4 qadam
DTMF detektori: 4 qadam

Video: DTMF detektori: 4 qadam

Video: DTMF detektori: 4 qadam
Video: 😱Хакерская SDR Прослушка На Xiaomi 🔥 2024, Noyabr
Anonim
Image
Image

Sharh

Menga ushbu qurilmani uydan raqamli signallarni qayta ishlash bo'yicha onlayn kurs bo'yicha topshiriq ilhomlantirdi. Bu Arduino UNO yordamida amalga oshirilgan DTMF dekoderi, u telefon klaviaturasida ohang rejimida bosilgan raqamni u chiqaradigan tovush bilan aniqlaydi.

1 -qadam: Algoritmni tushunish

Kodeks
Kodeks

DTMFda har bir belgi rasmdagi jadvalga muvofiq ikkita chastota bilan kodlangan.

Qurilma mikrofondan kirishni yozib oladi va sakkiz chastota amplitudasini hisoblab chiqadi. Maksimal amplitudali ikkita chastota kodlangan belgining qatorini va ustunini beradi.

Ma'lumot olish

Spektrni tahlil qilish uchun namunalarni ma'lum bir chastotada olish kerak. Bunga erishish uchun men ADC rejimini maksimal aniqlikda ishlatardim (prescaler 128), bu 9615 Gts namuna olish tezligini beradi. Quyidagi kod Arduino ADC -ni qanday sozlashni ko'rsatadi.

bekor ADAD () {

// ADCni ishga tushirish; f = (16 MGts/oldindan hisoblagich)/13 tsikl/konvertatsiya ADMUX = 0; // Channel sel, right-adj, AREF pin ADCSRA = _BV (ADEN) dan foydalaning | // ADC _BV (ADSC) ni yoqish | // ADC boshlanishi _BV (ADATE) | // Avtomatik ishga tushirish _BV (ADIE) | // Tanaffusni yoqish _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Erkin ishlash rejimi DIDR0 = _BV (0); // ADC pin uchun raqamli kirishni o'chirish TIMSK0 = 0; // Taymer0 o'chirilgan} Va uzilish ishlovchisi ISR (ADC_vect) ga o'xshaydi {uint16_t sample = ADC; sample [samplePos ++] = namuna - 400; agar (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Bufer to'lgan, uzilish o'chirilgan}}

Spektrni tahlil qilish

Namunalarni yig'ib bo'lgach, men 8 ta chastotali kodlash belgilarining amplitudalarini hisoblayman. Buning uchun menga to'liq FFT ishga tushirish shart emas, shuning uchun men Goertzel algoritmidan foydalandim.

bo'sh gersel (uint8_t *namunalari, float *spektri) {

suzuvchi v_0, v_1, v_2; float re, im, amp; uchun (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k])); float s = pgm_read_float (& (sin_t [k])); float a = 2. * c; v_0 = v_1 = v_2 = 0; uchun (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (namunalar ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektr [k] = amp; }}

2 -qadam: Kod

Yuqoridagi rasmda maksimal amplitudasi 697 Gts va 1477 Gts chastotalarga mos keladigan 3 -raqamli kodlash misoli ko'rsatilgan.

To'liq eskiz quyidagicha ko'rinadi

/** * Ulanishlar: * [Micro to Arduino] * - Chiqish -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - Arduino: AREF -> 3.3V * [Arduino displeyi] * - Vcc - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 */ #include #include

#qo'shing

#CS_PIN 9 ni aniqlang

#aniqlang N 256

#IX_LEN 8 ni belgilang #TAHRISI 20 ni aniqlang

LEDMatrixDriver lmd (1, CS_PIN);

uint8_t namunalari [N];

uchuvchi uint16_t samplePos = 0;

suzuvchi spektr [IX_LEN];

// Chastotalar [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]

// 9615 Gts 256 namunali const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.68954054473706396666666666666666666666666666686, 0,8639 const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.7730104533627369, 0.7730104533627369

typedef tuzilishi {

char raqami; uint8_t indeksi; } raqam_t;

raqam_t aniqlangan_ raqam;

const char jadvali [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} };

bayt shrift [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} // *};

bekor initADC () {

// ADCni ishga tushirish; f = (16 MGts/oldindan hisoblagich)/13 tsikl/konvertatsiya ADMUX = 0; // Channel sel, right-adj, AREF pin ADCSRA = _BV (ADEN) dan foydalaning | // ADC _BV (ADSC) ni yoqish | // ADC boshlanishi _BV (ADATE) | // Avtomatik ishga tushirish _BV (ADIE) | // Tanaffusni yoqish _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Erkin ishlash rejimi DIDR0 = _BV (0); // ADC pin uchun raqamli kirishni o'chirish TIMSK0 = 0; // Taymer 0 o'chirilgan}

bo'sh gersel (uint8_t *namunalari, float *spektri) {

suzuvchi v_0, v_1, v_2; float re, im, amp; uchun (uint8_t k = 0; k <IX_LEN; k ++) {float c = pgm_read_float (& (cos_t [k])); float s = pgm_read_float (& (sin_t [k])); float a = 2. * c; v_0 = v_1 = v_2 = 0; uchun (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (namunalar ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektr [k] = amp; }}

suzuvchi o'rtacha (float *a, uint16_t len) {

float natijasi =.0; uchun (uint16_t i = 0; i <len; i ++) {natija+= a ; } natijani qaytarish / len; }

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

if (pol <THRESHOLD) {qaytish -1; } int8_t ix = -1; uchun (uint16_t i = 0; i ostona) {if (ix == -1) {ix = i; } boshqa {qaytish -1; }}} qaytarish ix; }

void detect_digit (float *spektr) {

suzuvchi avg_row = o'rtacha (spektr, 4); suzuvchi avg_col = avg (& spektr [4], 4); int8_t qator = get_single_index_above_threshold (spektr, 4, avg_row); int8_t col = get_single_index_above_threshold (& spektr [4], 4, avg_col); agar (qator! = -1 && col! = -1 && avg_col> 200) {aniqlangan_digit.digit = pgm_read_byte (& (jadval [qator] [col])); aniqlangan_digit.index = pgm_read_byte (& (char_indexes [qator] [col])); } boshqa {aniqlangan_digit.digit = 0; }}

void drawSprite (bayt* sprite) {

// Niqob sprite qator bayt niqobidan ustun bitini olish uchun ishlatiladi = B10000000; for (int iy = 0; iy <8; iy ++) {for (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & mask));

// niqobni bir pikselga o'ngga siljiting

niqob = niqob >> 1; }

// ustun niqobini tiklash

niqob = B10000000; }}

bo'sh o'rnatish () {

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

Serial.begin (115200);

lmd.setEnabled (haqiqiy); lmd.setIntensity (2); lmd.clear (); lmd.display ();

aniqlangan_digit.digit = 0;

}

belgisiz uzun z = 0;

void loop () {

esa (ADCSRA & _BV (ADIE)); // Ovozli namuna olish tugaguncha kuting (namunalar, spektr); aniqlash_digit (spektr);

agar (aniqlangan_digit.digit! = 0) {

drawSprite (shrift [detect_digit.index]); lmd.display (); } if (z % 5 == 0) {for (int i = 0; i <IX_LEN; i ++) {Serial.print (spektr ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) detect_digit.digit); } z ++;

namunaPos = 0;

ADCSRA | = _BV (ADIE); // Namuna olishni to'xtatishni davom ettiring

}

ISR (ADC_vect) {

uint16_t namuna = ADC;

namunalar [samplePos ++] = namuna - 400;

agar (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Bufer to'ldirildi, uzilish o'chirildi}}

3 -qadam: sxemalar

Sxemalar
Sxemalar

Quyidagi aloqalarni o'rnatish kerak:

Arduino uchun mikrofon

Chiqish -> A0

Vcc -> 3.3V Gnd -> Gnd

AREF -ni 3.3V ga ulash muhim

Arduino -da ko'rsatish

Vcc -> 5V

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

4 -qadam: Xulosa

Bu erda nimani yaxshilash mumkin? Men N = 256 namunalarini 9615 Gts tezlikda ishlatardim, ularda spektr oqimi bor edi, agar N = 205 va tezligi 8000 Gts bo'lsa, kerakli chastotalar diskretizatsiya tarmog'iga to'g'ri keladi. Buning uchun ADC taymerni to'ldirish rejimida ishlatilishi kerak.

Tavsiya: