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

[项目] 【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具

[复制链接]
使用 Adafruit、SparkFun、Arduino 和 ProtoStax 制作优美的音乐!使用 Arduino 创建 RGB 矩阵音频可视化工具。

在本文中,我解释了如何使用 Arduino、RGB LED 矩阵扩展板和音频频谱分析仪扩展板构建 RGB LED 矩阵音频可视化器,然后将其放入外壳中,这样您就可以拥有一个完成的项目,您可以通过音乐系统显示该项目,为您的音乐进行精彩的灯光秀!

对于音频频谱分析,我使用 SparkFun 的频谱屏蔽,它使用两个 MSGEQ7 图形均衡器显示滤波器,将立体声音频输入分成 7 个频段(每个通道),并使用 Arduino 上的 ADC 读取每个频段的幅度。它带有 Arduino 示例草图以开始使用。

对于 RGB LED 矩阵,我使用 Adafruit 的 NeoPixel Shield for Arduino,它由 40 个 RGB NeoPixel(Adafruit 的 WS2812 光源术语)组成。红色、绿色和蓝色 LED 与驱动芯片一起集成到一个通过单线控制的微型表面贴装封装中。它们可以单独使用,链接成更长的字符串或组装成更有趣的外形尺寸。就盾牌而言,它们被锁在一起。Shield 还附带 Adafruit_NeoMatrix 库,可简化对 RGB LED 矩阵的访问和 LED 控制。

最后是外壳。你们中的一些人可能知道,我创建了一个新的可堆叠模块化外壳系统,称为 ProtoStax。这是我不得不抓挠的个人痒处——我想要一个外壳,它支持原型设计的不同阶段,在开始时提供保护和开放通道,能够稍后添加侧壁和顶部,但也能够并排堆叠多个单元或一个重叠, 从而能够根据原型设计需求以及添加其他电路板和组件进行扩展。

在这个例子中,我将 ProtoStax 用于 Arduino,这是一个用于 Arduino 的透明亚克力外壳——它既适合 Uno/Leonardo 封装,也适合更大的 Mega/Due 封装——它也是可堆叠和模块化的,并且有舒适的空间容纳两个 Shield(有一些细微的修改,我将概述)。它清晰坚固,还配有橡胶脚垫,可稍微抬高它并保护您的桌子表面,因此您可以将音频可视化工具及其灯光秀与音乐系统一起展示!

第 1 步 - 将 Arduino 安装到外壳底板上
让我们首先将 Arduino(在我们的示例中为 Uno)安装到外壳的底板上。这为它提供了保护,同时提供对它的完全开放访问,以配置和设置 Arduino 并使用它。当您准备关闭它时, 添加侧壁和顶板并用螺钉固定所有东西很容易。

将 Arduino 安装到底板上,并添加支脚和其他硬件以在平台配置中准备外壳。请参阅幻灯片中的以下步骤 - 每张图片的标题都有编号,并为每个步骤提供了额外的说明。

第 2 步 - 为 Arduino 准备 SparkFun Spectrum Shield
SparkFun Spectrum Shield 不附带接头。对我们来说幸运的是,Adafruit NeoPixel Shield for Arduino 配备了堆叠接头和普通接头。由于我希望 NeoPixel Shield 位于顶部,因此我想使用它使用普通接头,以便它齐平,这样堆叠接头就可以与 Spectrum Shield 一起使用,这正是我想要的!
然而,带有堆叠接头的 Spectrum Shield 并不紧密贴合 - Arduino Uno 上的 USB 和电源端口会妨碍,如图所示。


