Përmbajtje:
Video: Detektor DTMF: 4 hapa
2024 Autor: John Day | [email protected]. E modifikuara e fundit: 2024-01-30 12:21
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
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
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:
DTMF VIDEO STREAMING ROVER: 3 hapa
DTMF VIDEO STREAMING ROVER: përshëndetje pas ROVER -it tim të kontrolluar LINUX TERMINAL TIRMINAL dhe PC WIFI DTMF ky është roboti im i tretë. dhe si dy të tjerët këtu gjithashtu nuk kam përdorur asnjë mikrokontrollues ose programim për ta mbajtur atë të thjeshtë dhe të lehtë për tu bërë. gjithashtu transmeton video drejtpërdrejt përmes wifi
Si të bëni një Dekodues të Thjeshtë të DTMF (toni) të linjës telefonike: 3 hapa
Si të bëni një Dekodues të Thjeshtë të Linjës Telefonike DTMF (ton): Ky është një projekt i thjeshtë që ju lejon të deshifroni sinjalet DTMF në thelb çdo linjë telefonike. Në këtë tutorial, ne po përdorim deshifruesin MT8870D. Ne po përdorim një dekodues të paravendosur të tonit, sepse, më besoni, është një dhimbje në pjesën e pasme të provosh dhe ta bësh atë me
WIFI DTMF ROBOT: 5 hapa
WIFI DTMF ROBOT: përshëndetje në këtë tutorial do t'ju tregoj se si mund të bëni një rover të kontrolluar nga kompjuteri pa përdorur mikro kontrollues, kjo do të thotë që në këtë projekt nuk ka kod të nivelit të lartë të përfshirë, thjesht keni nevojë për njohuri themelore në lidhje me krijimin e faqeve html. mund ta shikoni të plotë
Si të bëni një robot të kontrolluar nga celulari Bazuar në DTMF - Pa Mikrokontrollues & Programim - Kontroll nga kudo në botë - RoboGeeks: 15 hapa
Si të bëni një robot të kontrolluar nga celulari Bazuar në DTMF | Pa Mikrokontrollues & Programim | Kontroll nga kudo në botë | RoboGeeks: Dëshironi të bëni një robot i cili mund të kontrollohet nga kudo në botë, Le ta bëjmë atë
Karrige me rrota Robotike e kontrolluar nga DTMF dhe Gjest: 7 hapa (me fotografi)
Karrige me rrota Robotike e kontrolluar nga DTMF dhe Gesture: Në këtë botë një numër njerëzish janë me aftësi të kufizuara. Jeta e tyre sillet rreth rrotave. Ky projekt paraqet një qasje për kontrollin e lëvizjes së karrigeve me rrota duke përdorur njohjen e gjesteve të dorës dhe DTMF të një smartphone