цифровая электроника
вычислительная техника
встраиваемые системы

 

Детектор уровня звука на Arduino своими руками

Автор: Mike(admin) от 28-09-2017, 20:35

Платформа Arduino зарекомендовала себя уже во многих радиолюбительских проектах благодаря своей простоте и функциональности. С ее помощью делают системы домашней автоматизации, устройства Интернета вещей и прочие электронные приборы и системы. Кроме того, Arduino может с успехом применяться в музыкальных приложениях.


Детектор уровня звука на Arduino своими руками

Так, на основе Arduino можно самостоятельно собрать детектор уровня звука или бит-детектор для регистрации сигналов (преимущественно звуковых) определенного уровня.


Идея этого проекта заключается в использовании Arduino для обнаружения ударов (битов) в музыке на линейном выходе (например, красный и белый RCA аудио кабели). Проект довольно прост, но был бы еще проще, если бы не ограничение аналогового входа Arduino, который может принимать сигналы напряжением от 0 до 5 В. Но аудиосигнал – это сигнал переменного тока, и он может менять свое значение относительно нуля. Итак, как получить отрицательную часть волны аудиосигнала на входе Arduino? Необходимо сместить ноль на уровень 2.5 В. В итоге волна сигнала будет «ходить» выше и ниже этого нового нуля. Только так мы сможем подключиться к аналоговому входу Arduino. Схема подключения приведена на рисунке ниже.


Детектор уровня звука на Arduino своими руками

Ниже приведен код (скетч) для Arduino, который позволяет определить уровень бита в аудиосигнале, и в зависимости от этого можно сформировать какое-либо действие на выходе, например, мигание светодиода или включение реле.



#define SAMPLEPERIODUS 200

// Определение настроек и очистка битов регистров
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void setup() {
    // Настройка АЦП на 77 КГц и 10 разрядов
    sbi(ADCSRA,ADPS2);
    cbi(ADCSRA,ADPS1);
    cbi(ADCSRA,ADPS0);

    // Вывод на светодиод или реле
    pinMode(2, OUTPUT);
}

// КИХ-фильтр 20 - 200 Гц
float bassFilter(float sample) {
    static float xv[3] = {0,0,0}, yv[3] = {0,0,0};
    xv[0] = xv[1]; xv[1] = xv[2]; 
    xv[2] = (sample) / 3.f; // измените на значение близкое к 2, чтобы адаптировать силу источника аудиосигнала  
    

    yv[0] = yv[1]; yv[1] = yv[2]; 
    yv[2] = (xv[2] - xv[0])
        + (-0.7960060012f * yv[0]) + (1.7903124146f * yv[1]);
    return yv[2];
}

// КИХ-фильтр 10 Гц
float envelopeFilter(float sample) {
    static float xv[2] = {0,0}, yv[2] = {0,0};
    xv[0] = xv[1]; 
    xv[1] = sample / 50.f;
    yv[0] = yv[1]; 
    yv[1] = (xv[0] + xv[1]) + (0.9875119299f * yv[0]);
    return yv[1];
}

// КИХ-фильтр 1.7 - 3.0 Гц
float beatFilter(float sample) {
    static float xv[3] = {0,0,0}, yv[3] = {0,0,0};
    xv[0] = xv[1]; xv[1] = xv[2]; 
    xv[2] = sample / 2.7f;
    yv[0] = yv[1]; yv[1] = yv[2]; 
    yv[2] = (xv[2] - xv[0])
        + (-0.7169861741f * yv[0]) + (1.4453653501f * yv[1]);
    return yv[2];
}

void loop() {
    unsigned long time = micros(); // Используется для отслеживания скорости сигнала
    float sample, value, envelope, beat, thresh;
    unsigned char i;

    for(i = 0;;++i){
        // Считывание АЦП и центрирование на +-512
        sample = (float)analogRead(0)-503.f;

        // Фильтровать только басовый компонент
        value = bassFilter(sample);

        // Взять амплитуду сигнала и отфильтровать
        if(value < 0)value=-value;
        envelope = envelopeFilter(value);

        // Каждые 200 отсчетов (25 Гц) фильтровать огибающую 
        if(i == 200) {
                // Отфильтровать повторяющиеся басовые звуки 100 - 180 bpm
                beat = beatFilter(envelope);

                // Уровень срабатывания, порог основан на потенциометре на AN1
                thresh = 0.02f * (float)analogRead(1);

                // Если порог превышен, то включаем светодиод или реле
                if(beat > thresh) digitalWrite(2, HIGH);
                else digitalWrite(2, LOW);

                // сбрасываем счетчик
                i = 0;
        }

        // Потребляет избыточные тактовые циклы, чтобы поддерживать 5000 Гц
        for(unsigned long up = time+SAMPLEPERIODUS; time > 20 && time < up; time = micros());
    }  
}



© digitrode.ru


Теги: Arduino




Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий