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

 

Детектор уровня звука на 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



   Благодарим Вас за интерес к информационному проекту digitrode.ru.
   Если Вы хотите, чтобы интересные и полезные материалы выходили чаще, и было меньше рекламы,
   Вы можее поддержать наш проект, пожертвовав любую сумму на его развитие.


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

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

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