Përmbajtje:

Detektor DTMF: 4 hapa
Detektor DTMF: 4 hapa

Video: Detektor DTMF: 4 hapa

Video: Detektor DTMF: 4 hapa
Video: 1)SIM 800L DTMF НА 4 РЕЛЕ С ГОЛОСОВЫМ ОПОВЕЩЕНИЕМ И ТЕСТОМ ВКЛЮЧЕННЫХ УСТРОЙСТВ 2024, Nëntor
Anonim
Image
Image

Vështrim i përgjithshëm

Unë u frymëzova për të ndërtuar këtë pajisje nga një detyrë në shtëpi në kursin online të Përpunimit të Sinjalit Dixhital. Ky është një dekodues DTMF i zbatuar me Arduino UNO, ai zbulon një shifër të shtypur në një tastierë të telefonit në modalitetin e tonit nga tingulli që prodhon.

Hapi 1: Kuptimi i Algoritmit

Kodi
Kodi

Në DTMF çdo simbol është i koduar me dy frekuenca sipas tabelës në figurë.

Pajisja kap hyrjen nga mikrofoni dhe llogarit amplitudat e tetë frekuencave. Dy frekuenca me amplituda maksimale japin një rresht dhe një kolonë të simbolit të koduar.

Marrja e të dhënave

Për të kryer analizën e spektrit, mostrat duhet të kapen në një frekuencë të caktuar të parashikueshme. Për të arritur këtë, unë përdor modalitetin ADC të lirë me saktësi maksimale (prescaler 128), i cili jep shkallën e marrjes së mostrave 9615Hz. Kodi më poshtë tregon se si të konfiguroni ADC të Arduino.

void initADC () {

// Init ADC; f = (16MHz/prescaler)/13 cikle/konvertim ADMUX = 0; // Shitja e kanalit, djathtas-adj, përdorni pin AREF ADCSRA = _BV (ADEN) | // ADC aktivizoni _BV (ADSC) | // ADC start _BV (ADATE) | // Shkrepësi automatik _BV (ADIE) | // Ndërprerja e aktivizimit _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Hz ADCSRB = 0; // Mënyra e drejtimit të lirë DIDR0 = _BV (0); // Fikni hyrjen dixhitale për pinin ADC TIMSK0 = 0; // Kohëmatësi0 i fikur} Dhe mbajtësi i ndërprerjeve duket si ky ISR (ADC_vect) {uint16_t mostër = ADC; mostra [samplePos ++] = mostër - 400; nëse (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Tamponi i plotë, ndërprerja e çaktivizuar}}

Analiza e spektrit

Pas mbledhjes së mostrave unë llogaris amplitudat e 8 frekuencave që kodojnë simbole. Nuk kam nevojë të ekzekutoj FFT të plotë për këtë, kështu që kam përdorur algoritmin e Goertzel.

void goertzel (uint8_t *mostra, float *spektër) {

noton v_0, v_1, v_2; notoj re, im, amp; për (uint8_t k = 0; k <IX_LEN; k ++) {noton c = pgm_read_float (& (cos_t [k])); noton s = pgm_read_float (& (sin_t [k])); noton a = 2. * c; v_0 = v_1 = v_2 = 0; për (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (noton) (mostrat ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektri [k] = amp; }}

Hapi 2: Kodi

Fotografia e mësipërme tregon shembullin e kodimit të shifrës 3 ku amplituda maksimale korrespondon me frekuencat 697Hz dhe 1477Hz.

Skica e plotë duket si më poshtë

/** * Lidhjet: * [Mik për Arduino] * - Jashtë -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - Arduino: AREF -> 3.3V * [Shfaq në Arduino] * - Vcc - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 */ #include #include

#përfshi

#përcaktoni CS_PIN 9

#përcakto N 256

#përcakto IX_LEN 8 #përcakto THRESHOLD 20

LEDMatrixDriver lmd (1, CS_PIN);

mostra uint8_t [N];

mostër e paqëndrueshme uint16_tPos = 0;

spektri notues [IX_LEN];

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

// Llogaritur për 9615Hz 256 mostra const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.6343963968, 0.63439363985, 0.634393603, 0.634393603, 0.63439.396393, 0.63439.396393 0.6343.96393, 0.6343.96393, 0.6343.9639639 0. 0.6343.9639639. const pluskues sin_t [IX_LEN] PROGMEM = {,44961132965460654,,49289819222978404,,5349976198870972,,5956993044924334,,7242470829514669,,7730104533627369,,8314696123025451,,8819212643483549};

typedef struct {

shifra char; indeksi uint8_t; } shifra_t;

shifra_t zbuluar_shifra;

const tabelë 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} };

font byte [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 }, // 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 = (16MHz/prescaler)/13 cikle/konvertim ADMUX = 0; // Shitja e kanalit, djathtas-adj, përdorni pin AREF ADCSRA = _BV (ADEN) | // ADC aktivizoni _BV (ADSC) | // ADC start _BV (ADATE) | // Shkrepësi automatik _BV (ADIE) | // Ndërprerja e aktivizimit _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Hz ADCSRB = 0; // Mënyra e drejtimit të lirë DIDR0 = _BV (0); // Fikni hyrjen dixhitale për pinin ADC TIMSK0 = 0; // Kohëmatësi 0 i fikur}

void goertzel (uint8_t *mostra, float *spektër) {

noton v_0, v_1, v_2; notoj re, im, amp; për (uint8_t k = 0; k <IX_LEN; k ++) {noton c = pgm_read_float (& (cos_t [k])); noton s = pgm_read_float (& (sin_t [k])); noton a = 2. * c; v_0 = v_1 = v_2 = 0; për (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (noton) (mostrat ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektri [k] = amp; }}

mesatar float (noto *a, uint16_t len) {

rezultati notues =.0; për (uint16_t i = 0; i <len; i ++) {rezultati+= a ; } rezultati i kthimit / len; }

int8_t merrni_single_index_above_thresh (float *a, uint16_t len, pragu notues) {

nëse (pragu <THRESHOLD) {kthehu -1; } int8_t ix = -1; për (uint16_t i = 0; i pragu) {if (ix == -1) {ix = i; } else {kthimi -1; }}} kthehu ix; }

void dete_digit (float *spektri) {

noton avg_row = avg (spektri, 4); noton avg_col = mesatar (& spektri [4], 4); int8_t rresht = merrni_single_index_above_thresh (spektri, 4, avg_row); int8_t col = merrni_single_index_above_thresh (& spectrum [4], 4, avg_col); nëse (rreshti! = -1 && kol! = -1 && avg_col> 200) {zbuluar_digit.digit = pgm_read_byte (& (tabela [rreshti] [kol]))); zbuluar_digit.index = pgm_read_byte (& (char_indexes [rresht] [col])); } else {zbuluar_digit.digit = 0; }}

void drawSprite (byte* sprite) {

// Maska përdoret për të marrë bitin e kolonës nga masa e bajtit të rreshtit sprite = B10000000; për (int iy = 0; iy <8; iy ++) {për (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & mask));

// zhvendoseni maskën me një piksel në të djathtë

maskë = maskë >> 1; }

// rivendos maskën e kolonës

maskë = B10000000; }}

void setup () {

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

Serial.fillo (115200);

lmd.setEnabled (e vërtetë); lmd.setIntensiteti (2); lmd.qartë (); lmd.shfaq ();

zbuluar_digit.digit = 0;

}

i panënshkruar i gjatë z = 0;

lak void () {

ndërsa (ADCSRA & _BV (ADIE)); // Prisni që marrja e mostrave audio të përfundojë goertzel (mostra, spektër); shifra e zbulimit (spektri);

nëse (zbuluar_digit.digit! = 0) {

drawSprite (font [zbuluar_digit.index]); lmd.shfaq (); } nëse (z % 5 == 0) {për (int i = 0; i <IX_LEN; i ++) {Serial.print (spektri ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) zbuluar_digit.digit); } z ++;

mostërPos = 0;

ADCSRA | = _BV (ADIE); // Vazhdo ndërprerjen e marrjes së mostrave

}

ISR (ADC_vect) {

mostër uint16_t = ADC;

mostra [samplePos ++] = mostër - 400;

nëse (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Tamponi i plotë, ndërprerja e çaktivizuar}}

Hapi 3: Skemat

Skematike
Skematike

Lidhjet e mëposhtme duhet të bëhen:

Mikrofoni për Arduino

Jashtë -> A0

Vcc -> 3.3V Gnd -> Gnd

Importantshtë e rëndësishme të lidhni AREF me 3.3V

Shfaq në Arduino

Vcc -> 5V

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

Hapi 4: Përfundimi

Çfarë mund të përmirësohet këtu? Kam përdorur mostra N = 256 në shkallën 9615Hz e cila ka një rrjedhje të spektrit, nëse N = 205 dhe shkalla është 8000Hz atëherë frekuencat e dëshiruara përkojnë me rrjetin diskretizues. Për këtë ADC duhet të përdoret në modalitetin e tejkalimit të kohëmatësit.

Recommended: