ዝርዝር ሁኔታ:

DTMF ፈታሽ: 4 ደረጃዎች
DTMF ፈታሽ: 4 ደረጃዎች

ቪዲዮ: DTMF ፈታሽ: 4 ደረጃዎች

ቪዲዮ: DTMF ፈታሽ: 4 ደረጃዎች
ቪዲዮ: Создание DTMF звонка для Вашей радиостанции 2024, ሀምሌ
Anonim
Image
Image

አጠቃላይ እይታ

በዲጂታል ሲግናል ፕሮሰሲንግ በመስመር ላይ ኮርስ ላይ ይህንን መሣሪያ በቤት ምደባ ለመገንባት አነሳሳኝ። ይህ ከአርዱዲኖ UNO ጋር የተተገበረ የ DTMF ዲኮደር ነው ፣ እሱ በሚያወጣው ድምጽ በድምፅ ሞድ ውስጥ በስልክ ቁልፍ ሰሌዳ ላይ የተጫነ አሃዝ ያሳያል።

ደረጃ 1 - ስልተ ቀመሩን መረዳት

ኮዱ
ኮዱ

በዲኤምቲኤፍ ውስጥ እያንዳንዱ ምልክት በስዕሉ ላይ ባለው ሰንጠረዥ መሠረት በሁለት ድግግሞሽ የተቀረፀ ነው።

መሣሪያው ከማይክሮፎኑ ግብዓት ይይዛል እና የስምንት ድግግሞሾችን ስፋት ያሰላል። ከፍተኛ ድግግሞሽ ያላቸው ሁለት ድግግሞሾች ረድፍ እና የተቀረፀውን ምልክት አምድ ይሰጣሉ።

የውሂብ ማግኛ

የንፅፅር ትንተና ናሙናዎችን ለማከናወን በተወሰነ ሊገመት በሚችል ድግግሞሽ መያዝ አለባቸው። ይህንን ለማሳካት በከፍተኛ ትክክለኛነት (ቅድመ-ተቆጣጣሪ 128) ነፃ-አሂድ የኤዲሲ ሁነታን ተጠቅሜ የናሙና ደረጃ 9615Hz ይሰጣል። ከዚህ በታች ያለው ኮድ የአርዲኖን ኤዲሲን እንዴት ማዋቀር እንደሚቻል ያሳያል።

ባዶነት initADC () {

// ኢኒት ኤዲሲ; f = (16MHz/prescaler)/13 ዑደቶች/መለወጥ ADMUX = 0; // ሰርጥ sel ፣ right-adj ፣ AREF pin ADCSRA = _BV (ADEN) | // ADC ያንቁ _BV (ADSC) | // ADC ጅምር _BV (ADATE) | // በራስ ተነሳሽነት _BV (ADIE) | // አቋርጥ _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // ነፃ አሂድ ሁኔታ DIDR0 = _BV (0); // ለኤዲሲ ፒን TIMSK0 = 0 ዲጂታል ግብዓት ያጥፉ ፤ // Timer0 ጠፍቷል} እና የተቋረጠው ተቆጣጣሪው ይህንን ISR (ADC_vect) {uint16_t ናሙና = ADC ፣ ናሙናዎች [samplePos ++] = ናሙና - 400; ከሆነ (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // ቋት ሞልቷል ፣ አቋርጦ ጠፍቷል}}

ስፔክትረም ትንተና

ናሙናዎችን ከሰበሰብኩ በኋላ የ 8 ድግግሞሾችን የኢኮዲንግ ምልክቶችን ስፋት እሰላለሁ። ለዚህ ሙሉ ኤፍኤፍቲ ማሄድ አያስፈልገኝም ፣ ስለዚህ የ Goertzel ስልተ ቀመርን እጠቀም ነበር።

ባዶ goertzel (uint8_t *ናሙናዎች ፣ ተንሳፋፊ *ስፔክትረም) {

ተንሳፋፊ v_0 ፣ v_1 ፣ v_2; ተንሳፋፊ ዳግም ፣ 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])); ተንሳፋፊ ሀ = 2. * ሐ; 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; } ዳግም = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); ስፔክትረም [k] = amp; }}

ደረጃ 2 - ኮዱ

ከላይ ያለው ስዕል ከፍተኛው ስፋት ከ 697 Hz እና 1477Hz ጋር የሚዛመድበትን አሃዝ 3 የመቀየሪያ ምሳሌን ያሳያል።

የተሟላ ንድፍ እንደሚከተለው ይመስላል

/** * ግንኙነቶች ፦ * [ማይክ ለ አርዱinoኖ] * - ውጭ -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - አርዱinoኖ ፦ AREF -> 3.3V * [ለአርዲኖ ማሳያ] * - ቪሲሲ - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 */ #ያካትቱ #ያካትቱ

#ያካትቱ

#CS_PIN ን ይግለጹ 9

#ገላጭ ኤን 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 ናሙናዎች const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153 ፣ 0.8700869911087115 ፣ 0.8448535652497071 ፣ 0.8032075314806449 ፣ 0.689540544737066985555555555555555555563235632356323563235 533 595 593 595 593 59 43 59 56 59 58 58 59 59 59 59 59 53 59 59 59 53 59 59 59 59 59 53 59 53 59 59 59 59 59 53 59 59 54 const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654 ፣ 0.49289819222978404 ፣ 0.5349976198870972 ፣ 0.5956993044924334 ፣ 0.7242470829514669 ፣ 0.77301045336273699484946 ፣ 468444444 ፣ 583

የንድፍ መዋቅር {

የቻር አሃዝ; uint8_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 ፣ 0x48 ፣ 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 0x04 ፣ 0x04 ፣ 0x78} ፣ // 9 {0x00 ፣ 0x1c ፣ 0x22 ፣ 0x42 ፣ 0x42 ፣ 0x7e ፣ 0x42 ፣ 0x42} ፣ // ኤ {0x00 ፣ 0x78 ፣ 0x44 ፣ 0x44 ፣ 0x78 ፣ 0x44 ፣ 0x44 ፣ 0x44 / ለ {0x00 ፣ 0x3c ፣ 0x44 ፣ 0x40 ፣ 0x40 ፣ 0x40 ፣ 0x44 ፣ 0x7c} ፣ // ሲ {0x00 ፣ 0x7c ፣ 0x42 ፣ 0x42 ፣ 0x42 ፣ 0x42 ፣ 0x44 ፣ 0x78} ፣ // መ {0x00 ፣ 0x0a ፣ 0x0a ፣ 0x14 ፣ 0x28 ፣ 0xfe ፣ 0x50 ፣ 0x00} ፣ // # {0x00 ፣ 0x10 ፣ 0x54 ፣ 0x38 ፣ 0x10 ፣ 0x38 ፣ 0x54 ፣ 0x10} // *};

ባዶነት initADC () {

// ኢኒት ኤዲሲ; f = (16MHz/prescaler)/13 ዑደቶች/መለወጥ ADMUX = 0; // ሰርጥ sel ፣ right-adj ፣ AREF pin ADCSRA = _BV (ADEN) | // ADC ያንቁ _BV (ADSC) | // ADC ጅምር _BV (ADATE) | // በራስ ተነሳሽነት _BV (ADIE) | // አቋርጥ _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // ነፃ አሂድ ሁኔታ DIDR0 = _BV (0); // ለኤዲሲ ፒን TIMSK0 = 0 ዲጂታል ግብዓት ያጥፉ ፤ // ሰዓት ቆጣሪ 0 ጠፍቷል}

ባዶ goertzel (uint8_t *ናሙናዎች ፣ ተንሳፋፊ *ስፔክትረም) {

ተንሳፋፊ v_0 ፣ v_1 ፣ v_2; ተንሳፋፊ ዳግም ፣ 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])); ተንሳፋፊ ሀ = 2. * ሐ; 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; } ዳግም = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); ስፔክትረም [k] = amp; }}

ተንሳፋፊ አማካይ (ተንሳፋፊ *ሀ ፣ uint16_t len) {

ተንሳፋፊ ውጤት =.0; ለ (uint16_t i = 0; i <len; i ++) {result+= a ; } የመመለሻ ውጤት / ሌን; }

int8_t_single_index_above_threshold (ተንሳፋፊ *ሀ ፣ uint16_t ሌን ፣ ተንሳፋፊ ደፍ) {

ከሆነ (ደፍ <THRESHOLD) {መመለስ -1; } int8_t ix = -1; ለ (uint16_t i = 0; i ደፍ) {ከሆነ (ix == -1) {ix = i; } ሌላ {መመለስ -1; }}} መመለስ ix; }

ባዶነት detect_digit (ተንሳፋፊ *ስፔክትረም) {

ተንሳፋፊ avg_row = avg (ስፔክትረም ፣ 4); ተንሳፋፊ avg_col = avg (& spectrum [4], 4); int8_t ረድፍ = ማግኘት_single_index_above_threshold (spectrum ፣ 4 ፣ avg_row); int8_t col = get_single_index_above_threshold (& spectrum [4] ፣ 4 ፣ avg_col) ፤ ከሆነ (ረድፍ! = -1 && col! = -1 && avg_col> 200) {detected_digit.digit = pgm_read_byte (& (ሠንጠረዥ [ረድፍ] [col])); detected_digit.index = pgm_read_byte (& (char_indexes [ረድፍ] [col]))); } ሌላ {detected_digit.digit = 0; }}

ባዶ ባዶ ስፕሪፕት (ባይት* sprite) {

// ጭምብሉ የዓምዱን ቢት ከ sprite ረድፍ ባይት ጭንብል = B10000000 ለማግኘት ያገለግላል። ለ (int iy = 0; iy <8; iy ++) {ለ (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & mask));

// ጭምብሉን በአንድ ፒክሰል ወደ ቀኝ ያዙሩት

ጭምብል = ጭምብል >> 1; }

// የአምድ ጭምብልን ዳግም ያስጀምሩ

ጭምብል = B10000000; }}

ባዶነት ማዋቀር () {

ክሊ (); initADC (); sei ();

Serial.begin (115200);

lmd.setEnabled (እውነት); lmd.setIntensity (2); lmd.clear (); lmd.display ();

detected_digit.digit = 0;

}

ያልተፈረመ ረጅም z = 0;

ባዶነት loop () {

ሳለ (ADCSRA & _BV (ADIE)); // goertzel (ናሙናዎች ፣ ስፔክትረም) እስኪጨርስ የኦዲዮ ናሙና ይጠብቁ ፤ dete_digit (ስፔክትረም);

ከሆነ (detected_digit.digit! = 0) {

drawSprite (ቅርጸ -ቁምፊ [detected_digit.index]); lmd.display (); } ከሆነ (z % 5 == 0) {ለ (int i = 0; i <IX_LEN; i ++) {Serial.print (spectrum ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) detected_digit.digit); } z ++;

samplePos = 0;

ADCSRA | = _BV (ADIE); // የናሙና ናሙና ማቋረጡን ይቀጥሉ

}

ISR (ADC_vect) {

uint16_t ናሙና = ADC;

ናሙናዎች [samplePos ++] = ናሙና - 400;

ከሆነ (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // ቋት ሞልቷል ፣ አቋርጦ ጠፍቷል}}

ደረጃ 3: መርሃግብሮች

መርሃግብሮች
መርሃግብሮች

የሚከተሉት ግንኙነቶች መደረግ አለባቸው

ማይክ ለአርዲኖ

ውጭ -> A0

Vcc -> 3.3V Gnd -> Gnd

AREF ን ከ 3.3 ቪ ጋር ማገናኘት አስፈላጊ ነው።

ለአርዱዲኖ ማሳያ

ቪሲሲ -> 5 ቪ

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

ደረጃ 4 መደምደሚያ

እዚህ ምን ሊሻሻል ይችላል? እኔ N = 256 ናሙናዎችን በ ‹9615Hz› መጠን አንዳንድ የፍሳሽ ማስወገጃ (ፍሳሽ) ን ተጠቅሜ ፣ N = 205 እና ደረጃ 8000Hz ከሆነ ፣ የሚፈለጉት ድግግሞሽዎች ከተለዋዋጭ ፍርግርግ ጋር ይጣጣማሉ። ለዚያ ኤዲሲ በሰዓት ቆጣሪ ፍሰት ሁኔታ ውስጥ ጥቅም ላይ መዋል አለበት።

የሚመከር: