Я не могу установить правильную конфигурацию звукового модуля

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

Я использовал голосовой модуль:

Голосовой модуль

Я использовал следующий код:

#include <FastLED.h>

/** BASIC CONFIGURATION  **/

//Количество светодиодов в сетапе
#define NUM_LEDS 10
//Пин, который управляет светодиодами
#define LED_PIN 6
//Пин, с которого мы считываем значения датчиков, формирует
#define ANALOG_READ 0

// Подтверждено минимальное значение микрофона и максимальное значение
#define MIC_LOW 0.0
#define MIC_HIGH 737.0
/** Other macros */
//Сколько предыдущих значений датчика влияет на среднее значение?
#define AVGLEN 15
//Сколько предыдущих значений датчика определяет, находимся ли мы на пике/ВЫСОКОМ (например, в песне)
#define LONG_SECTOR 5

//Мневмоника
#define HIGH  3
#define NORMAL 2

//Как долго мы сохраняем "текущий средний" звук, перед перезапуском измерения
#define MSECS 2000
#define CYCLES MSECS / DELAY

/*Sometimes readings are wrong or strange. How much is a reading allowed
to deviate from the average to not be discarded? **/
#define DEV_THRESH 0.8

// Задержка цикла Arduino
#define DELAY 1

float fscale( float originalMin, float originalMax, float newBegin, float newEnd, float inputValue, float curve);
void insert(int val, int *avgs, int len);
int compute_average(int *avgs, int len);
void visualize_music();

//Сколько светодиодов отображать
int curshow = NUM_LEDS;

/*Not really used yet. Thought to be able to switch between sound reactive
mode, and general gradient pulsing/static color*/
int mode = 0;

//Отображение разных цветов в зависимости от режима.
int songmode = NORMAL;

//Среднее измерение звука за последние ЦИКЛЫ
unsigned long song_avg;

//Количество итераций с момента сброса song_avg
int iter = 0;

//Скорость, когда светодиоды становятся черными, если не загораются снова
float fade_scale = 1.2;

//Светодиодная матрица
CRGB leds[NUM_LEDS];

/*Short sound avg used to "normalize" the input values.
We use the short average instead of using the sensor input directly */
int avgs[AVGLEN] = {-1};

// дольше звук в среднем
int long_avg[LONG_SECTOR] = {-1};

// Отслеживание того, как часто и как долго мы используем определенный режим
struct time_keeping {
  unsigned long times_start;
  short times;
};

//На сколько увеличивать или уменьшать каждый цвет в каждом цикле
struct color {
  int r;
  int g;
  int b;
};

struct time_keeping high;
struct color Color; 

void setup() {
  Serial.begin(9600);
  //Установите все источники света, чтобы убедиться, что все они работают должным образом
  FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
  for (int i = 0; i < NUM_LEDS; i++) 
    leds[i] = CRGB(0, 0, 255);
  FastLED.show(); 
  delay(1000);  

  // загрузите среднее значение с некоторыми низкими значениями
  for (int i = 0; i < AVGLEN; i++) {  
    insert(250, avgs, AVGLEN);
  }

  //Исходные значения
  high.times = 0;
  high.times_start = millis();
  Color.r = 0;  
  Color.g = 0;
  Color.b = 1;
}

/*With this we can change the mode if we want to implement a general 
lamp feature, with for instance general pulsing. Maybe if the
sound is low for a while? */
void loop() {
  switch(mode) {
    case 0:
      visualize_music();
      break;
    default:
      break;
  }
    delay(DELAY);       // задержка между чтениями для стабильности
}


/**Funtion to check if the lamp should either enter a HIGH mode,
or revert to NORMAL if already in HIGH. If the sensors report values
that are higher than 1.1 times the average values, and this has happened
more than 30 times the last few milliseconds, it will enter HIGH mode. 
TODO: Not very well written, remove hardcoded values, and make it more
reusable and configurable.  */
void check_high(int avg) {
  if (avg > (song_avg/iter * 1.1))  {
    if (high.times != 0) {
      if (millis() - high.times_start > 200.0) {
        high.times = 0;
        songmode = NORMAL;
      } else {
        high.times_start = millis();  
        high.times++; 
      }
    } else {
      high.times++;
      high.times_start = millis();

    }
  }
  if (high.times > 30 && millis() - high.times_start < 50.0)
    songmode = HIGH;
  else if (millis() - high.times_start > 200) {
    high.times = 0;
    songmode = NORMAL;
  }
}

//Основная функция для визуализации звуков в лампе
void visualize_music() {
  int sensor_value, mapped, avg, longavg;

  //Фактическое значение датчика
  sensor_value = analogRead(ANALOG_READ);

  //Если 0, сразу отбрасываем. Вероятно, это неправильно и экономит процессор.
  if (sensor_value == 0)
    return;

  // Отбрасываем показания, которые слишком сильно отклоняются от прошлого среднего.
  mapped = (float)fscale(MIC_LOW, MIC_HIGH, MIC_LOW, (float)MIC_HIGH, (float)sensor_value, 2.0);
  avg = compute_average(avgs, AVGLEN);

  if (((avg - mapped) > avg*DEV_THRESH)) //|| ((среднее - сопоставлено) < -avg*DEV_THRESH))
    return;

  // Вставить новое среднее значение. ценности
  insert(mapped, avgs, AVGLEN); 
  insert(avg, long_avg, LONG_SECTOR); 

  // Вычисление значения датчика "среднее значение песни"
  song_avg += avg;
  iter++;
  if (iter > CYCLES) {  
    song_avg = song_avg / iter;
    iter = 1;
  }

  longavg = compute_average(long_avg, LONG_SECTOR);

  // Проверяем, вошли ли мы в режим HIGH
  check_high(longavg);  

  if (songmode == HIGH) {
    fade_scale = 3;
    Color.r =  8;
    Color.g = 1;
    Color.b = -2;
  }
  else if (songmode == NORMAL) {
    fade_scale = 3;
    Color.r = -1;
    Color.b = 6;
    Color.g = -2;
  }

  //Решаем, сколько светодиодов будет гореть
  curshow = fscale(MIC_LOW, MIC_HIGH, 0.0, (float)NUM_LEDS, (float)avg, -1);

  /*Set the different leds. Control for too high and too low values.
          Fun thing to try: Dont account for overflow in one direction, 
    some interesting light effects appear! */
  for (int i = 0; i < NUM_LEDS; i++) 
    //Светодиоды, которые мы хотим показать
    if (i < curshow) {
      if (leds[i].r + Color.r > 255)
        leds[i].r = 255;
      else if (leds[i].r + Color.r < 0)
        leds[i].r = 0;
      else
        leds[i].r = leds[i].r + Color.r;

      if (leds[i].g + Color.g > 255)
        leds[i].g = 255;
      else if (leds[i].g + Color.g < 0)
        leds[i].g = 0;
      else 
        leds[i].g = leds[i].g + Color.g;

      if (leds[i].b + Color.b > 255)
        leds[i].b = 255;
      else if (leds[i].b + Color.b < 0)
        leds[i].b = 0;
      else 
        leds[i].b = leds[i].b + Color.b;  

    //Все остальные светодиоды начинают свое постепенное исчезновение в полной темноте
    } else {
      leds[i] = CRGB(leds[i].r/fade_scale, leds[i].g/fade_scale, leds[i].b/fade_scale);
    }
  FastLED.show(); 
}
//Вычислить среднее значение массива int, учитывая начальный указатель и длину
int compute_average(int *avgs, int len) {
  int sum = 0;
  for (int i = 0; i < len; i++)
    sum += avgs[i];

  return (int)(sum / len);

}

// Вставляем значение в массив и сдвигаем его вниз удаляя
//первое значение, если массив уже заполнен
void insert(int val, int *avgs, int len) {
  for (int i = 0; i < len; i++) {
    if (avgs[i] == -1) {
      avgs[i] = val;
      return;
    }  
  }

  for (int i = 1; i < len; i++) {
    avgs[i - 1] = avgs[i];
  }
  avgs[len - 1] = val;
}

//Функция импортирована с сайта arduino.
//В основном карта, но с кривой в масштабе (может быть неравномерной).
float fscale( float originalMin, float originalMax, float newBegin, float
    newEnd, float inputValue, float curve){

  float OriginalRange = 0;
  float NewRange = 0;
  float zeroRefCurVal = 0;
  float normalizedCurVal = 0;
  float rangedValue = 0;
  boolean invFlag = 0;


  // параметр кривой состояния
  // ограничение диапазона

  if (curve > 10) curve = 10;
  if (curve < -10) curve = -10;

  curve = (curve * -.1) ; // - инвертировать и масштабировать - это кажется более интуитивным - положительные числа придают больший вес верхнему пределу на выходе
  curve = pow(10, curve); // преобразовать линейную шкалу в логарифмическую экспоненту для другой функции pow

  // Проверка на выход за пределы диапазона inputValues
  if (inputValue < originalMin) {
    inputValue = originalMin;
  }
  if (inputValue > originalMax) {
    inputValue = originalMax;
  }

  // Нулевая ссылка на значения
  OriginalRange = originalMax - originalMin;

  if (newEnd > newBegin){ 
    NewRange = newEnd - newBegin;
  }
  else
  {
    NewRange = newBegin - newEnd; 
    invFlag = 1;
  }

  zeroRefCurVal = inputValue - originalMin;
  normalizedCurVal  =  zeroRefCurVal / OriginalRange;   // нормализовать до 0-1 с плавающей запятой

  // Проверить исходное значение Min > originalMax - математика для всех других случаев, т.е. отрицательные числа, похоже, работают нормально
  if (originalMin > originalMax ) {
    return 0;
  }

  if (invFlag == 0){
    rangedValue =  (pow(normalizedCurVal, curve) * NewRange) + newBegin;

  }
  else     // инвертируем диапазоны
  {   
    rangedValue =  newBegin - (pow(normalizedCurVal, curve) * NewRange); 
  }

  return rangedValue;
}

, 👍0

Обсуждение

На странице продукта указано, что модуль обеспечивает «выходной сигнал» и основан на LM393 (который является компаратором). Ваш код, похоже, ожидает аналоговое значение., @Edgar Bonet


1 ответ


1

Потенциометр предназначен только для изменения порогового значения, при котором цифровой выходной контакт будет выдавать ВЫСОКОЕ или НИЗКОЕ значение. Контакт аналогового выхода не должен изменяться потенциометром.

Я думаю, что ваш звуковой модуль может не подойти для вашего проекта, если вы работаете со слабыми аудиосигналами. Он больше подходит для таких проектов, как детекторы хлопков и тому подобное. Возможно, вы сможете использовать этот датчик для обнаружения более слабых сигналов, если поместите аудиоусилитель после контакта аналогового выхода или измените значение аналогового эталона на Arduino.

,

Можете предложить мне звуковой модуль, идеально подходящий для этого проекта.., @Atom Warex