Мазмұны:
Бейне: DTMF детекторы: 4 қадам
2024 Автор: John Day | [email protected]. Соңғы өзгертілген: 2024-01-30 10:26
Шолу
Мен бұл құрылғыны цифрлық сигналды өңдеудің онлайн курсы бойынша үй тапсырмасынан шабыттандырдым. Бұл Arduino UNO көмегімен енгізілген DTMF декодері, ол дыбыс режимінде телефон пернетақтасында басылған санды анықтайды.
1 -қадам: Алгоритмді түсіну
DTMF -те әр белгі суреттегі кестеге сәйкес екі жиілікпен кодталған.
Құрылғы микрофоннан кірісті алады және сегіз жиіліктің амплитудасын есептейді. Максималды амплитудасы бар екі жиілік кодталған символдың жолын және бағанын береді.
Деректерді алу
Спектрлік талдауды жүргізу үшін белгілі бір жиілікте үлгілерді алу керек. Бұған қол жеткізу үшін мен ADC режимін максималды дәлдікпен қолдандым (128-прескалор), ол 9615 Гц іріктеу жиілігін береді. Төмендегі код Arduino ADC конфигурациясын көрсетеді.
жарамсыз initADC () {
// ADC қосу; f = (16MHz/prescaler)/13 цикл/ADMUX = 0 түрлендіру; // Channel sel, right-adj, AREF pin ADCSRA = _BV (ADEN) | қолданыңыз // ADC _BV (ADSC) қосу | // ADC start _BV (ADATE) | // Автоматты триггер _BV (ADIE) | // Үзілісті қосу _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Гц ADCSRB = 0; // Еркін жұмыс режимі DIDR0 = _BV (0); // ADC пині үшін сандық кірісті өшіру TIMSK0 = 0; // Таймер0 өшірулі} Ал үзіліс өңдегіші келесідей көрінеді ISR (ADC_vect) {uint16_t sample = ADC; sample [samplePos ++] = үлгі - 400; if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Буфер толды, үзіліс өшірілді}}
Спектрлік талдау
Үлгілерді жинағаннан кейін мен таңбаларды кодтайтын 8 жиіліктің амплитудасын есептеймін. Бұл үшін толық FFT іске қосудың қажеті жоқ, сондықтан мен Гертцель алгоритмін қолдандым.
жарамсыз герцель (uint8_t *үлгілері, float *спектрі) {
өзгермелі v_0, v_1, v_2; float re, 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])); float a = 2. * c; v_0 = v_1 = v_2 = 0; үшін (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (үлгілер ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); спектр [k] = амп; }}
2 -қадам: Кодекс
Жоғарыдағы суретте максималды амплитудасы 697 Гц және 1477 Гц жиіліктеріне сәйкес келетін 3 -ші цифрды кодтау мысалы көрсетілген.
Толық эскиз келесідей көрінеді
/** * Қосылымдар: * [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 */ #include #include
#қосу
#CS_PIN 9 анықтаңыз
#анықтаңыз N 256
#анықтау IX_LEN 8 #анықтау ШЕКТІ 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]
// 9615 Гц 256 сынамалар үшін есептеледі const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370639666666666666666666666666666666868 const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.7730104533627459
typedef құрылымы {
таңбалық сан; uint8_t индексі; } digit_t;
цифр_t анықталды_сандар;
const 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} };
байт қарпі [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} // *};
жарамсыз initADC () {
// ADC қосу; f = (16MHz/prescaler)/13 цикл/конверсия ADMUX = 0; // Channel sel, right-adj, AREF pin ADCSRA = _BV (ADEN) | қолданыңыз // ADC қосу _BV (ADSC) | // ADC start _BV (ADATE) | // Автоматты триггер _BV (ADIE) | // Үзілісті қосу _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Гц ADCSRB = 0; // Еркін жұмыс режимі DIDR0 = _BV (0); // ADC пині үшін сандық кірісті өшіру TIMSK0 = 0; // Таймер0 өшірулі}
жарамсыз герцель (uint8_t *үлгілері, float *спектрі) {
өзгермелі v_0, v_1, v_2; float re, 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])); float a = 2. * c; v_0 = v_1 = v_2 = 0; үшін (uint16_t i = 0; i <N; i ++) {v_0 = v_1; v_1 = v_2; v_2 = (float) (үлгілер ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); спектр [k] = амп; }}
орташа өзгермелі (float *a, uint16_t len) {
өзгермелі нәтиже =.0; for (uint16_t i = 0; i <len; i ++) {нәтиже+= a ; } нәтижені қайтару / len; }
int8_t get_single_index_above_threshold (float *a, uint16_t len, float табалдырығы) {
if (шекті <THRESHOLD) {қайтару -1; } int8_t ix = -1; for (uint16_t i = 0; i шегі) {if (ix == -1) {ix = i; } else {қайтару -1; }}} ix қайтару; }
void detect_digit (float *спектрі) {
float avg_row = avg (спектр, 4); float avg_col = avg (& спектр [4], 4); int8_t row = get_single_index_above_threshold (спектр, 4, avg_row); int8_t col = get_single_index_above_threshold (& спектр [4], 4, avg_col); егер (жол! = -1 && col! = -1 && avg_col> 200) {found_digit.digit = pgm_read_byte (& (кесте [қатар] [col])); found_digit.index = pgm_read_byte (& (char_indexes [қатар] [col])); } басқа {found_digit.digit = 0; }}
void drawSprite (байт* спрайт) {
// Маска спрайт жолының байт маскасынан баған битін алу үшін қолданылады = B10000000; for (int iy = 0; iy <8; iy ++) {for (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & mask));
// масканы бір пиксельге оңға жылжытыңыз
маска = маска >> 1; }
// баған маскасын қалпына келтіру
маска = B10000000; }}
жарамсыз орнату () {
cli (); initADC (); sei ();
Serial.begin (115200);
lmd.setEnabled (шын); lmd.setIntensity (2); lmd.clear (); lmd.display ();
found_digit.digit = 0;
}
белгісіз ұзын z = 0;
void loop () {
while (ADCSRA & _BV (ADIE)); // Аудиториялық іріктеудің тоқтауы аяқталғанша күтіңіз (үлгілер, спектр); detect_digit (спектр);
if (found_digit.digit! = 0) {
drawSprite (қаріп [detect_digit.index]); lmd.display (); } if (z % 5 == 0) {for (int i = 0; i <IX_LEN; i ++) {Serial.print (спектр ); Serial.print («\ t»); } Serial.println (); Serial.println ((int) detect_digit.digit); } z ++;
samplePos = 0;
ADCSRA | = _BV (ADIE); // іріктеу үзілісін жалғастыру
}
ISR (ADC_vect) {
uint16_t үлгі = ADC;
үлгілер [samplePos ++] = үлгі - 400;
if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Буфер толды, үзіліс өшірілді}}
3 -қадам: Схемалар
Келесі байланыстар жасалуы керек:
Ардуиноға микрофон
Шығу -> A0
Vcc -> 3.3V Gnd -> Gnd
AREF -ті 3.3 В -ке қосу маңызды
Arduino дисплейі
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
4 -қадам: Қорытынды
Бұл жерде нені жақсартуға болады? Мен N = 256 үлгілерін 9615 Гц жылдамдықта қолдандым, оның спектрінің ағуы бар, егер N = 205 және жылдамдығы 8000 Гц болса, онда қалаған жиіліктер дискретизация торымен сәйкес келеді. Ол үшін ADC таймердің толып кету режимінде қолданылуы керек.
Ұсынылған:
Raspberry Pi - TMD26721 инфрақызыл сандық жақындық детекторы Java оқулығы: 4 қадам
Raspberry Pi-TMD26721 инфрақызыл сандық жақындық детекторы Java оқулығы: TMD26721-инфрақызыл цифрлық жақындық детекторы, ол жақындықты анықтаудың толық жүйесін және бір 8 істікшелі беттік монтаждық модульде цифрлық интерфейс логикасын қамтамасыз етеді. дәлдік. Кәсіби
Су деңгейінің детекторы: 7 қадам
Су деңгейінің детекторы: ультрадыбыстық сенсор радар жүйесі сияқты жұмыс істейді. Ультрадыбыстық сенсор электр энергиясын акустикалық толқынға айналдыра алады және керісінше. Әйгілі HC SR04 ультрадыбыстық сенсоры 40 кГц жиіліктегі ультрадыбыстық толқындарды шығарады
Түтін детекторы: 13 қадам
Түтін детекторы: Сәлем достар бүгін түтін детекторы туралы білейік орнына
Қазіргі діріл детекторы: 3 қадам
Қазіргі діріл детекторы: Бұл жобада біз біреу сыйлықты/қорапты шайқаса, дабыл беретін құрылғы жасаймыз. Мен Рождествоға поштаға пакет алған кезде мен бұл идеяны алдым. Ішінде не бар екенін білуге тырысу үшін, әрине, біз оны басқалар сияқты сілкіндірдік
Projeto IoT - De Fumaça детекторы: 5 қадам
Projeto IoT - Fumaça детекторы жүйесі: Android жүйесінде детектордың кіріспесі - бұл IoT -дің рұқсаты бар, ол Android -тің сақталуын бақылауды қажет етеді. Микроконтроллермен байланыс орнатыңыз