RGB Matrix Audio Visualizer with Arduino
组件和用品
![]() |
| × | 1 | |||
| × | 1 | ||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
| × | 1 | ||||
| × | 2 | ||||
| × | 2 | ||||
| × | 1 |
必要的工具和机器
![]() |
|
关于这个项目

在本文中,我将解释如何使用 Arduino、RGB LED 矩阵扩展板和音频频谱分析器扩展板构建 RGB LED 矩阵音频可视化器,然后将其放入外壳中,以便您可以完成一个完整的项目由您的音乐系统显示,让您的音乐呈现出美妙的灯光效果!
对于音频频谱分析,我使用 SparkFun 的 Spectrum Shield,它使用两个 MSGEQ7 图形均衡器显示滤波器,将立体声音频输入分成 7 个频段(每个通道),并使用 Arduino 上的 ADC 读取每个频段的幅度。它随附 Arduino 示例草图以开始使用。
对于 RGB LED 矩阵,我使用 Adafruit 的 NeoPixel Shield for Arduino,它包含 40 个 RGB NeoPixel(Adafruit 对其 WS2812 光源的术语)。红色、绿色和蓝色 LED 与驱动器芯片一起集成到一个通过单线控制的微型表面贴装封装中。它们可以单独使用、链接成更长的字符串或组装成更有趣的外形。在 Shield 的情况下,它们被链接在一起。 Shield 还带有 Adafruit_NeoMatrix 库,可简化对 RGB LED 矩阵的访问和控制 LED。
最后是外壳。你们中的一些人可能知道我已经创建了一个名为 ProtoStax 的新的可堆叠模块化外壳系统。这是我不得不抓挠的个人渴望 - 我想要一个支持原型制作不同阶段的外壳,在开始时提供保护和开放式访问,能够在以后添加侧壁和顶部,但也能够堆叠多个单元并排或一个在另一个之上,从而能够根据原型设计需求和添加其他电路板和组件进行扩展。
在这个例子中,我为 Arduino 使用了 ProtoStax,这是一个用于 Arduino 的透明亚克力外壳——它既适合 Uno/Leonardo 的足迹,也适合更大的 Mega/Due 足迹——它也是可堆叠和模块化的,并且为两者提供了舒适的空间盾牌(有一些小的修改,我将概述)。它清晰而坚固,还有橡胶支脚,可以稍微抬高它并保护您的桌子表面,因此您可以将您的音频展示台及其灯光秀与您的音乐系统一起展示! 😊
好的,让我们开始吧,好吗? 😊
第 1 步 - 将 Arduino 安装到机箱底板
让我们首先将 Arduino(在我们的示例中为 Uno)安装到外壳的底板上。这为它提供了保护,同时提供了对它的完全开放访问,以配置和设置 Arduino 并使用它。当您准备关闭它时,很容易添加侧壁和顶板并用螺钉固定所有东西。
将Arduino安装到底板上,并在平台配置中添加地脚和其他硬件以准备外壳 .请参阅幻灯片中的以下步骤 - 每张图片的标题都有编号,并为每个步骤提供额外说明。









以下是 gif 动画的所有步骤:

第 2 步 - 为 Arduino 准备 SparkFun Spectrum Shield
SparkFun Spectrum Shield 不附带标题。对我们来说幸运的是,用于 Arduino 的 Adafruit NeoPixel Shield 带有堆叠头和普通头。因为我希望 NeoPixel Shield 位于顶部,所以我想使用普通标题,以便它可以齐平,这使得堆叠标题与 Spectrum Shield 一起使用,这正是我想要的! 😉
但是,带有堆叠接头的 Spectrum Shield 不适合 - Arduino Uno 上的 USB 和电源端口妨碍了,如下图所示。

我做了以下两个修改 -
- 切断 USB 和电源端口上 Spectrum Shield 的末端(该部分具有原型制作区域,未使用。即使您使用它,最终也只会切断一排孔)这使得Spectrum Shield 紧贴在 Arduino 上。
- 堆叠头的支腿可能仍然太长,Spectrum Shield 无法紧贴。我修剪了堆叠接头的腿,使 Spectrum Shield 与堆叠接头紧贴在 Arduino 上。


现在它很合身!



第 3 步 - 将 Adafruit NeoPixel Shield for Arduino 插入 Spectrum Shield 的堆叠头
Adafruit NeoPixel Shield 位于 Spectrum Shield 之上。您首先需要焊接常规标头(它随附)。我还焊接了它附带的终端连接器,但在本例中,我使用 Arduino 为其供电,因为所有 LED 不会同时打开,因此功耗在 Arduino 可以提供的范围内.
来自 Adafruit 的 NeoPixel Shield for Arduino 页面的消息:


第 4 步 - 演示代码
让我们看一下演示代码,看看它在做什么。为此,我们可以将其分为两个主要部分:
- 频谱分析和保存结果
- 将其转化为 8x5 NeoPixel 矩阵的显示/配色方案。
您可以在此处快速参考演示代码:
https://github.com/protostax/ProtoStax_Audio_Visualizer_Demo/blob/master/ProtoStax_Audio_Visualizer_Demo.ino
频谱分析
您可以参考 Spectrum Shield 连接指南,了解有关 Spectrum Shield 的其他信息。我已经总结了这里的信息。
通过将数字序列写入 Spectrum Shield 的 STROBE 和 RESET 引脚,您可以初始化 Shield 使用的 MSGEQ7 芯片。然后,您可以继续读取频谱分成的 7 个不同频段中每个频段的幅度。读取每个波段,然后脉冲 STROBE 引脚以启动下一个波段的读取。立体声输入的两个通道的值存储在 Frequencies_One[7] 和 Frequencies_Two[7] 中。这些值是通过使用 Arduino 的 10 位 ADC 读取的,因此输出值可以是 0 - 1023 - 它们提供了每个频段幅度的表示。
//声明频谱屏蔽引脚连接#define STROBE 4#define RESET 5#define DC_One A0#define DC_Two A1 //定义频谱变量int freq_amp;int Frequencies_One[7];int Frequencies_Two[7];国际我; void setup() { ... //初始化频谱分析仪 digitalWrite(STROBE, LOW);延迟(1);数字写入(重置,高);延迟(1);数字写入(频闪,高);延迟(1);数字写入(频闪,低);延迟(1); digitalWrite(RESET, LOW);...} void loop() {... Read_Frequencies();...} /*******************从Spectrum Shield********************/void Read_Frequencies(){... //读取每个频段的频率 for (freq_amp =0; freq_amp<7; freq_amp++) { Frequencies_One[freq_amp] =(analogRead(DC_One) + analogRead(DC_One))>> 1; Frequencies_Two[freq_amp] =(analogRead(DC_Two) + analogRead(DC_Two))>> 1; ...digitalWrite(STROBE, HIGH);数字写入(频闪,低); }}
频谱的7个频段是:
- 63Hz
- 160Hz
- 400Hz
- 1kHz
- 2.5kHz
- 6.25kHz
- 16kHZ
我将它们分成 3 个范围 - BASS、MID_RANGE 和 TREBLE。典型的低音范围是 60 到 250 Hz,因此前两个频段在 BASS 范围内。中频通常为 500 Hz 到 2 kHz,因此我将接下来的 3 个频段分组为 MID_RANGE。我将剩下的 2 个频段组合成 TREBLE。
[注意:我还注意到每个波段的最大读数到一个单独的变量中。这可能用于将读数自动缩放到由 RGB 矩阵列表示的级别 - 这在输入信号低的情况下很有用 - 否则在这种情况下只有很少的 RGB 矩阵会点亮。 ]
RGB 矩阵
您可以参考 Adafruit NeoPixel Überguide,了解有关 NeoPixel Shield 和 NeoPixel 的一般信息。我在这里总结了与我们的使用有关的信息。
我将尝试澄清的主要观点是 NeoPixel Shield 的方向和方向以及坐标系的编号,起初我发现这有点令人困惑。 Überguide 解释了它,但我想我可以让它更容易一些。
首先要注意的是,在坐标系中,[0, 0] 始终指的是左上角,无论方向如何。
接下来是注意您感兴趣的任何方向的宽度,然后是高度(即 5 x 8 与 8 x 5 在我们的 Shield 的情况下)
第三是注意 PHYSICAL LED #0 的位置(以可爱的 Adafruit 标志为标志)。 TOP-RIGHT、TOP-LEFT、BOTTOM-LEFT 和 BOTTOM-RIGHT 视情况而定。还要注意物理 LED 的进展方向。布局在我们的板上是渐进式的(一行结束后的下一个物理 LED 从下一行的开头开始,如黄色线所示)。当宽度较宽(水平方向)(如绿色短箭头所示)和宽度较窄(垂直方向)的 COLUMNS(再次如绿色短箭头所示)时,级数的方向是沿着 ROWS )。
幻灯片中的以下 4 张图片说明了这些。标题包括每种情况下的相关设置!




在我们的示例中,我们有 7 个频段和一个 8 x 5(或 5 x 8,取决于您查看它的方式!)矩阵。我选择沿 8 维显示 7 个波段(留下一个未使用)。然后我将沿 5 维显示每个频段的幅度表示。换句话说,我希望我的进度如下:
我希望我的原点从左下角开始(代表最低频段的最低水平)并向上工作。但是由于在坐标系中首先要注意的是[0, 0]总是指TOP-LEFT,所以你应该将头向左倾斜并查看下图,以了解初始化NeoMatrix的值的选择! 😊(WIDTH =5, HEIGHT =8, TOP-RIGHT, COLUMNS PROGRESSIVE)

让我们深入研究一下有关 NeoMatrix 和绘制频率的演示代码。首先,我们确定我们的 NeoPixel 有 WIDTH=5,HEIGHT=8,我们喜欢的方向是 TOP-RIGHT,和 COLUMNS PROGRESSIVE。按照 setup() 函数中矩阵所需的设置进行操作。
在 loop() 中,我们读取任何串行输入以选择配色方案 - 我定义了 3 种不同的配色方案
enum SCHEME { MAGNITUDE_HUE =0, MAGNITUDE_HUE_2 =1, HSV_COLOR_WHEEL =2};
然后我使用该配色方案选择调用 Graph_Frequencies。另请注意可以选择要显示的频率范围(BASS、MID-RANGE 或 TREBLE)的第一个参数
enum RANGE { BASS =0, MID_RANGE =1, TREBLE =2, ALL =3};
现在,我选择要显示的所有范围 - 读者可以练习选择要显示的范围 - 通过串行输入或包括瞬时按下按钮以在 BASS、MID_RANGE 之间切换显示,高音或全部。 RANGE 的选择决定了要显示的行的“from”和“to”范围。
对于每一行(频带),我们选择两个频率幅度(立体声输入的右声道和左声道)中较大的一个。正如我们已经讨论过的,该值介于 0 和 1023 之间。我们需要将其映射到显示的 5 个不同列中,因此我们将频率除以定义为 204 的 FREQ_DIV_FACTOR(1023/204 =5,这会将输出 1023 映射到 5)。为了安全起见,我们还确保要显示的 numCol 不大于 5。这决定了每个频段要显示的列数。
然后我使用 matrix.drawPixel() 以适当的颜色显示适当的像素。
我在图形显示中使用 HSV 色轮。这带来了一些额外的皱纹需要克服。
通常,用法是 matrix.drawPixel(column, row, Color(r, g, b)),其中 Color(r, g, b) 表示由 RED、GREEN 和 BLUE 值指定的颜色。但是,使用 HSV 可以实现一些不错的平滑颜色过渡。
NeoMatrix 提供了 matrix.ColorHSV(uint16_t hue) 方法,该方法采用单个 uint16_t 色调值并返回 uint32_t HSV 颜色。
但是 matrix.Color(r, g, b) 返回 uint16_t 颜色。 matrix.drawPixel 还需要 16 位颜色。
解决这个问题的方法是使用 matrix.setPassThruColor(32 位颜色值)。这会在矩阵中设置一个标志,导致 drawPixel 忽略其颜色参数,而是使用上述方法已设置的 32 位颜色。请记住调用 matrix.setPassThruColor() 来重置有问题的标志。不是超级优雅,但它有效。例如,
静态 uint16_t 色调 =0; //21845 22250 到 -250 uint16_t HueDelta =200;色调 +=色调Delta;... rgbcolor =matrix.ColorHSV(hue);... matrix.setPassThruColor(rgbcolor); matrix.drawPixel(col, row, (uint16_t)0); // 颜色在这里无关紧要 matrix.setPassThruColor();...matrix.show();
使用 HSV,可以增加 16 位色调并生成 HSV 颜色代码,从而获得漂亮的颜色平滑过渡。
以下是不同的代码片段供参考:
<代码>的#define NEO_MATRIX_WIDTH 5#限定NEO_MATRIX_HEIGHT 8#限定NEOPIXEL_PIN 6 //盾映射它到引脚6Adafruit_NeoMatrix矩阵=Adafruit_NeoMatrix(NEO_MATRIX_WIDTH,NEO_MATRIX_HEIGHT,NEOPIXEL_PIN,NEO_MATRIX_TOP + NEO_MATRIX_RIGHT + NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,NEO_GRB + NEO_KHZ800); .... void setup() {... matrix.begin();矩阵.setTextWrap(false);矩阵.setBrightness(40);矩阵.fillScreen(0); matrix.show();...} void loop() { static int scheme =0;而 (Serial.available()> 0) { 方案 =Serial.parseInt(); }... Graph_Frequencies(ALL, scheme);... delay(50);} void Graph_Frequencies(CHANNEL c, SCHEME s){... for( row=from; rowFrequencies_One[row])?Frequencies_Two[row]:Frequencies_One[row]; int numCol =(freq/FREQ_DIV_FACTOR);如果 (numCol> 5) numCol =5; for (int col =0; col
接下来是配色方案的选择。请注意,我已经做出规定,可以为不同的频率范围(bassHue、midHue、trebleHue)选择颜色。我创建了 3 种不同的配色方案 - 一种使用绿色到红色/粉红色范围显示从最低幅度到最高幅度,另一种使用更多粉红色/蓝色偏移范围。第三种方案对所有像素使用相同的颜色,但随着整个色轮的进行循环。我将向您展示所有 3 种配色方案的视频。
switch(s) { case MAGNITUDE_HUE:bassHue =22250; midHue =22250; //54613 高音色调 =22250; //43690 if (row>=0 &&row <2) { rgbcolor =matrix.ColorHSV(bassHue - (7416 * col)); } else if (row>=2 &&row <5) { rgbcolor =matrix.ColorHSV(midHue - (7416 * col)); } else if (row>=5 &&row <7) { rgbcolor =matrix.ColorHSV(trebleHue - (7416 * col)); } 休息;案例 MAGNITUDE_HUE_2:bassHue =54613; midHue =54613; //54613 高音色调 =54613; //43690 if (row>=0 &&row <2) { rgbcolor =matrix.ColorHSV(bassHue - (7416 * col)); } else if (row>=2 &&row <5) { rgbcolor =matrix.ColorHSV(midHue - (7416 * col)); } else if (row>=5 &&row <7) { rgbcolor =matrix.ColorHSV(trebleHue - (7416 * col)); } 休息; case HSV_COLOR_WHEEL:rgbcolor =matrix.ColorHSV(hue);休息; }
第 6 步 - 测试一切
这是一个测试一切的视频
第 6 步 - 关闭它
安装顶部支撑元件、侧壁、音频线和顶部。请参阅幻灯片中的以下步骤 - 每张图片的标题都有编号,并为每个步骤提供额外说明。













以下是单个动画 gif 中的所有步骤:

第 7 步 - 展示您的创作并使美妙的音乐更加美妙!
您现在可以拥有一个有趣的音频可视化器,您可以将它与您的音乐系统一起显示,并使用一些很酷的自制灯光动作来增强您的音乐!
第 8 步 - 更进一步
这里有一些想法可以让项目更进一步!
1. 目前,音频线(输入和输出)已插入外壳中的 Spectrum Shield,因此您将这些线连接到外壳并悬挂在外面。相反,您可以在 Spectrum Shield 立体声插孔附近的侧壁上添加几个面板安装立体声插孔(列在所用“物品”列表中),然后将音频电缆与 3.5 毫米公立体声音频插孔焊接在一起到每个,然后将它们插入 Spectrum Shield 的音频插孔。在这种情况下,您的外壳变得非常整洁,所有接线都是独立的,外壳上只有音频插孔供外部系统插入。
2. 您可以为 Audio Visualizer 添加更多甚至更多的灯光方案 - 不同的颜色范围、不同的图案。
3. 添加使用串行输入启用/禁用频率范围的选项 - 目前只能更改配色方案,但不能更改要显示的频率范围。
4. 添加一个开关来在不同的配色方案之间切换,而不是使用串行输入。修改外壳以在其中一个长侧壁上添加一个孔,以容纳面板安装瞬时按钮开关(列在所用“物品”列表中)。
5. 添加第二个开关以在显示的不同频率范围(BASS、MID_RANGE、TREBLE、ALL)之间切换,并将该开关安装到外壳的侧壁。
6. 由于外壳由亚克力制成,您可以在其上使用一些蓝色油漆胶带来保护表面,并使用钻头在所需一侧钻一个孔以安装面板安装立体声插孔和/或开关。建议使用阶梯钻,或从较小的孔开始,然后扩大孔直到达到您想要的尺寸。列出的立体声插孔需要5/16"的安装孔,开关需要0.47"的安装孔。
7. 轻轻均匀地打磨顶板的顶面。这将充当光漫射器,并为您提供更漫射和更柔和的光效果。
如果有足够的兴趣,我将更新该项目以使用音频插孔和开关以及不透明的光扩散器顶部来展示它 - 如果您想查看更新的项目,请给我发消息! 😊
你还能想到更多吗?在下方写下评论让我们知道! 😊 也欢迎您提出任何问题! 😊
快乐制作! 😊
代码
ProtoStax Audio Visualizer 演示
包含此 ProtoStax Audio Visualizer Demo 中使用的代码的 Github 存储库 https://github.com/protostax/ProtoStax_Audio_Visualizer_Demo制造工艺