38浏览
查看: 38|回复: 2

[项目] 【Arduino 动手做】MAX7219 图形音频频谱分析仪

[复制链接]
具有大量设置和功能的 Graph Spectrum Analyzer
光谱输出开启:
显示器 1602
4 个块的矩阵 8x8 (MAX7219)
WS2812 可寻址矩阵
亮度调整
色域调整(适用于 WS2812)
调整增益和杂色减少
调整动画平滑度
音量设置:
固定
来自电位计
自动
最高积分
开 关
挂起时间
坠落速度
按频率手动采样

算法
频谱分析,在输出端,我们有一个光谱波段值数组(128 个波段)
按每个波段的较低值(128 个波段)进行筛选
从 128 个通道过渡到 16 个通道,同时保持基于线性的带间值
求最大值以校正矩阵上条形的高度
将带材的净“重量”转换为模具的高度
将条带发送到矩阵
计算最高积分的位置并将其发送到 mtaritsa
顺便过滤较高的峰,从体积中校正柱的高度,等等

【Arduino 动手做】MAX7219 图形音频频谱分析仪图3

【Arduino 动手做】MAX7219 图形音频频谱分析仪图2

【Arduino 动手做】MAX7219 图形音频频谱分析仪图1

【Arduino 动手做】MAX7219 图形音频频谱分析仪图4

【Arduino 动手做】MAX7219 图形音频频谱分析仪图5

【Arduino 动手做】MAX7219 图形音频频谱分析仪图6

【Arduino 动手做】MAX7219 图形音频频谱分析仪图7

【Arduino 动手做】MAX7219 图形音频频谱分析仪图8

驴友花雕  中级技神
 楼主|

发表于 前天 07:07

【Arduino 动手做】MAX7219 图形音频频谱分析仪

项目代码

  1. // -------------------------------- НАСТРОЙКИ --------------------------------
  2. // матрица
  3. #define BRIGHTNESS 15     // яркость матрицы (0 - 15)
  4. // сигнал
  5. #define INPUT_GAIN 1.5    // коэффициент усиления входного сигнала
  6. #define LOW_PASS 35       // нижний порог чувствительности шумов (нет скачков при отсутствии звука)
  7. #define MAX_COEF 1.1      // коэффициент, который делает "максимальные" пики чуть меньше максимума, для более приятного восприятия
  8. #define NORMALIZE 0       // нормализовать пики (столбики низких и высоких частот будут одинаковой длины при одинаковой громкости) (1 вкл, 0 выкл)
  9. // анимация
  10. #define SMOOTH 0.4        // плавность движения столбиков (0 - 1)
  11. #define DELAY 4           // задержка между обновлениями матрицы (периодичность основного цикла), миллиисекунды
  12. // громкость
  13. #define DEF_GAIN 100       // максимальный порог по умолчанию (при MANUAL_GAIN или AUTO_GAIN игнорируется)
  14. #define MANUAL_GAIN 0     // ручная настройка потенциометром на громкость (1 вкл, 0 выкл)
  15. #define AUTO_GAIN 1       // автонастройка по громкости (экспериментальная функция) (1 вкл, 0 выкл)
  16. // точки максимума
  17. #define MAX_DOTS 1        // включить/выключить отрисовку точек максимума (1 вкл, 0 выкл)
  18. #define FALL_DELAY 50     // скорость падения точек максимума (задержка, миллисекунды)
  19. #define FALL_PAUSE 700    // пауза перед падением точек максимума, миллисекунды
  20. // массив тонов, расположены примерно по параболе. От 80 Гц до 16 кГц
  21. byte posOffset[33] = {
  22.   2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20, 25, 32, 36, 40, 44, 48, 52, 57, 62, 67, 72, 78, 84, 90, 96, 102, 108, 120
  23. };
  24. // -------------------------------- НАСТРОЙКИ --------------------------------
  25. // ---------------------- ПИНЫ ----------------------
  26. // для увеличения точности уменьшаем опорное напряжение,
  27. // выставив EXTERNAL и подключив Aref к выходу 3.3V на плате через делитель
  28. // GND ---[10-20 кОм] --- REF --- [10 кОм] --- 3V3
  29. // Матрица: CS -> 10 / CLK -> 13 / DIN -> 11
  30. #define AUDIO_IN 0         // пин, куда подключен звук
  31. #define POT_PIN 7          // пин потенциометра настройки (если нужен MANUAL_GAIN)
  32. // ---------------------- ПИНЫ ----------------------
  33. // --------------- ДЛЯ РАЗРАБОТЧИКОВ ---------------
  34. #define MATR_NUM 4        // количество матриц последовательно
  35. #define FHT_N 256         // ширина спектра х2
  36. #define LOG_OUT 1
  37. #include <FHT.h>           // преобразование Хартли
  38. #include <SPI.h>
  39. #include <Adafruit_GFX.h>
  40. #include <Max72xxPanel.h>
  41. Max72xxPanel matrix = Max72xxPanel(10, 4, 1);
  42. #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  43. #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  44. int gain = DEF_GAIN;   // усиление по умолчанию
  45. unsigned long gainTimer, fallTimer;
  46. byte maxValue;
  47. float k = 0.05, maxValue_f = 0.0;
  48. int maxLevel[32];
  49. byte posLevel_old[32];
  50. unsigned long timeLevel[32], mainDelay;
  51. boolean fallFlag;
  52. // --------------- ДЛЯ РАЗРАБОТЧИКОВ ---------------
  53. void setup() {
  54.   // поднимаем частоту опроса аналогового порта до 38.4 кГц, по теореме
  55.   // Котельникова (Найквиста) максимальная частота дискретизации будет 19 кГц
  56.   // http://yaab-arduino.blogspot.ru/2015/02/fast-sampling-from-analog-input.html
  57.   sbi(ADCSRA, ADPS2);
  58.   cbi(ADCSRA, ADPS1);
  59.   sbi(ADCSRA, ADPS0);
  60.   analogReference(EXTERNAL);
  61.   Serial.begin(9600);
  62.   matrix.setIntensity(BRIGHTNESS);
  63.   for (byte i = 0; i < MATR_NUM; i++) {
  64.     // матрицы расположены криво, здесь поворачиваем
  65.     matrix.setRotation(i, 1);
  66.   }
  67.   matrix.fillScreen(LOW);
  68.   matrix.write();
  69. }
  70. void loop() {
  71.   if (millis() - mainDelay > DELAY - 2) {     // итерация главного цикла
  72.     mainDelay = millis();
  73.     analyzeAudio();   // функция FHT, забивает массив fht_log_out[] величинами по спектру
  74.     for (int i = 0; i < 128; i ++) {
  75.       // вот здесь сразу фильтруем весь спектр по минимальному LOW_PASS
  76.       if (fht_log_out[i] < LOW_PASS) fht_log_out[i] = 0;
  77.       // усиляем сигнал
  78.       fht_log_out[i] = (float)fht_log_out[i] * INPUT_GAIN;
  79.       // уменьшаем громкость высоких частот (пропорционально частоте) если включено
  80.       if (NORMALIZE) fht_log_out[i] = (float)fht_log_out[i] / ((float)1 + (float)i / 128);
  81.     }
  82.     maxValue = 0;
  83.     matrix.fillScreen(LOW);
  84.     delay(2);///////////////////СУКАДИЛЕЙ//////БЕЗ НЕГО МАТРИЦА НАЧИНАЕТ КОСОЖОПИТЬ///////////
  85.     for (byte pos = 0; pos < MATR_NUM * 8; pos++) {    // для кажого столбца матрицы
  86.       int posLevel = fht_log_out[posOffset[pos]];
  87.       byte linesBetween;
  88.       if (pos > 0 && pos < MATR_NUM * 8) {
  89.         linesBetween = posOffset[pos] - posOffset[pos - 1];
  90.         for (byte i = 0; i < linesBetween; i++) {  // от предыдущей полосы до текущей
  91.           posLevel += (float) ((float)i / linesBetween) * fht_log_out[posOffset[pos] - linesBetween + i];
  92.         }
  93.         linesBetween = posOffset[pos + 1] - posOffset[pos];
  94.         for (byte i = 0; i < linesBetween; i++) {  // от предыдущей полосы до текущей
  95.           posLevel += (float) ((float)i / linesBetween) * fht_log_out[posOffset[pos] + linesBetween - i];
  96.         }
  97.       }
  98.       // найти максимум из пачки тонов
  99.       if (posLevel > maxValue) maxValue = posLevel;
  100.       // фильтрация длины столбиков, для их плавного движения
  101.       posLevel = posLevel_old[pos] * SMOOTH + posLevel * (1 - SMOOTH);
  102.       posLevel_old[pos] = posLevel;
  103.       // преобразовать значение величины спектра в диапазон 0..7 с учётом настроек
  104.       posLevel = map(posLevel, LOW_PASS, gain, 0, 7);
  105.       posLevel = constrain(posLevel, 0, 7);
  106.       // если столбик больше нуля, то начать линию с координаты (pos, 7) и рисовать в (pos, 7 - значение)
  107.       if (posLevel > 0) matrix.drawLine(pos, 7, pos, 7 - posLevel, HIGH);
  108.       if (posLevel > 0 && posLevel > maxLevel[pos]) {    // если для этой полосы есть максимум, который больше предыдущего
  109.         maxLevel[pos] = posLevel;                        // запомнить его
  110.         timeLevel[pos] = millis();                       // запомнить время
  111.       }
  112.       // если точка максимума выше нуля (или равна ему) - включить пиксель
  113.       if (MAX_DOTS && maxLevel[pos] >= 0) matrix.drawPixel(pos, 7 - maxLevel[pos], HIGH);
  114.       if (fallFlag) {                                           // если падаем на шаг
  115.         if ((long)millis() - timeLevel[pos] > FALL_PAUSE) {     // если максимум держался на своей высоте дольше FALL_PAUSE
  116.           if (maxLevel[pos] >= 0) maxLevel[pos]--;              // уменьшить высоту точки на 1
  117.           // внимание! Принимает минимальное значение -1 !
  118.         }
  119.       }
  120.     }
  121.     matrix.write();  // отправить на матрицу
  122.     fallFlag = 0;                                 // сбросить флаг падения
  123.     if (millis() - fallTimer > FALL_DELAY) {      // если настало время следующего падения
  124.       fallFlag = 1;                               // поднять флаг
  125.       fallTimer = millis();
  126.     }
  127.     // если разрешена ручная настройка уровня громкости
  128.     if (MANUAL_GAIN) gain = map(analogRead(POT_PIN), 0, 1023, 0, 150);
  129.     // если разрешена авто настройка уровня громкости
  130.     if (AUTO_GAIN) {
  131.       if (millis() - gainTimer > 10) {      // каждые 10 мс
  132.         maxValue_f = maxValue * k + maxValue_f * (1 - k);
  133.         // если максимальное значение больше порога, взять его как максимум для отображения
  134.         if (maxValue_f > LOW_PASS) gain = (float) MAX_COEF * maxValue_f;
  135.         // если нет, то взять порог побольше, чтобы шумы вообще не проходили
  136.         else gain = 100;
  137.         gainTimer = millis();
  138.       }
  139.     }
  140.   }
  141. }
  142. void analyzeAudio() {
  143.   for (int i = 0 ; i < FHT_N ; i++) {
  144.     int sample = analogRead(AUDIO_IN);
  145.     fht_input[i] = sample; // put real data into bins
  146.   }
  147.   fht_window();  // window the data for better frequency response
  148.   fht_reorder(); // reorder the data before doing the fht
  149.   fht_run();     // process the data in the fht
  150.   fht_mag_log(); // take the output of the fht
  151. }
  152. /*
  153.    Алгоритм работы:
  154.    Анализ спектра, на выходе имеем массив величин полос спектра (128 полос)
  155.    Фильтрация по нижним значениям для каждой полосы (128 полос)
  156.    Переход от 128 полос к 16 полосам с сохранением межполосных значений по линейной зависимости
  157.    Поиск максимумов для коррекции высоты столбиков на матрице
  158.    Перевод чистого "веса" полосы к высоте матрицы
  159.    Отправка полос на матрицу
  160.    Расчёт позиций точек максимума и отправка их на мтарицу
  161.    Мимоходом фильтрация верхних пиков, коррекция высоты столбиков от громкости и прочее
  162. */
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 07:11

【Arduino 动手做】MAX7219 图形音频频谱分析仪

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail