Мазмуну:
Video: DTMF детектору: 4 кадам
2024 Автор: John Day | [email protected]. Акыркы өзгөртүү: 2024-01-30 10:41
Обзор
Бул аппаратты санариптик сигналды иштетүү боюнча онлайн курстун тапшырмасы шыктандырды. Бул Arduino UNO менен ишке ашырылган DTMF декодери, ал үндүн режиминде телефондун клавиатурасында басылган санды аныктайт.
1 -кадам: Алгоритмди түшүнүү
DTMFде ар бир символ сүрөттөгү таблицага ылайык эки жыштык менен коддолгон.
Түзмөк микрофондун киришин жазат жана сегиз жыштыктын амплитудасын эсептейт. Максималдуу амплитудасы бар эки жыштык коддолгон символдун бир сабын жана колонкасын берет.
Маалымат алуу
Спектр анализин жүргүзүү үчүн үлгүлөрдү белгилүү бир жыштыкта кармоо керек. Буга жетүү үчүн мен ADC режимин максималдуу тактык менен колдондум (prescaler 128), ал 9615 Гц ылдамдыкта ылдамдыкты берет. Төмөндөгү код Arduino ADCди кантип конфигурациялоону көрсөтөт.
жараксыз initADC () {
// Init ADC; f = (16MHz/prescaler)/13 цикл/конверсия ADMUX = 0; // Channel sel, right-adj, AREF pin ADCSRA = _BV (ADEN) | колдонуңуз // ADC _BV (ADSC) иштетүү | // ADC баштоо _BV (ADATE) | // Авто триггер _BV (ADIE) | // Үзгүлтүк иштетүү _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Гц ADCSRB = 0; // Эркин иштөө режими DIDR0 = _BV (0); // ADC пин TIMSK0 = 0 үчүн санариптик киргизүүнү өчүрүү; // Timer0 өчүк} Жана үзгүлтүк иштетүүчү мындай ISR (ADC_vect) окшойт {uint16_t sample = ADC; sample [samplePos ++] = sample - 400; if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Буфер толгон, үзгүлтүккө учуроо}}
Спектр анализи
Үлгүлөрдү чогулткандан кийин мен 8 жыштыктын коддоочу амплитудасын эсептейм. Бул үчүн толук FFT иштетүүнүн кажети жок, ошондуктан мен Goertzelдин алгоритмин колдондум.
жараксыз гертцел (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 = (калкып чыгуу) (үлгүлөр ) + 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 үчүн Arduino] * - Чыгуу -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - Arduino: AREF -> 3.3V * [Ардуиного көрсөтүү] * - 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.6895405447370639623666666666666666666686, 0,831666666666666, 0,8316692 const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.7730104533627369, 0.7730104533627369
typedef структурасы {
char цифрасы; uint8_t индекси; } digit_t;
digit_t found_digit;
const char table [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 () {
// Init ADC; f = (16MHz/prescaler)/13 цикл/конверсия ADMUX = 0; // Channel sel, right-adj, AREF pin ADCSRA = _BV (ADEN) | колдонуңуз // ADC _BV (ADSC) иштетүү | // ADC баштоо _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 = (калкып чыгуу) (үлгүлөр ) + 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) {
float result =.0; for (uint16_t i = 0; i <len; i ++) {result+= a ; } return result / 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 {return -1; }}} return 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); if (row! = -1 && col! = -1 && avg_col> 200) {found_digit.digit = pgm_read_byte (& (table [row] [col])); found_digit.index = pgm_read_byte (& (char_indexes [катар] [col])); } else {found_digit.digit = 0; }}
жараксыз 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 sample = ADC;
үлгүлөр [samplePos ++] = үлгү - 400;
if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Буфер толгон, үзгүлтүккө учуроо}}
3 -кадам: схемалар
Төмөндөгү байланыштар түзүлүшү керек:
Микрофон Ардуиного
Чыгуу -> A0
Vcc -> 3.3V Gnd -> Gnd
AREFти 3.3Vга туташтыруу маанилүү
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 Infrared Digital Proximity Detector Java үйрөткүчү: TMD26721-бул инфрақызыл санариптик жакындык детектору, ал толугу менен жакындыкты аныктоо тутумун жана санариптик интерфейстин логикасын бир 8 пиндүү беттик монтаждоо модулунда камтыйт. тактык. А про
Түтүн детектору: 13 кадам
Түтүн детектору: Салам достор бүгүн түтүн детектору жөнүндө көрөлү Көбүңүздөр соода борборлоруна бардыңыздар, көбүнчө сиз түтүн детектору деп аталган аппаратты көрө аласыз, ал түтүндү аныктап, чачыраткычты күйгүзүп, өрттү токтотот. Бирок бул долбоордо бир аз өзгөрүү анын ордуна
Учурдагы силкинүү детектору: 3 кадам
Учурдагы титирөө детектору: Бул долбоордо биз кимдир бирөө белекти/кутуну чайкаса, сигнал бере турган түзүлүштү жасайбыз. Бул идеяны биз Рождествого почтага келгенибизде түшүндүм. Мунун ичинде эмне бар экенин билүү үчүн, албетте, биз аны ар кимге окшоп чайкадык
Projeto IoT - Система детектору De Fumaça: 5 кадам
Projeto IoT - Fumaça системасынын детектору: IntroduçãOO Android детектору Fumaça системасынын IoT коммюникесинде жана Androidде орнотулган детекторлордо да, Android системасында да карта орнотулган. Микроконтроллердин жардамы менен сиз өзүңүздү комментарийлейсиз
Arduino жана жамгыр тамчыларынын жардамы менен жамгыр детектору: 8 кадам
Жамгыр детектору Arduino жана жамгыр тамчыларынын сенсорун колдонот: Бул үйрөткүчтө жамгырдын сенсорунун жардамы менен жамгырды кантип аныктоону жана ызы -чуу модулун, OLED Display жана Visuino аркылуу үн чыгарууну үйрөнөбүз