فهرست مطالب:

آشکارساز DTMF: 4 مرحله
آشکارساز DTMF: 4 مرحله

تصویری: آشکارساز DTMF: 4 مرحله

تصویری: آشکارساز DTMF: 4 مرحله
تصویری: آموزش ساخت مدار آشکارساز امواج موبایل (حسگر امواج تلفن همراه) 2024, جولای
Anonim
Image
Image

بررسی اجمالی

من برای ساخت این دستگاه از یک تکلیف خانگی در دوره آنلاین پردازش سیگنال دیجیتال الهام گرفتم. این یک رمزگشای DTMF است که با Arduino UNO پیاده سازی شده است ، با صدایی که تولید می کند ، یک رقم فشرده شده روی صفحه کلید تلفن را در حالت تن تشخیص می دهد.

مرحله 1: درک الگوریتم

کد
کد

در DTMF هر نماد با دو فرکانس مطابق جدول روی تصویر کدگذاری می شود.

دستگاه ورودی میکروفون را گرفته و دامنه هشت فرکانس را محاسبه می کند. دو فرکانس با حداکثر دامنه یک ردیف و یک ستون از نماد رمزگذاری شده می دهد.

اکتساب داده ها

به منظور انجام تجزیه و تحلیل طیف نمونه ها باید با فرکانس قابل پیش بینی خاصی گرفته شوند. برای دستیابی به این هدف ، من از حالت ADC رایگان با حداکثر دقت (پیش شماره گیری 128) استفاده کردم که میزان نمونه برداری را 9615 هرتز می دهد. کد زیر نحوه پیکربندی ADC Arduino را نشان می دهد.

void initADC () {

// Init ADC؛ f = (16 مگاهرتز/پیش فروشنده)/13 چرخه/تبدیل ADMUX = 0 ؛ // کانال فروش ، right-adj ، از پین AREF ADCSRA = _BV (ADEN) | استفاده کنید // ADC را فعال کنید _BV (ADSC) | // ADC start _BV (ADATE) | // ماشه خودکار _BV (ADIE) | // وقفه فعال _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0) ؛ // 128: 1 /13 = 9615 هرتز ADCSRB = 0 ؛ // حالت آزاد اجرا DIDR0 = _BV (0)؛ // خاموش کردن ورودی دیجیتال برای پین ADC TIMSK0 = 0؛ // تایمر 0 خاموش} و کنترل کننده وقفه شبیه این ISR (ADC_vect) است {uint16_t sample = ADC؛ نمونه [samplePos ++] = نمونه - 400 ؛ if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE) ؛ // بافر کامل ، وقفه خاموش}}

تجزیه و تحلیل طیف

پس از جمع آوری نمونه ها ، دامنه 8 فرکانس رمزگذاری نمادها را محاسبه می کنم. برای این کار نیازی به اجرای کامل FFT ندارم ، بنابراین از الگوریتم Goertzel استفاده کردم.

void goertzel (uint8_t *نمونه ، شناور *طیف) {

شناور 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 * [نمایش به Arduino] * - Vcc - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 */ #include #include

#عبارتند از

#تعریف 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]

// محاسبه برای 9615Hz 256 نمونه توایع cos_t شناور [IX_LEN] PROGMEM = {.8932243011955153،.8700869911087115،.8448535652497071،.8032075314806449،.6895405447370669،.6343932841636456،.5555702330196023،.4713967368259978}؛ const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654 ، 0.49289819222978404 ، 0.5349976198870972 ، 0.5956993044924334 ، 0.7242470829514669 ، 0.7730104533627369 ، 0.831924984 ، 0.8319246 ، 0.83141296 ، 0.8319246 ، 0.8319246

typedef struct {

رقم کاراکتر ؛ شاخص uint8_t ؛ } digit_t؛

رقم_تشخیص_شخص ؛

const char table [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 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 0x04 ، 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 ؛ // کانال فروش ، right-adj ، از پین AREF ADCSRA = _BV (ADEN) | استفاده کنید // ADC را فعال کنید _BV (ADSC) | // ADC start _BV (ADATE) | // ماشه خودکار _BV (ADIE) | // وقفه فعال _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0) ؛ // 128: 1 /13 = 9615 هرتز ADCSRB = 0 ؛ // حالت آزاد اجرا DIDR0 = _BV (0)؛ // خاموش کردن ورودی دیجیتال برای پین ADC TIMSK0 = 0؛ // تایمر 0 خاموش}

void goertzel (uint8_t *نمونه ، شناور *طیف) {

شناور 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 ؛ } result result / len؛ }

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

if (آستانه <THRESHOLD) {بازگشت -1 ؛ } int8_t ix = -1؛ برای (uint16_t i = 0؛ i آستانه) {if (ix == -1) {ix = i؛ } else {return -1؛ }}} return ix؛ }

void dete_digit (float *spectrum) {

شناور avg_row = avg (طیف ، 4) ؛ شناور avg_col = avg (& طیف [4] ، 4) ؛ int8_t row = get_single_index_above_threshold (طیف ، 4 ، avg_row) ؛ int8_t col = get_single_index_above_threshold (& spectrum [4] ، 4 ، avg_col) ؛ if (row! = -1 && col! = -1 && avg_col> 200) {dete_digit.digit = pgm_read_byte (& (جدول [سطر] [col])) ؛ detect_digit.index = pgm_read_byte (& (char_indexes [ردیف] [col]))؛ } else {dete_digit.digit = 0؛ }}

void drawSprite (بایت* Sprite) {

// ماسک برای بدست آوردن بیت ستون از sprite row byte mask = B10000000 استفاده می شود؛ for (int iy = 0؛ iy <8؛ iy ++) {for (int ix = 0؛ ix <8؛ ix ++) {lmd.setPixel (7 - iy، ix، (bool) (sprite [iy] & mask)) ؛

// ماسک را یک پیکسل به راست منتقل کنید

mask = mask >> 1؛ }

// بازنشانی ماسک ستون

ماسک = B10000000؛ }}

void setup () {

cli ()؛ initADC ()؛ sei ()؛

Serial.begin (115200) ؛

lmd.setEnabled (درست) ؛ lmd.setIntensity (2) ؛ lmd.clear ()؛ lmd.display ()؛

dete_digit.digit = 0؛

}

طولانی بدون علامت z = 0؛

حلقه خالی () {

در حالی که (ADCSRA & _BV (ADIE)) ؛ // منتظر بمانید تا نمونه برداری صوتی گواترزل (نمونه ها ، طیف) را به پایان برساند. detective_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) detect_digit.digit) ؛ } z ++ ؛

samplePos = 0 ؛

ADCSRA | = _BV (ADIE) ؛ // ادامه نمونه گیری وقفه

}

ISR (ADC_vect) {

uint16_t نمونه = ADC؛

نمونه [samplePos ++] = نمونه - 400 ؛

if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE) ؛ // بافر کامل ، وقفه خاموش}}

مرحله 3: شماتیک

طرحواره ها
طرحواره ها

اتصالات زیر باید ایجاد شود:

میکروفون به آردوینو

خارج -> A0

Vcc -> 3.3V Gnd -> Gnd

اتصال AREF به 3.3V مهم است

نمایش به آردوینو

Vcc -> 5V

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

مرحله 4: نتیجه گیری

چه چیزی می تواند در اینجا بهبود یابد؟ من از N = 256 نمونه با نرخ 9615 هرتز که دارای نشتی طیف است استفاده کردم ، اگر N = 205 و نرخ 8000Hz باشد ، فرکانس های مورد نظر با شبکه گسسته مطابقت دارد. برای آن ADC باید در حالت سرریز تایمر استفاده شود.

توصیه شده: