Arduino Audio Reactive Desk Light
组件和用品
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
必要的工具和机器
|
应用和在线服务
|
关于这个项目
你好世界!!
你好!在这个版本中,我们将使用简单的组件和一些基本的 Arduino 编程。站在桌子上玩游戏、播放音乐以及其他任何真正能发出声音的东西时,它都会产生很棒的效果。出发吧!
这是我根据 youtuber 的“自然书呆子”所做的一个项目。这是我的项目版本。所有的功劳都归功于他们,并向他们大喊大叫,因为他们向我提供了有关如何执行该项目的详细信息。
Youtube 链接
第 1 步:主要供应品
第一件事:我们需要什么样的供应品,它们的成本是多少?嗯,它们在很大程度上是可选的,并且可以进行大量即兴创作。尽管如此,如果您想遵循本指南,还是需要一些关键项目:
- Arduino Nano (或任何同样小的 Arduino 类型)(RM 12.50 购买链接)
- 声音检测器模块 (RM 5.90 购买链接)
- 5 伏 电源 (或 12 伏,带降压模块)
- 单独可寻址 LED 每条带 60 个 LED。米(购买链接)
根据您想要的外观,您可能希望以不同的方式排列条带或以另一种方式漫射光线。这是您可以发挥创造力的地方。如果你喜欢我的方法,我使用了以下项目:
- 最高的宜家 Droppar 罐 (宜家链接)
- 一小段 PVC 管。
- 泡沫板
- 热胶枪
考虑到所有因素,我花了大约 83.30 令吉,具体取决于您去购买物品的商店,其中 LED 灯条是迄今为止最昂贵的部分,仅 1 米就花费了我 40 令吉。
第 2 步:为组件供电
为组件供电将是一种直接的方法。我只是使用 Arduino Nano 的 USB 电缆并直接插入电脑。如果您使用外部电源,例如 AC 到 DC 电源,您将需要一个降压模块来帮助您减少流向电路的电流量。否则,如果你不使用它,你可能有很大的机会烧毁 Arduino,包括连接的组件。
该节目的明星是声音检测器模块。这将为 Arduino 提供一个模拟信号,我们可以用它来(希望)巧妙地点亮 RGB 灯。为了能够做到这一点,我们需要为两个设备供电。幸运的是,它们都需要 5 伏输入。我正在使用降压模块从 12 伏降压到 5 伏,但直接使用 5 伏电源会更容易。将 Arduino 和声音检测器板上的 VIN 连接到正极输入。然后将 Arduino 上的 GND 和检测器连接到负极。查看所附原理图上的黑色和红色电线。我们还需要将 LED 灯条上的正负输入连接到电源。
第 3 步:检测器和条带
图> 图>将所有三个部分都连接到电源后,我们需要将它们相互连接起来。
声音检测器模块将通过模拟输入引脚与 Arduino 通信。在这种情况下,我将使用 0 号引脚。
LED 灯条需要一个数字脉冲才能了解我们要寻址的 LED。因此,我们需要将数字输出引脚连接到 Arduino nano。我将使用 6 号引脚。
将收缩管用于选择区域,以便稍后电缆不会在狭小空间内相互碰撞。
只要按照我在这里提供的示意图就可以了!
太棒了,现在我们基本上完成了电子产品!
第 4 步:上传代码
这个构建中最重要的部分可以说是代码。它可以将这个构建从非常酷变成非常棒。您可以使用我与此项目一起提供的代码。主要原理是将我们从传感器获得的模拟值映射到要显示的 LED 数量。
第 5 步:准备外壳
图> 图> 图> 图>起初我以为盖子是用亚克力做的,在我买了罐子并意识到它不是亚克力而是玻璃之后。所以我需要通过制作一个易于戳和安装 Arduino 和 LED 的盖子来重新调整我的计划。所以我选择了泡沫板。
第一步 ,我需要切割泡沫板,使其完全为圆形,并且直径与罐子的玻璃盖相同。我没有合适的测量直径工具,所以我即兴使用湿记号笔并标记玻璃的直径并将其印在一张纸上。之后,我将纸粘贴到泡沫板上,然后沿着纸上圆圈的边缘粘贴板。它并不完美,但它应该足以容纳所有 Arduino 和 LED 组件。
第二步 ,我需要打破罐盖上的玻璃。 注意!请用厚塑料袋盖住罐子 防止玻璃散落在房间周围,并在开放空间进行。了解你周围的环境。打破玻璃后,请确保将卡在罐盖侧面裂缝处的玻璃全部取出。这是为了防止您或其他人因将他们自己切割到卡住的玻璃上而受伤。
第三步 , 将圆形泡沫板放在罐盖中央。确保泡沫紧实且不太松,以便与罐子完美贴合。
图> 图>第四步, 我刚刚意识到我需要改变这个项目的布局。我想让用户在出现故障时可以轻松访问 Arduino 组件。所以,我决定使用迷你面包板并将其放在盖子的中央。不仅如此,我还为声音模块的电缆切了两个孔,我将把它放在罐盖底部,以便进入罐子和面包板上,还有一个孔让 Arduino 与 USB 电缆连接以发挥作用作为电路的电源。
图> 图> 图>第五步 ,我用美纹纸胶带标记 pvc 管并在胶带的中心画线。然后,我把它贴在 pvc 管道上。标记是我将PVC管切割均匀并试图切割干净的标志。
在测量了我需要使用的 pvc 长度后,我按照我提供的标记仔细切割。 pvc 管的长度取决于您的罐子高度。您可以使用任何您想要的长度。
图> 图> 图> 图> 图>第六步 ,我扭曲了我用 LED 灯条切割的 PVC 管,使其稍微倾斜并螺旋到 PVC 的顶部。我确保为多余的电缆长度创建一个小孔,以隐藏在 PVC 罐内以进行电缆管理。然后我需要找到一种方法将 PVC 放在面包板上。使用热胶枪或双面胶带,我能够将 PVC 管粘在额外的泡沫板上,然后将其粘贴在面包板上未使用的区域。在这一步中,我能够将一些组件连接到面包板。
使用提供的示意图连接所有组件。
(面包板的左侧区域为正极,面包板的右侧区域为负极。`
图> 图> 图> 图> 图>第七步,我把发声模块放在罐盖外面。这样做是为了便于模块稍后在罐子外拾取声音。模块放置好后,用电缆连接好,按照给定的原理图进行匹配。然后,将所有电缆与传感器和 Arduino 连接到面包板。 Arduino 垂直设置,以便为电路供电的电缆能够通过泡沫板轻松连接到 Arduino 板。
就这样,我完成了这个项目。我花了一段时间加上尝试和错误,但我设法完成了它。
代码
- Arduino 编码
Arduino 编码Arduino
此代码将使 LED 对声音模块检测到的声音做出反应。#include/** BASIC CONFIGURATION **////设置中的 LED 数量#define NUM_LEDS 60 //控制LED的引脚#define LED_PIN 6//我们读取传感器值的引脚形成#define ANALOG_READ 0//确认麦克风低值和最大值#define MIC_LOW 0.0#define MIC_HIGH 200.0/** 其他宏* ///有多少先前的传感器值影响操作平均值?#define AVGLEN 5//有多少先前的传感器值决定我们是否处于峰值/高(例如在歌曲中)#define LONG_SECTOR 20//Mneumonics#define HIGH 3 #define NORMAL 2//在重新开始测量之前,我们保持“当前平均值”声音多久#define MSECS 30 * 1000#define CYCLES MSECS / DELAY/*有时读数错误或奇怪。允许读数偏离平均值多少才不会被丢弃? **/#define DEV_THRESH 0.8//Arduino循环延迟#define DELAY 1float 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 visual_music();//我们显示多少个LEDint curshow =NUM_LEDS;/*还没有真正使用。以为可以在声音reactivemode之间切换,一般梯度脉冲/静态颜色*/int mode =0;//根据模式显示不同的颜色.int songmode =NORMAL;//平均声音测量最后一个CYCLES unsigned long song_avg; //自song_avg被重置后的迭代次数int iter =0;//如果不是的话,LED变黑的速度 relitfloat fake_scale =1.2;//Led arrayCRGB leds[NUM_LEDS];/*用于“正常化”的短声音平均输入值。我们使用短平均值而不是直接使用传感器输入 */int avgs[AVGLEN] ={-1};//更长的声音 avgint long_avg[LONG_SECTOR] ={-1};//跟踪频率,以及我们达到某个模式的时间有多长 struct time_keeping { unsigned long times_start;短时间;};//每种颜色增加或减少多少每个循环结构颜色{ int r;国际g; int b;};struct time_keeping high;struct color Color;无效设置(){ Serial.begin(9600); //设置所有灯以确保所有灯都按预期工作 FastLED.addLeds (leds, NUM_LEDS); for (int i =0; i (song_avg/iter * 1.1)) { if (high.times !=0) { if (millis() - high.times_start> 200.0) { high.times =0;歌曲模式 =正常; } else { high.times_start =millis(); high.times++; } } else { high.times++; high.times_start =毫秒(); if (high.times> 30 &&millis() - high.times_start <50.0) songmode =HIGH;否则 if (millis() - high.times_start> 200) { high.times =0;歌曲模式 =正常; }}//用于可视化lampvoid中声音的主要函数visual_music() { int sensor_value, mapping, avg, longavg; //实际传感器值 sensor_value =analogRead(ANALOG_READ); //如果为0,立即丢弃。可能不对,节省CPU。如果(sensor_value ==0)返回; //丢弃与过去平均值偏差太大的读数。映射 =(float)fscale(MIC_LOW, MIC_HIGH, MIC_LOW, (float)MIC_HIGH, (float)sensor_value, 2.0); avg =compute_average(avgs, AVGLEN); if (((avg - 映射)> avg*DEV_THRESH)) //|| ((avg - 映射) <-avg*DEV_THRESH)) 返回; //插入新的平均值。值插入(映射,平均,AVGLEN);插入(平均,long_avg,LONG_SECTOR); //计算“歌曲平均值”传感器值 song_avg +=avg;迭代++; if (iter> CYCLES) { song_avg =song_avg / iter;迭代 =1; } longavg =compute_average(long_avg, LONG_SECTOR); //检查我们是否进入HIGH模式 check_high(longavg);如果(songmode ==HIGH){fade_scale =3;颜色.r =5;颜色.g =3;颜色.b =-1; } else if (songmode ==NORMAL) {fade_scale =2;颜色.r =-1;颜色.b =2;颜色.g =1; } //决定点亮多少个LED curshow =fscale(MIC_LOW, MIC_HIGH, 0.0, (float)NUM_LEDS, (float)avg, -1); /*设置不同的LED。控制过高和过低的值。有趣的尝试:不要考虑一个方向的溢出,会出现一些有趣的光效! */ for (int i =0; i 255) leds[i]. r =255;否则如果 (leds[i].r + Color.r <0) leds[i].r =0;否则 leds[i].r =leds[i].r + Color.r;如果(leds[i].g + Color.g> 255)leds[i].g =255;否则如果 (leds[i].g + Color.g <0) leds[i].g =0;否则 leds[i].g =leds[i].g + Color.g;如果(leds[i].b + Color.b> 255)leds[i].b =255;否则如果 (leds[i].b + Color.b <0) leds[i].b =0;否则 leds[i].b =leds[i].b + Color.b; //所有其他 LED 开始逐渐变暗直至完全黑暗 } 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 10) curve =10;如果(曲线 <-10)曲线 =-10;曲线 =(曲线 * -.1); // - 反转和缩放 - 这似乎更直观 - 正数给予输出曲线高端的更多权重 =pow(10, curve); // 将线性标度转换为其他 pow 函数的对数指数 // 检查 inputValues 是否超出范围 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 浮点数 // 检查 originalMin> originalMax - 所有其他情况的数学,即负数似乎工作正常 if (originalMin> originalMax ) { return 0; } if (invFlag ==0){ rangedValue =(pow(normalizedCurVal, curve) * NewRange) + newBegin; } else // 反转范围 { rangedValue =newBegin - (pow(normalizedCurVal, curve) * NewRange); } return rangedValue;}
示意图
制造工艺