Talaan ng mga Nilalaman:
- Hakbang 1: Pag-unawa sa Algorithm
- Hakbang 2: Ang Code
- Hakbang 3: Mga Skematika
- Hakbang 4: Konklusyon
Video: DTMF Detector: 4 na Hakbang
2024 May -akda: John Day | [email protected]. Huling binago: 2024-01-30 13:13
Pangkalahatang-ideya
May inspirasyon akong bumuo ng aparatong ito ng isang takdang-aralin sa bahay sa kurso sa online na Pagproseso ng Digital Signal. Ito ay isang decoder ng DTMF na ipinatupad sa Arduino UNO, nakita nito ang isang digit na pinindot sa isang keypad ng telepono sa tone mode ng tunog na ginagawa nito.
Hakbang 1: Pag-unawa sa Algorithm
Sa DTMF ang bawat simbolo ay naka-encode na may dalawang frequency alinsunod sa talahanayan sa larawan.
Nakukuha ng aparato ang input mula sa mikropono at kinakalkula ang mga amplitude ng walong mga frequency. Ang dalawang dalas na may maximum na amplitude ay nagbibigay ng isang hilera at isang haligi ng naka-encode na simbolo.
Pagkuha ng data
Upang maisagawa ang mga sample ng pagsusuri ng spectrum ay dapat makuha sa isang tiyak na hinuhulaan na dalas. Upang makamit ito, ginamit ko ang libreng-run na ADC mode na may maximum na katumpakan (prescaler 128) nagbibigay ito ng sampling rate na 9615Hz. Ipinapakita ng code sa ibaba kung paano i-configure ang Arduino's ADC.
walang bisa initADC () {
// Init ADC; f = (16MHz / prescaler) / 13 cycle / conversion ADMUX = 0; // Channel sel, right-adj, gamitin ang AREF pin ADCSRA = _BV (ADEN) | // ADC paganahin ang _BV (ADSC) | // ADC start _BV (ADATE) | // Auto trigger _BV (ADIE) | // Makagambala paganahin ang _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Free-run mode DIDR0 = _BV (0); // Patayin ang digital input para sa ADC pin TIMSK0 = 0; // Timer0 off} At ang gumagambala ng handler ay ganito ang ISR (ADC_vect) {uint16_t sample = ADC; mga sample [samplePos ++] = sample - 400; kung (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer full, interrupt off}}
Pagsusuri sa Spectrum
Pagkatapos ng pagkolekta ng mga sample kinakalkula ko ang mga amplitude ng 8 mga frequency na simbolo ng pag-encode. Hindi ko kailangang patakbuhin ang buong FFT para dito, kaya ginamit ko ang algorithm ni Goertzel.
void goertzel (uint8_t * mga sample, float * spectrum) {
float v_0, v_1, v_2; float re, im, amp; para sa (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; para sa (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (mga sample ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spectrum [k] = amp; }}
Hakbang 2: Ang Code
Ipinapakita ng larawan sa itaas ang halimbawa ng pag-encode ng digit 3 kung saan ang maximum na amplitude ay tumutugma sa mga frequency na 697Hz at 1477Hz.
Ang kumpletong sketch ay ang hitsura ng mga sumusunod
/ ** * Mga Koneksyon: * [Mic to Arduino] * - Out -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - Arduino: AREF -> 3.3V * [Display to Arduino] * - Vcc - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 * / # isama ang # isama
# isama
# tukuyin ang CS_PIN 9
# tukuyin ang N 256
# tukuyin ang IX_LEN 8 # tukuyin ang THRESHOLD 20
LEDMatrixDriver lmd (1, CS_PIN);
uint8_t mga sample [N];
pabagu-bago ng isip uint16_t samplePos = 0;
float spectrum [IX_LEN];
// Frequences [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]
// Kinalkula para sa 9615Hz 256 na mga halimbawa ng const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.634393284163645613, 0.56083681378 Const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.8314696123025451, 0.83019454, 0.8301945496, 0.8301945496, 0.830194519451, 0.83019459794, 0.828191930451, 0.8301913054
typedef struct {
char digit; uint8_t index; } digit_t;
nakita ang digit_t_digit;
talahanayan ng char 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} };
byte font [16] [8] = {
{0x00, 0x38, 0x44, 0x4c, 0x54, 0x64, 0x44, 0x38}, // 0 {0x04, 0x0c, 0x14, 0x24, 0x04, 0x04, 0x04, 0x04}, // 1 {0x00, 0x30, 0x48, 0x0, 0x04, 0x38, 0x40, 0x7c}, // 2 {0x00, 0x38, 0x04, 0x04, 0x18, 0x04, 0x44, 0x38}, // 3 {0x00, 0x04, 0x0c, 0x14, 0x24, 0x7e, 0x04, 0x0 }, // 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} // *};
walang bisa initADC () {
// Init ADC; f = (16MHz / prescaler) / 13 cycle / conversion ADMUX = 0; // Channel sel, right-adj, gamitin ang AREF pin ADCSRA = _BV (ADEN) | // ADC paganahin ang _BV (ADSC) | // ADC start _BV (ADATE) | // Auto trigger _BV (ADIE) | // Makagambala paganahin ang _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Free-run mode DIDR0 = _BV (0); // Patayin ang digital input para sa ADC pin TIMSK0 = 0; // Naka-off ang Timer0}
void goertzel (uint8_t * mga sample, float * spectrum) {
float v_0, v_1, v_2; float re, im, amp; para sa (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; para sa (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (mga sample ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spectrum [k] = amp; }}
float avg (float * a, uint16_t len) {
resulta ng float =.0; para sa (uint16_t i = 0; i <len; i ++) {resulta + = a ; } ibalik ang resulta / len; }
int8_t makakuha ng_single_index_above_threshold (float * a, uint16_t len, float threshold) {
kung (threshold <THRESHOLD) {return -1; } int8_t ix = -1; para sa (uint16_t i = 0; i threshold) {if (ix == -1) {ix = i; } iba pa {bumalik -1; }}} ibalik ang ix; }
walang bisa ang detect_digit (float * spectrum) {
float avg_row = avg (spectrum, 4); float avg_col = avg (& spectrum [4], 4); int8_t row = get_single_index_above_threshold (spectrum, 4, avg_row); int8_t col = get_single_index_above_threshold (& spectrum [4], 4, avg_col); kung (row! = -1 && col! = -1 && avg_col> 200) {napansin_digit.digit = pgm_read_byte (& (table [row] [col])); napansin_digit.index = pgm_read_byte (& (char_indexes [row] [col])); } iba pa {napansin_digit.digit = 0; }}
void drawSprite (byte * sprite) {
// Ang mask ay ginagamit upang makuha ang haligi ng haligi mula sa sprite row byte mask = B10000000; para sa (int iy = 0; iy <8; iy ++) {para sa (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & mask));
// shift the mask by one pixel to the right
mask = mask >> 1; }
// reset ang mask ng haligi
mask = B10000000; }}
walang bisa ang pag-setup () {
Tala (); initADC (); sei ();
Serial.begin (115200);
lmd.setEn pinagana (totoo); lmd.setIntensity (2); lmd.clear (); lmd.display ();
napansin_digit.digit = 0;
}
unsigned mahabang z = 0;
void loop () {
habang (ADCSRA & _BV (ADIE)); // Maghintay para sa audio sampling upang matapos ang goertzel (mga sample, spectrum); makita_digit (spectrum);
kung (napansin_digit.digit! = 0) {
drawSprite (font [nakita_digit.index]); lmd.display (); } kung (z% 5 == 0) {para sa (int i = 0; i <IX_LEN; i ++) {Serial.print (spectrum ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) napansin_digit.digit); } z ++;
samplePos = 0;
ADCSRA | = _BV (ADIE); // Ipagpatuloy ang pag-sampal ng sampling
}
ISR (ADC_vect) {
uint16_t sample = ADC;
mga sample [samplePos ++] = sample - 400;
kung (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer full, interrupt off}}
Hakbang 3: Mga Skematika
Ang mga sumusunod na koneksyon ay dapat gawin:
Mic kay Arduino
Lumabas -> A0
Vcc -> 3.3V Gnd -> Gnd
Mahalagang ikonekta ang AREF sa 3.3V
Ipakita kay Arduino
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
Hakbang 4: Konklusyon
Ano ang maaaring mapabuti dito? Gumamit ako ng N = 256 na mga sample sa rate 9615Hz na mayroong ilang spectrum leakage, kung N = 205 at rate ay 8000Hz kung gayon ang nais na mga frequency ay kasabay ng discretisation grid. Para sa ADC na iyon ay dapat gamitin sa mode ng overflow ng timer.
Inirerekumendang:
DTMF VIDEO STREAMING ROVER: 3 Hakbang
DTMF VIDEO STREAMING ROVER: hi pagkatapos ng aking LINUX TERMINAL CONTROLLED ROVER at WIFI DTMF PC CONTROLLED ROBOT ito ang aking pangatlong robot. at tulad ng iba pang dalawa dito hindi rin ako gumamit ng anumang microcontroller o programa upang mapanatili itong simple at madaling gawin. Nag-stream din ito ng live na video sa wifi
Paano Gumawa ng isang Simpleng DTMF (tone) Phone Line Decoder: 3 Mga Hakbang
Paano Gumawa ng isang Simpleng DTMF (tono) Decoder ng Linya ng Telepono: Ito ay isang simpleng proyekto na hinahayaan kang ma-decode ang mga signal ng DTMF sa karaniwang anumang linya ng telepono. Sa tutorial na ito, ginagamit namin ang decoder MT8870D. Gumagamit kami ng isang prebuilt tone decoder dahil, maniwala ka sa akin, sakit sa likuran upang subukan at gawin ito sa
WIFI DTMF ROBOT: 5 Hakbang
WIFI DTMF ROBOT: hi sa tutorial na ito ipapakita ko sa iyo kung paano ka makagagawa ng isang pc kinokontrol na rover nang hindi gumagamit ng micro controller, nangangahulugan ito sa proyektong ito na walang kasamang mataas na antas ng code na kailangan mo lamang ng pangunahing kaalaman tungkol sa paggawa ng pahina ng html na iyon. maaaring panoorin ang buong
Paano Gumawa ng isang Mobile Controlled Robot - Batay sa DTMF - Nang walang Microcontroller at Programming - Pagkontrol Mula Sa Kahit Saan Sa Mundo - RoboGeeks: 15 Hakbang
Paano Gumawa ng isang Mobile Controlled Robot | Batay sa DTMF | Nang walang Microcontroller at Programming | Pagkontrol Mula Sa Kahit Saan Sa Mundo | RoboGeeks: Nais gumawa ng isang robot na maaaring makontrol mula sa kahit saan sa mundo, Hinahayaan Ito
IOT Smoke Detector: I-update ang Umiiral na Smoke Detector Sa IOT: 6 na Hakbang (na may Mga Larawan)
IOT Smoke Detector: I-update ang Umiiral na Smoke Detector Gamit ang IOT: Listahan ng mga nag-aambag, Imbentor: Tan Siew Chin, Tan Yit Peng, Tan Wee Heng Tagapamahala: Dr Chia Kim Seng Kagawaran ng Mechatronic at Robotic Engineering, Faculty of Electrical and Electronic Engineering, Universiti Tun Hussein Onn Malaysia. Ipamahagi