第 3 步 - 将适用于 Arduino 的 Adafruit NeoPixel 扩展板插入 Spectrum Shield 的堆叠接头
Adafruit NeoPixel Shield 位于 Spectrum Shield 之上。您首先需要焊接常规接头(随附)。我还焊接了它附带的端子连接器,尽管在这个例子中,我使用 Arduino 为其供电,因为所有 LED 不会同时打开,因此功耗在 Arduino 可以提供的范围内。
来自 Adafruit 的 NeoPixel Shield for Arduino 页面的消息:
为了便于启动,LED 默认由 5V 板载 Arduino 电源供电。只要你没有点亮所有像素全功率白色,那应该没问题。如果您想使用外部电源为屏蔽板供电,请焊接随附的接线端子(专业提示:将其放在电路板底部,这样它就不会粘起来)连接到外部 4-6VDC 电源 - 该电源还将为 Arduino 和屏蔽供电。如果您想使用接线端子为屏蔽层供电,但仅将 Arduino 本身保持在直流或 USB 电源上,请将接线端子右侧的焊料跳线中心切割。外部输入端有一个极性保护 FET,以防您将电源向后接线(我们永远不会这样做,它是,嗯,我们的一个朋友,是的,就是这样!

第 4 步 - 演示代码
让我们看一下演示代码,看看它在做什么。为此,我们可以将其分为两个主要部分:
• 频谱分析和保存结果
• 将其转换为 8x5 NeoPixel 矩阵的显示/配色方案。
您可以在此处快速参考演示代码:
https://github.com/protostax/Pro ... Visualizer_Demo.ino
频谱分析
您可以参考 Spectrum Shield 连接指南,了解有关 Spectrum Shield 的更多信息。我在这里总结了信息。
通过将数字序列写入频谱屏蔽的STROBE和RESET引脚,您可以初始化屏蔽使用的MSGEQ7芯片。然后,您可以继续读取频谱被分割成的 7 个不同频段中每个频段的幅度。读取每个频段,然后脉冲 STROBE 引脚以启动下一个频段的读取。这些值存储在立体声输入的两个通道的Frequencies_One[7]和Frequencies_Two[7]中。使用Arduino的10位ADC读取这些值,因此输出值可以是0 - 1023 - 它们提供了每个频段幅度的表示。

频谱的 7 个频段是:
• 63赫兹
• 160赫兹
• 400赫兹
• 1kHz
• 2.5kHz
• 6.25kHz
• 16千赫兹
我将它们分为 3 个范围 - BASS、MID_RANGE 和 TREBLE。典型的低音范围为 60 至 250 Hz,因此前两个频段在低音范围内。中频频率通常为 500 Hz 至 2 kHz,因此我将接下来的 3 个频段分为 MID_RANGE。我将剩余的 2 个频段归入 TREBLE。
[注意:我还注意到每个波段的最大读数进入一个单独的变量。这可能可用于自动将读数缩放到 RGB 矩阵列所表示的水平 - 这在输入信号较低的情况下很有用 - 否则在这种情况下只有极少数 RGB 矩阵会亮起。]
RGB 矩阵
您可以参考 Adafruit NeoPixel Überguide,了解有关 NeoPixel Shield 和 NeoPixel 的其他信息。我在这里总结了与我们的使用有关的信息。
我将尝试澄清的要点是 NeoPixel Shield 的方向和方向以及坐标系的编号,一开始我发现有点令人困惑。Überguide 解释了它,但我想我可以让它变得更容易一些。
首先要注意的是,在坐标系中,[0, 0] 始终指的是左上角,无论方向如何。
接下来是注意您感兴趣的任何方向的 WIDTH,然后是 HEIGHT(即 5 x 8 与 8 x 5,在我们的 Shield 的情况下)
第三是注意物理 LED #0 的位置(由可爱的 Adafruit 徽标标记)。TOP-RIGHT、TOP-LEFT、BOTTOM-LEFT 和 BOTTOM-RIGHT 视情况而定。还要注意物理 LED 进展的方向。我们的板中的布局是渐进式的(一行结束后的下一个物理 LED 从下一行的开头开始,如黄线所示)。当宽度较宽(水平方向)(如短绿色箭头所示)时,行进的方向沿着行,宽度较窄(垂直方向)的列(同样,如短绿色箭头所示)。

最后 - 更进一步
这里有一些想法可以进一步推动该项目的发展!
1. 目前,音频电缆(输入和输出)已插入外壳中的频谱屏蔽,因此您将拥有连接这些电线并悬挂在外面的外壳。相反,您可以在 Spectrum Shield 立体声插孔附近的侧壁上添加几个面板安装立体声插孔(列在使用的“东西”列表中),然后焊接一根带有 3.5 毫米公立体声音频插孔的音频电缆到每个插孔上,然后将它们插入 Spectrum Shield 的音频插孔。在这种情况下,您的外壳变得非常整洁,并且所有接线都是独立的,外壳上只有音频插孔供外部系统插入。
2. 您可以为您的 Audio Visualizer 添加更多甚至更多的灯光方案 - 不同的颜色范围、不同的图案。
3. 添加使用串行输入启用/禁用频率范围的选项 - 目前只能更改配色方案,但不能更改要显示的频率范围。
4. 添加一个开关以在不同配色方案之间切换,而不是使用串行输入。修改外壳,在其中一个长侧壁上添加一个孔,以容纳面板安装的瞬时按钮开关(列在使用的“事物”列表中)。
5. 添加第二个开关以在显示的不同频率范围(BASS、MID_RANGE、TREBLE、ALL)之间切换,并将该开关安装到外壳的侧壁上。
6. 因为外壳是由亚克力制成的,所以你可以在上面使用一些蓝色的油漆胶带来保护表面,并用钻头在必要的一侧钻一个孔,以安装面板安装立体声插孔和/或开关。建议使用阶梯钻,或从较小的孔开始,然后扩大孔,直到达到您想要的尺寸。列出的立体声插孔需要一个 5/16 英寸的安装孔,开关需要一个 0.47 英寸的安装孔。
7、轻打磨顶板顶面均匀。这将充当光扩散器,为您提供更漫射、更柔和的光效果。

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图1

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图2

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图3

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图5

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图4

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图6

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图8

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图7

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图9

驴友花雕  中级技神
 楼主|

发表于 昨天 07:43

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具

项目代码

  1. /***************************************************
  2.   ProtoStax Audio Visualizer Demo
  3.   This is a example sketch for an Audio Visualizer using Arduino,  
  4.    
  5.   SparkFun Spectrum Shield --> https://www.sparkfun.com/products/13116 ,
  6.   Adafruit NeoPixel Shield --> https://www.adafruit.com/product/1430 ,
  7.   and
  8.   ProtoStax for Arduino --> https://www.protostax.com/products/protostax-for-arduino
  9.   It analyzes the frequency spectrum of the audio input and visualizes it using
  10.   an RGB LED matrix with different schemes.
  11.   Written by Sridhar Rajagopal for ProtoStax
  12.   BSD license. All text above must be included in any redistribution
  13. */
  14. #include <Adafruit_GFX.h>
  15. #include <Adafruit_NeoMatrix.h>
  16. #include <Adafruit_NeoPixel.h>
  17. #ifndef PSTR
  18. #define PSTR // Make Arduino Due happy
  19. #endif
  20. //Declare Spectrum Shield pin connections
  21. #define STROBE 4
  22. #define RESET 5
  23. #define DC_One A0
  24. #define DC_Two A1
  25. //Define spectrum variables
  26. int freq_amp;
  27. int Frequencies_One[7];
  28. int Frequencies_Two[7];
  29. // MATRIX DECLARATION:
  30. // Parameter 1 = width of NeoPixel matrix
  31. // Parameter 2 = height of matrix
  32. // Parameter 3 = pin number (most are valid)
  33. // Parameter 4 = matrix layout flags, add together as needed:
  34. //   NEO_MATRIX_TOP, NEO_MATRIX_BOTTOM, NEO_MATRIX_LEFT, NEO_MATRIX_RIGHT:
  35. //     Position of the FIRST LED in the matrix; pick two, e.g.
  36. //     NEO_MATRIX_TOP + NEO_MATRIX_LEFT for the top-left corner.
  37. //   NEO_MATRIX_ROWS, NEO_MATRIX_COLUMNS: LEDs are arranged in horizontal
  38. //     rows or in vertical columns, respectively; pick one or the other.
  39. //   NEO_MATRIX_PROGRESSIVE, NEO_MATRIX_ZIGZAG: all rows/columns proceed
  40. //     in the same order, or alternate lines reverse direction; pick one.
  41. //   See example below for these values in action.
  42. // Parameter 5 = pixel type flags, add together as needed:
  43. //   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
  44. //   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
  45. //   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
  46. //   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
  47. // Example for NeoPixel Shield used in Audio Visualizer Demo.
  48. // In this application we'd like to use it
  49. // as a 5x8 tall matrix, with the USB port positioned at the top of the
  50. // Arduino.  When held that way, the first physical pixel is at the top right, and
  51. // lines are arranged in columns, progressive order.  The shield uses
  52. // 800 KHz (v2) pixels that expect GRB color data.
  53. // See https://www.hackster.io/sridhar-rajagopal/rgb-matrix-audio-visualizer-with-arduino-845062
  54. // for more details on how to choose the parameters
  55. #define NEO_MATRIX_WIDTH 5
  56. #define NEO_MATRIX_HEIGHT 8
  57. #define NEOPIXEL_PIN 6 // Shield maps it to pin 6
  58. Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(NEO_MATRIX_WIDTH, NEO_MATRIX_HEIGHT, NEOPIXEL_PIN,
  59.   NEO_MATRIX_TOP     + NEO_MATRIX_RIGHT +
  60.   NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,
  61.   NEO_GRB            + NEO_KHZ800);
  62. enum RANGE {
  63.   BASS = 0,
  64.   MID_RANGE = 1,
  65.   TREBLE = 2,
  66.   ALL = 3
  67. };
  68. enum SCHEME {
  69.   MAGNITUDE_HUE = 0,
  70.   MAGNITUDE_HUE_2 = 1,
  71.   HSV_COLOR_WHEEL = 2
  72. };
  73. /********************Setup *************************/
  74. void setup() {
  75.   Serial.begin(9600);
  76.   Serial.println("ProtoStax Audio Visualizer Demo");
  77.   Serial.println("**************************************************");
  78.   matrix.begin();
  79.   matrix.setTextWrap(false);
  80.   matrix.setBrightness(40);
  81.   matrix.fillScreen(0);
  82.   matrix.show();
  83.   
  84.   //Set spectrum Shield pin configurations
  85.   pinMode(STROBE, OUTPUT);
  86.   pinMode(RESET, OUTPUT);
  87.   pinMode(DC_One, INPUT);
  88.   pinMode(DC_Two, INPUT);  
  89.   digitalWrite(STROBE, HIGH);
  90.   digitalWrite(RESET, HIGH);
  91.   
  92.   //Initialize Spectrum Analyzers
  93.   digitalWrite(STROBE, LOW);
  94.   delay(1);
  95.   digitalWrite(RESET, HIGH);
  96.   delay(1);
  97.   digitalWrite(STROBE, HIGH);
  98.   delay(1);
  99.   digitalWrite(STROBE, LOW);
  100.   delay(1);
  101.   digitalWrite(RESET, LOW);
  102. }
  103. /************************** Loop*****************************/
  104. void loop() {
  105.   static int scheme = 0;
  106.   while (Serial.available() > 0) {
  107.     scheme = Serial.parseInt();
  108.   }
  109.   
  110.   Read_Frequencies();
  111.   Graph_Frequencies(ALL, scheme);
  112.   // Print_Frequencies();
  113.   delay(50);
  114. }
  115. int max_bass_freq = 0;
  116. int max_mid_freq = 0;
  117. int max_treble_freq = 0;
  118. /*******************Pull frquencies from Spectrum Shield********************/
  119. void Read_Frequencies(){
  120.   max_bass_freq = 0;
  121.   max_mid_freq = 0;
  122.   max_treble_freq = 0;
  123.   //Read frequencies for each band
  124.   for (freq_amp = 0; freq_amp<7; freq_amp++)
  125.   {
  126.     Frequencies_One[freq_amp] = (analogRead(DC_One) + analogRead(DC_One) ) >> 1 ;
  127.     Frequencies_Two[freq_amp] = (analogRead(DC_Two) + analogRead(DC_Two) ) >> 1;
  128.     if (freq_amp >= 0 && freq_amp < 2) {
  129.         if (Frequencies_One[freq_amp] > max_bass_freq)
  130.           max_bass_freq = Frequencies_One[freq_amp];
  131.         if (Frequencies_Two[freq_amp] > max_bass_freq)
  132.           max_bass_freq = Frequencies_Two[freq_amp];  
  133.     }
  134.     else if (freq_amp >= 2 && freq_amp < 5) {
  135.         if (Frequencies_One[freq_amp] > max_mid_freq)
  136.           max_mid_freq = Frequencies_One[freq_amp];
  137.         if (Frequencies_Two[freq_amp] > max_mid_freq)
  138.           max_mid_freq = Frequencies_Two[freq_amp];  
  139.     }
  140.     else if (freq_amp >= 5 && freq_amp < 7) {
  141.         if (Frequencies_One[freq_amp] > max_treble_freq)
  142.           max_treble_freq = Frequencies_One[freq_amp];
  143.         if (Frequencies_Two[freq_amp] > max_treble_freq)
  144.           max_treble_freq = Frequencies_Two[freq_amp];  
  145.     }   
  146.     digitalWrite(STROBE, HIGH);
  147.     digitalWrite(STROBE, LOW);
  148.   }
  149. }
  150. int FREQ_DIV_FACTOR = 204;
  151. /*******************Light LEDs based on frequencies*****************************/
  152. void Graph_Frequencies(RANGE r, SCHEME s){
  153.    int from = 0;
  154.    int to = 0;
  155.    switch(r) {
  156.     case BASS:
  157.       from = 0;
  158.       to = 2;
  159.       break;
  160.     case MID_RANGE:
  161.       from = 2;
  162.       to = 5;
  163.       break;
  164.     case TREBLE:
  165.       from = 5;
  166.       to = 7;
  167.       break;
  168.     case ALL:
  169.       from = 0;
  170.       to = 7;
  171.       break;
  172.     default:
  173.       break;
  174.    }
  175.   
  176.    // Serial.print("max freq is "); Serial.println(max_freq);
  177.    // FREQ_DIV_FACTOR = max_bass_freq/4;
  178.    // Serial.print("FREQ_DIV_FACTOR is "); Serial.println(FREQ_DIV_FACTOR);
  179.    
  180.    static uint16_t hue = 0; //21845 22250 to -250
  181.    uint16_t hueDelta = 200;
  182.    hue += hueDelta;
  183.    
  184.    uint16_t bassHue = 22250;
  185.    uint16_t midHue = 22250; //54613
  186.    uint16_t trebleHue = 22250; //43690
  187.       
  188.    matrix.fillScreen(0);
  189.    uint32_t rgbcolor;
  190.    for(int row= from; row<to; row++)
  191.    {
  192.      int freq = (Frequencies_Two[row] > Frequencies_One[row])?Frequencies_Two[row]:Frequencies_One[row];
  193.      
  194.      int numCol = (freq/FREQ_DIV_FACTOR);
  195.      if (numCol > 5) numCol = 5;
  196.    
  197.      for (int col = 0 ; col < numCol ; col++) {
  198.        switch(s) {
  199.         case MAGNITUDE_HUE:
  200.           bassHue = 22250;
  201.           midHue = 22250; //54613
  202.           trebleHue = 22250; //43690
  203.           if (row >= 0 && row < 2) {
  204.             rgbcolor = matrix.ColorHSV(bassHue - (7416 * col) );      
  205.           } else if (row >= 2 && row < 5) {
  206.             rgbcolor = matrix.ColorHSV(midHue - (7416 * col) );      
  207.             
  208.           } else if (row >= 5 && row < 7) {
  209.             rgbcolor = matrix.ColorHSV(trebleHue - (7416 * col) );      
  210.           }
  211.           break;         
  212.         case MAGNITUDE_HUE_2:
  213.           bassHue = 54613;
  214.           midHue = 54613; //54613
  215.           trebleHue = 54613; //43690        
  216.           if (row >= 0 && row < 2) {
  217.             rgbcolor = matrix.ColorHSV(bassHue - (7416 * col) );      
  218.           } else if (row >= 2 && row < 5) {
  219.             rgbcolor = matrix.ColorHSV(midHue - (7416 * col) );      
  220.             
  221.           } else if (row >= 5 && row < 7) {
  222.             rgbcolor = matrix.ColorHSV(trebleHue - (7416 * col) );      
  223.           }        
  224.           break;
  225.         case HSV_COLOR_WHEEL:
  226.           rgbcolor = matrix.ColorHSV(hue);
  227.           break;
  228.        }
  229.       
  230.         matrix.setPassThruColor(rgbcolor);      
  231.         matrix.drawPixel(col, row, (uint16_t)0); // color does not matter here
  232.         matrix.setPassThruColor();
  233.         
  234.         //matrix.show();
  235.      
  236.      }
  237.      matrix.show();
  238.    }
  239. }
  240. // Used for debugging
  241. void Print_Frequencies() {
  242.   for (int i = 0; i < 7; i++) {
  243.     Serial.print("FreqOne["); Serial.print(i); Serial.print( "]:"); Serial.println((Frequencies_One[i]/FREQ_DIV_FACTOR)%5);
  244.     Serial.print("FreqTwo["); Serial.print(i); Serial.print( "]:"); Serial.println((Frequencies_Two[i]/FREQ_DIV_FACTOR)%5);
  245.   }
  246. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 昨天 07:45

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具
项目链接:https://www.hackster.io/sridhar- ... with-arduino-845062
项目作者:斯里达尔·拉贾戈帕尔

项目视频 :
https://www.youtube.com/watch?v=n20gm_qOhbE
https://www.youtube.com/watch?v=0mGiqoVA6K4
项目代码:https://github.com/protostax/Pro ... Visualizer_Demo.ino

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图2

【Arduino 动手做】带Arduino的RGB矩阵音频可视化工具图1

回复

使用道具 举报

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

本版积分规则

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

硬件清单

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

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

mail