基于Arduino的RGB矩阵音乐节奏灯
使用Adafruit、SparkFun、Arduino和ProtoStax创造美妙的音乐!用Arduino制作一个RGB矩阵音频可视化器。
标签
Arduino
refdesignshare
更新2024-06-28
389

项目来自:RGB Matrix Audio Visualizer with Arduino - Hackster.io

Github链接:protostax/ProtoStax_Audio_Visualizer_Demo: Demo for ProtoStax Audio Visualizer with Spectrum Shield, NeoPixel Shield and Arduino (github.com)

在这篇文章中,将为大家展示如何巧用Arduino、RGB LED矩阵扩展板和音频频谱分析扩展板,亲手打造一个RGB LED矩阵音频可视化器,并配上透明的亚克力外壳,为你的音乐带来一场美妙的灯光秀,增添一抹绚烂的光影!

介绍

对于音频频谱分析,本项目中使用的是SparkFun的频谱扩展板,它使用两个MSGEQ7图形均衡器显示滤波器,将立体声音频输入分割成7个频段(每个通道),并使用Arduino上的ADC读取每个频段的幅度。它附带了Arduino示例草图,以便开始使用。

对于RGB LED矩阵,本项目中使用的是Adafruit为Arduino设计的NeoPixel扩展板,它由40个RGB NeoPixels组成(Adafruit对他们的WS2812光源的术语)。红色、绿色和蓝色LED与驱动芯片集成在一起,通过单根导线进行控制。它们可以单独使用,串联成更长的灯串,或者组装成更有趣的形态。在扩展板上,它们是串联在一起的。扩展板还附带了Adafruit_NeoMatrix库,该库简化了对RGB LED矩阵的访问和LED的控制。

最后是外壳部分,本项目创建了一种新的可堆叠、模块化的外壳系统,叫做ProtoStax。它支持不同阶段的原型设计,提供保护和开放访问,以便在开始时使用,并有能力稍后添加侧壁和顶部,但也有能力水平堆叠或垂直堆叠多个单元,从而能够根据原型设计需求和其他板卡及组件的增加进行扩展。

本项目中使用ProtoStax for Arduino,一个为Arduino设计的透明亚克力外壳——它适合Uno/Leonardo尺寸以及更大的Mega/Due尺寸——这也是可堆叠和模块化的,并且有足够的空间容纳两个扩展板。采用了透明且坚固的亚克力材料,方便展示你的音频可视化器以及你的音乐系统!

步骤 1 - 将Arduino安装到外壳基座板上

首先将Arduino(以示例中的Uno为例)安装到外壳的基座板上。这样做可以在配置和设置Arduino时提供保护,同时提供完全开放的访问权限,以便进行操作和调整。当你准备将其封闭起来时,可以轻松地添加侧壁和顶板,并用螺丝将所有部件固定。

将Arduino安装到基座板上,并添加脚垫和其他硬件,以准备外壳的平板配置。请参阅下图所有步骤的动态演示图:

步骤 2 - 为 Arduino 准备 SparkFun 频谱扩展板

SparkFun频谱扩展板没有附带插座。幸运的是,Adafruit为Arduino设计的NeoPixel扩展板既附带堆叠插座也附带普通插座。由于想要NeoPixel扩展板位于顶部,本项目中使用普通插座,这样它就能平齐,这样就留下了堆叠插座供频谱扩展板使用。

但是,带有堆叠接头的 Spectrum Shield 并不紧密地适合,Arduino Uno 上的 USB 和电源端口会妨碍,如下图所示。

在此做了以下两项修改:

  • 切断覆盖在USB和电源端口上的频谱扩展板的末端(那部分有原型区域,但未使用)这使得频谱扩展板能够紧密地安装在Arduino上。
  • 即使如此,堆叠插座的腿可能仍然太长,导致频谱扩展板无法紧密贴合。稍微修剪堆叠插座的腿,以使频谱扩展板能够使用堆叠插座紧密地安装在Arduino上。


现在它很贴合!

步骤 3 - 将Adafruit NeoPixel扩展板插入到频谱扩展板的堆叠插座中

Adafruit NeoPixel Shield 位于 Spectrum Shield 之上。首先需要焊接常规接头(随附)。在本项目中还焊接了它附带的终端连接器,尽管在这个例子中,使用 Arduino 为其供电,因为所有 LED 不会同时亮起,所以功耗在Arduino能够提供的范围内。

来自Adafruit的NeoPixel扩展板页面的消息:

为了便于启动,LED 默认由 5V 板载 Arduino 电源供电。只要你不是让所有像素都以全功率白色点亮,那应该没问题。如果要使用外部电源为扩展板供电,请焊接随板附带的接线端子(专业提示:将其放在电路板底部,以免粘住)以连接到外部 4-6VDC 电源 - 该电源也将为 Arduino 和扩展板供电。如果您想使用接线端子为屏蔽层供电,但保持Arduino本身仅使用DC或USB电源,请将焊接跳线的中心切到接线端子的右侧。外部输入端有一个极性保护 FET,以防您将电源向后接线。

步骤 4 - 演示代码

代码分为两个主要部分:

  • 频谱分析和保存结果
  • 将其转换为 8x5 NeoPixel Matrix 的显示/配色方案。

演示代码链接:

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之间,它们提供了每个频段的振幅的表示。

//Declare Spectrum Shield pin connections
#define STROBE 4
#define RESET 5
#define DC_One A0
#define DC_Two A1
//Define spectrum variables
int freq_amp;
int Frequencies_One[7];
int Frequencies_Two[7];
int i;

void setup() {
...
//Initialize Spectrum Analyzers
digitalWrite(STROBE, LOW);
delay(1);
digitalWrite(RESET, HIGH);
delay(1);
digitalWrite(STROBE, HIGH);
delay(1);
digitalWrite(STROBE, LOW);
delay(1);
digitalWrite(RESET, LOW);
...
}

void loop() {
...
Read_Frequencies();
...
}

/*******************Pull frquencies from Spectrum Shield********************/
void Read_Frequencies(){
...
//Read frequencies for each band
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);
digitalWrite(STROBE, LOW);
}
}

频谱的 7 个频段是:

  • 63赫兹
  • 160赫兹
  • 400赫兹
  • 1kHz
  • 2.5k赫兹
  • 6.25k赫兹
  • 16k赫兹

将这些频段分为三个范围 - 低音(BASS)、中音(MID_RANGE)和高音(TREBLE)。典型的低音范围是 60 到 250 Hz,因此前两个频段在低音范围内。中频频率通常为 500 Hz 至 2 kHz,因此将接下来的 3 个频段归入中音范围,剩余的两个频段归入高音范围。

[注意:每个波段的最大读数到一个单独的变量中。这可能被用来自动将读数缩放到RGB矩阵列所代表的级别 - 这在输入信号较弱的情况下很有用,否则在这种情况下只有极少数 RGB 矩阵会亮起。]

RGB矩阵

可以参考 Adafruit NeoPixel Überguide 了解有关 NeoPixel Shield 和 NeoPixel 的更多信息。

首先要注意的是,在坐标系中,[0, 0] 总是指左上角,无论方向如何。接下来是记下您感兴趣的任何方向的宽度,然后是高度。

第三是注意物理 LED #0 的位置(以 Adafruit 标志为标志)。右上角、左上角、左下角和右下角,视情况而定。还要注意物理 LED 的进展方向。在本项目的电路板中,布局是渐进式的(一行结束后的下一个物理 LED 从下一行的开头开始,如黄线所示)。进展的方向在宽度更宽(水平方向)时是沿着行的(由短的绿色箭头指示),在宽度更窄(垂直方向)时是沿着列的(同样由短的绿色箭头指示)。

以下图片说明了这些:

在示例中,有 7 个频段和一个 8 x 5(或 5 x 8,取决于您查看它的方式!本项目中选择沿着8的维度展示这7个频率带(留下一个未使用)。然后沿着5的维度展示每个频率带的幅度表示。

原点从左下角开始(代表最低频段的最低电平),然后向上移动。但由于在坐标系统中首先要记住的是[0, 0]总是指左上角,因此您应该将头向左倾斜并查看下图,以了解初始化 NeoMatrix 的值选择!(宽度 = 5,高度 = 8,右上角,逐行列)

现在来深入研究一下与 NeoMatrix 相关的演示代码并绘制频率图。首先,确定 NeoPixel 的宽度=5,高度=8,我们选择的朝向是右上角(TOP-RIGHT),并且列是递增的(COLUMNS PROGRESSIVE)。按照setup()函数中所需的矩阵设置进行操作。

在 loop()中,读取任何串行输入以选择配色方案 ,本项目中定义了 3 种不同的配色方案

enum SCHEME {
MAGNITUDE_HUE = 0,
MAGNITUDE_HUE_2 = 1,
HSV_COLOR_WHEEL = 2
};

接着,根据选定的颜色方案调用Graph_Frequencies函数。同时请注意,该函数的第一个参数可以选择要展示的频率范围(低音、中音或高音)。

enum RANGE {
BASS = 0,
MID_RANGE = 1,
TREBLE = 2,
ALL = 3
};

现在,选择所有要显示的范围,通过串行输入或包括一个瞬时按钮在 BASS、MID_RANGE、TREBLE 或 ALL 之间切换显示。RANGE的选择决定了要显示的行的起始和结束范围。

对于每一行(频段),选取立体声输入的左右两个声道中较大的频率幅度。该值介于 0 和 1023 之间,需要将其映射到显示器的 5 个不同的列中,因此将频率除以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)代表由红色、绿色和蓝色值定义的颜色。然而,使用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() 来重置该标志。

  static uint16_t hue = 0; //21845 22250 to -250 
uint16_t hueDelta = 200;
hue += hueDelta;
...
rgbcolor = matrix.ColorHSV(hue);
...
matrix.setPassThruColor(rgbcolor);
matrix.drawPixel(col, row, (uint16_t)0); // color does not matter here
matrix.setPassThruColor();
...
matrix.show();

使用 HSV,可以递增16位的色调值并生成HSV颜色码,这样就可以实现颜色的平滑过渡。

以下是供参考的不同代码片段:

#define NEO_MATRIX_WIDTH 5
#define NEO_MATRIX_HEIGHT 8
#define NEOPIXEL_PIN 6 // Shield maps it to pin 6
Adafruit_NeoMatrix matrix = 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();
matrix.setTextWrap(false);
matrix.setBrightness(40);
matrix.fillScreen(0);
matrix.show();
...
}

void loop() {
static int scheme = 0;
while (Serial.available() > 0) {
scheme = Serial.parseInt();
}
...
Graph_Frequencies(ALL, scheme);
...
delay(50);
}

void Graph_Frequencies(CHANNEL c, SCHEME s){
...
for( row= from; row<to; row++)
{
int freq = (Frequencies_Two[row] > Frequencies_One[row])?Frequencies_Two[row]:Frequencies_One[row];
int numCol = (freq/FREQ_DIV_FACTOR);
if (numCol > 5) numCol = 5;
for (int col = 0 ; col < numCol ; col++) {
... // pick color scheme to display
matrix.setPassThruColor(rgbcolor);
matrix.drawPixel(col, row, (uint16_t)0); // color does not matter here
matrix.setPassThruColor();
//matrix.show();
}
matrix.show();
}
}

接下来是配色方案的选择。请注意,我已经预留了根据不同频率范围选择颜色的选项(低音色调、中音色调、高音色调)。我创建了 3 种不同的配色方案 - 一种方案是从最低幅度到最高幅度使用绿色至红色/粉色的渐变,另一种方案使用更多偏向粉色/蓝色的范围。第三种方案则是所有像素使用单一颜色,但在运行时会循环遍历整个色轮。

switch(s) {
case MAGNITUDE_HUE:
bassHue = 22250;
midHue = 22250; //54613
trebleHue = 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) );
}
break;
case MAGNITUDE_HUE_2:
bassHue = 54613;
midHue = 54613; //54613
trebleHue = 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) );
}
break;
case HSV_COLOR_WHEEL:
rgbcolor = matrix.ColorHSV(hue);
break;
}

步骤 5 - 完成组装

图中安装顶部支撑元件、侧壁、音频线和顶部。请参照以下步骤 :

步骤 6 - 展示您的创作,让美妙的音乐更加美丽!

现在你可以拥有一个有趣的音频节奏灯,你可以将其展示在你的音乐系统旁边,让你自制的酷炫灯光效果增强音乐体验!

步骤 7 - 更进一步

这里有一些想法可以让项目走得更远!

  • 目前,音频线(输入和输出)插入外壳中的频谱扩展板,因此你将有这些电线连接并悬挂在外壳外面。相反,您可以在 Spectrum 扩展板的立体声插孔附近的侧壁上添加几个面板安装立体声插孔,然后将音频线焊接到每个插孔上,然后将它们插入 Spectrum 扩展板的音频插孔。在这种情况下,外壳会变得非常整洁,并且所有接线都是独立的,外壳上只有音频插孔供外部系统插入。
  • 可以向音频可视化工具添加更多甚至更多的灯光方案 - 不同的颜色范围,不同的图案。
  • 添加使用串行输入启用/禁用频率范围的选项 - 目前只能更改配色方案,但不能更改要显示的频率范围。
  • 添加一个开关以在不同配色方案之间切换,而不是使用串行输入。修改外壳,在其中一个长侧壁上添加一个孔,以容纳面板安装瞬时按钮开关(列在使用的“物品”列表中)。
  • 添加第二个开关来切换显示的不同频率范围(低音、中音、高音、全部),并将该开关安装在外壳的侧壁上。
  • 由于外壳由亚克力制成,可以使用一些胶带来保护表面,并使用钻头钻一个所需尺寸的孔以安装面板安装的立体声插孔和/或开关。建议使用阶梯钻头,或者从一个较小的孔开始,然后扩大孔直到达到所需的尺寸。立体声插孔需要一个5/16英寸的安装孔,开关需要一个0.47英寸的安装孔。
  • 轻轻均匀地打磨顶板的顶面。这将充当光扩散器,会有一个更分散、更柔和的光效果。


附件下载
ProtoStax_Audio_Visualizer_Demo.ino
团队介绍
Sridhar Rajagopal
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号