Mundarija:
Video: DTMF detektori: 4 qadam
2024 Muallif: John Day | [email protected]. Oxirgi o'zgartirilgan: 2024-01-30 13:26
Sharh
Menga ushbu qurilmani uydan raqamli signallarni qayta ishlash bo'yicha onlayn kurs bo'yicha topshiriq ilhomlantirdi. Bu Arduino UNO yordamida amalga oshirilgan DTMF dekoderi, u telefon klaviaturasida ohang rejimida bosilgan raqamni u chiqaradigan tovush bilan aniqlaydi.
1 -qadam: Algoritmni tushunish
DTMFda har bir belgi rasmdagi jadvalga muvofiq ikkita chastota bilan kodlangan.
Qurilma mikrofondan kirishni yozib oladi va sakkiz chastota amplitudasini hisoblab chiqadi. Maksimal amplitudali ikkita chastota kodlangan belgining qatorini va ustunini beradi.
Ma'lumot olish
Spektrni tahlil qilish uchun namunalarni ma'lum bir chastotada olish kerak. Bunga erishish uchun men ADC rejimini maksimal aniqlikda ishlatardim (prescaler 128), bu 9615 Gts namuna olish tezligini beradi. Quyidagi kod Arduino ADC -ni qanday sozlashni ko'rsatadi.
bekor ADAD () {
// ADCni ishga tushirish; f = (16 MGts/oldindan hisoblagich)/13 tsikl/konvertatsiya ADMUX = 0; // Channel sel, right-adj, AREF pin ADCSRA = _BV (ADEN) dan foydalaning | // ADC _BV (ADSC) ni yoqish | // ADC boshlanishi _BV (ADATE) | // Avtomatik ishga tushirish _BV (ADIE) | // Tanaffusni yoqish _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Erkin ishlash rejimi DIDR0 = _BV (0); // ADC pin uchun raqamli kirishni o'chirish TIMSK0 = 0; // Taymer0 o'chirilgan} Va uzilish ishlovchisi ISR (ADC_vect) ga o'xshaydi {uint16_t sample = ADC; sample [samplePos ++] = namuna - 400; agar (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Bufer to'lgan, uzilish o'chirilgan}}
Spektrni tahlil qilish
Namunalarni yig'ib bo'lgach, men 8 ta chastotali kodlash belgilarining amplitudalarini hisoblayman. Buning uchun menga to'liq FFT ishga tushirish shart emas, shuning uchun men Goertzel algoritmidan foydalandim.
bo'sh gersel (uint8_t *namunalari, float *spektri) {
suzuvchi v_0, v_1, v_2; float re, im, amp; uchun (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; uchun (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (namunalar ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektr [k] = amp; }}
2 -qadam: Kod
Yuqoridagi rasmda maksimal amplitudasi 697 Gts va 1477 Gts chastotalarga mos keladigan 3 -raqamli kodlash misoli ko'rsatilgan.
To'liq eskiz quyidagicha ko'rinadi
/** * Ulanishlar: * [Micro to Arduino] * - Chiqish -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - Arduino: AREF -> 3.3V * [Arduino displeyi] * - Vcc - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 */ #include #include
#qo'shing
#CS_PIN 9 ni aniqlang
#aniqlang N 256
#IX_LEN 8 ni belgilang #TAHRISI 20 ni aniqlang
LEDMatrixDriver lmd (1, CS_PIN);
uint8_t namunalari [N];
uchuvchi uint16_t samplePos = 0;
suzuvchi spektr [IX_LEN];
// Chastotalar [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]
// 9615 Gts 256 namunali const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.68954054473706396666666666666666666666666666686, 0,8639 const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.7730104533627369, 0.7730104533627369
typedef tuzilishi {
char raqami; uint8_t indeksi; } raqam_t;
raqam_t aniqlangan_ raqam;
const char jadvali [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} };
bayt shrift [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 }, // 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} // *};
bekor initADC () {
// ADCni ishga tushirish; f = (16 MGts/oldindan hisoblagich)/13 tsikl/konvertatsiya ADMUX = 0; // Channel sel, right-adj, AREF pin ADCSRA = _BV (ADEN) dan foydalaning | // ADC _BV (ADSC) ni yoqish | // ADC boshlanishi _BV (ADATE) | // Avtomatik ishga tushirish _BV (ADIE) | // Tanaffusni yoqish _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Erkin ishlash rejimi DIDR0 = _BV (0); // ADC pin uchun raqamli kirishni o'chirish TIMSK0 = 0; // Taymer 0 o'chirilgan}
bo'sh gersel (uint8_t *namunalari, float *spektri) {
suzuvchi v_0, v_1, v_2; float re, im, amp; uchun (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; uchun (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (namunalar ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektr [k] = amp; }}
suzuvchi o'rtacha (float *a, uint16_t len) {
float natijasi =.0; uchun (uint16_t i = 0; i <len; i ++) {natija+= a ; } natijani qaytarish / len; }
int8_t get_single_index_above_threshold (float *a, uint16_t len, float pol) {
if (pol <THRESHOLD) {qaytish -1; } int8_t ix = -1; uchun (uint16_t i = 0; i ostona) {if (ix == -1) {ix = i; } boshqa {qaytish -1; }}} qaytarish ix; }
void detect_digit (float *spektr) {
suzuvchi avg_row = o'rtacha (spektr, 4); suzuvchi avg_col = avg (& spektr [4], 4); int8_t qator = get_single_index_above_threshold (spektr, 4, avg_row); int8_t col = get_single_index_above_threshold (& spektr [4], 4, avg_col); agar (qator! = -1 && col! = -1 && avg_col> 200) {aniqlangan_digit.digit = pgm_read_byte (& (jadval [qator] [col])); aniqlangan_digit.index = pgm_read_byte (& (char_indexes [qator] [col])); } boshqa {aniqlangan_digit.digit = 0; }}
void drawSprite (bayt* sprite) {
// Niqob sprite qator bayt niqobidan ustun bitini olish uchun ishlatiladi = B10000000; for (int iy = 0; iy <8; iy ++) {for (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & mask));
// niqobni bir pikselga o'ngga siljiting
niqob = niqob >> 1; }
// ustun niqobini tiklash
niqob = B10000000; }}
bo'sh o'rnatish () {
cli (); initADC (); sei ();
Serial.begin (115200);
lmd.setEnabled (haqiqiy); lmd.setIntensity (2); lmd.clear (); lmd.display ();
aniqlangan_digit.digit = 0;
}
belgisiz uzun z = 0;
void loop () {
esa (ADCSRA & _BV (ADIE)); // Ovozli namuna olish tugaguncha kuting (namunalar, spektr); aniqlash_digit (spektr);
agar (aniqlangan_digit.digit! = 0) {
drawSprite (shrift [detect_digit.index]); lmd.display (); } if (z % 5 == 0) {for (int i = 0; i <IX_LEN; i ++) {Serial.print (spektr ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) detect_digit.digit); } z ++;
namunaPos = 0;
ADCSRA | = _BV (ADIE); // Namuna olishni to'xtatishni davom ettiring
}
ISR (ADC_vect) {
uint16_t namuna = ADC;
namunalar [samplePos ++] = namuna - 400;
agar (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Bufer to'ldirildi, uzilish o'chirildi}}
3 -qadam: sxemalar
Quyidagi aloqalarni o'rnatish kerak:
Arduino uchun mikrofon
Chiqish -> A0
Vcc -> 3.3V Gnd -> Gnd
AREF -ni 3.3V ga ulash muhim
Arduino -da ko'rsatish
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
4 -qadam: Xulosa
Bu erda nimani yaxshilash mumkin? Men N = 256 namunalarini 9615 Gts tezlikda ishlatardim, ularda spektr oqimi bor edi, agar N = 205 va tezligi 8000 Gts bo'lsa, kerakli chastotalar diskretizatsiya tarmog'iga to'g'ri keladi. Buning uchun ADC taymerni to'ldirish rejimida ishlatilishi kerak.
Tavsiya:
Raspberry Pi - TMD26721 infraqizil raqamli yaqinlik detektori Java darsligi: 4 qadam
Raspberry Pi-TMD26721 infraqizil raqamli yaqinlik detektori Java qo'llanmasi: TMD26721-bu infraqizil raqamli yaqinlik detektori bo'lib, u to'liq 8-pinli sirt o'rnatish modulida to'liq yaqinlikni aniqlash tizimi va raqamli interfeys mantig'ini ta'minlaydi. aniqlik. Pro
Tutun detektori: 13 qadam
Tutun detektori: Salom do'stlar, bugun tutun detektori haqida bilib olaylik. Ko'pchiligingiz savdo markazlariga borgansiz, asosan siz tutun detektori deb nomlangan qurilmani ko'rishingiz mumkin, u tutunni aniqlaydi va purkagichni yoqadi va olovni to'xtatadi. Lekin bu loyihada bu ozgina o'zgarish. o'rniga
Hozirgi tebranish detektori: 3 qadam
Hozirgi tebranish detektori: Ushbu loyihada biz kimdir sovg'ani/qutini silkitsa, signal beradigan signalli qurilma yasaymiz. Men Rojdestvo uchun pochta orqali pochta qutisiga kelganimizda, bu fikrga keldim. Unda nima borligini taxmin qilish uchun, albatta, biz ham xuddi hamma kabi silkitdik
Projeto IoT - De Fumaça detektori tizimi: 5 qadam
Projeto IoT - Fumachadagi tizim detektori: IoT -ning Android tizimidagi detektori - bu Android -dagi qoldiqlarning saqlanishini nazorat qilish. Bu mikrokontroldorlarning asosiy vazifasi
Yomg'ir detektori Arduino va yomg'ir tomchisi sensori yordamida: 8 qadam
Yomg'ir detektori Arduino va yomg'ir tomchi sensori yordamida: Bu qo'llanmada biz yomg'ir sensori yordamida yomg'irni qanday aniqlashni, signal moduli, OLED -displey va Visuino yordamida ovoz chiqarishni o'rganamiz