在這個(gè)項(xiàng)目構(gòu)建中,我們將使用簡(jiǎn)單的組件和一些基本的Arduino編程來制作一個(gè)與所有聲音和音樂共舞的漂亮燈。站在桌子上玩游戲、播放音樂和其他任何真正能發(fā)出聲音的東西時(shí),它都會(huì)產(chǎn)生令人驚嘆的效果。讓我們開始吧!
第 1 步:主要用品首先要做的事情是:規(guī)劃我們需要什么樣的用品,它們的成本是多少?它們?cè)诤艽蟪潭壬鲜强蛇x的,并且可以通過所需功能進(jìn)行變動(dòng)。但雖然如此,還是有一些關(guān)鍵的東西是必需的:
- Arduino Nano(或任何同樣小的 Arduino 類型)
- 聲音檢測(cè)模塊(RM 5.90 購(gòu)買鏈接)
- 5伏電源(或12伏降壓模塊)
- 每個(gè)可單獨(dú)尋址的 LED 燈條 60 個(gè) LED
- 最高的宜家 Droppar 罐
- 一小段PVC管。
- 泡沫板
- 熱膠槍
該部分的核心是聲音檢測(cè)器模塊。這將為 Arduino 提供模擬信號(hào),我們可以用它巧妙地點(diǎn)亮 RGB 燈。為了能夠做到這一點(diǎn),我們需要為這兩個(gè)設(shè)備供電。(關(guān)注公眾號(hào) 電路一點(diǎn)通)幸運(yùn)的是,它們都需要 5 伏輸入。我正在使用降壓模塊從 12 伏降到 5 伏,但直接使用 5 伏電源會(huì)更容易。將 Arduino 和聲音檢測(cè)器板上的 VIN 連接到正極輸入。然后將 Arduino 上的 GND 和檢測(cè)器連接到負(fù)極。我們還需要將 LED 燈條上的正負(fù)輸入連接到電源。
第 3 步:檢測(cè)器和條帶
將所有三個(gè)部分連接到電源后,我們需要將它們相互連接。聲音檢測(cè)器模塊將通過模擬輸入引腳與 Arduino 通信。在這種情況下,我將使用 0 號(hào)引腳。
LED 燈條需要一個(gè)數(shù)字脈沖才能了解我們要處理的 LED。因此,我們需要將數(shù)字輸出引腳連接到 Arduino nano。我將使用 6 號(hào)引腳。
在選擇區(qū)域使用收縮管,這樣電纜以后就不會(huì)在狹窄的空間內(nèi)相互碰撞。太棒了,現(xiàn)在我們大部分都完成了電子設(shè)備!
第 4 步:上傳代碼這個(gè)構(gòu)建中最重要的部分可以說是代碼。它可以將這個(gè)構(gòu)建從非常酷變?yōu)榉浅0簟V饕硎菍⑽覀儚?a href="http://m.xsypw.cn/v/tag/117/" target="_blank">傳感器獲得的模擬值映射到要顯示的 LED 數(shù)量。
第 5 步:準(zhǔn)備外殼
一開始我以為蓋子是亞克力做的,后來我買了罐子,發(fā)現(xiàn)它不是亞克力而是玻璃。所以我需要重新調(diào)整我的計(jì)劃,制作一個(gè)易于戳和安裝 Arduino 和 LED 的蓋子。所以我選擇了泡沫板。
第一步,我需要切割泡沫板,使其完全呈圓形,并且與罐子的玻璃蓋具有相同的直徑。我沒有合適的測(cè)量直徑工具,所以我使用濕記號(hào)筆即興創(chuàng)作了該方法,并標(biāo)記了玻璃的直徑并將其印在一張紙上。之后,我將紙粘貼到泡沫板上,但沿著紙上圓圈的邊緣粘貼到板上。它并不完美,但應(yīng)該足以容納所有 Arduino 和 LED 組件。
第二步,我需要打破罐蓋上的玻璃。警告!請(qǐng)用厚塑料袋蓋住罐子,以防止玻璃散落在房間周圍,并在空曠的地方進(jìn)行。了解您的周圍環(huán)境。打碎玻璃后,請(qǐng)確保所有粘在罐蓋側(cè)面裂縫處的玻璃都被清除。這是為了防止您或其他人因?qū)⑺鼈冏约呵懈畹娇ㄗ〉牟A隙軅?/span>
第三步,將圓形泡沫板放在罐蓋的中心。確保泡沫是緊的,不要太松,它們正好適合罐子。
第四步,我才意識(shí)到我需要改變這個(gè)項(xiàng)目的布局。我想讓用戶在出現(xiàn)故障時(shí)可以輕松訪問 Arduino 組件。所以,我決定使用迷你面包板并將其放在蓋子的中心。不僅如此,我還為聲音模塊上的電纜剪了兩個(gè)孔,我將把它們放在罐蓋的底部,進(jìn)入罐子和面包板上,還有一個(gè)孔讓 Arduino 與 USB 電纜連接以發(fā)揮作用作為電路的電源。
第五步,我用膠帶標(biāo)記pvc管并在膠帶的中心畫線。然后,我把它貼在 pvc 管上。標(biāo)記是我均勻切割 pvc 管并嘗試干凈切割的指標(biāo)。
在測(cè)量了我需要使用的 pvc 長(zhǎng)度后,我按照我提供的標(biāo)記仔細(xì)切割它。pvc 管的長(zhǎng)度取決于您的罐子高度。你可以使用任何你想要的長(zhǎng)度。
第六步,我將用 LED 燈條切割的 PVC 管翹曲,使其略微傾斜并螺旋到 PVC 的頂部。我確保為多余的電纜長(zhǎng)度創(chuàng)建一個(gè)小孔,以便將其隱藏在 PVC 罐內(nèi)以進(jìn)行電纜管理。然后我需要找到一種方法將 PVC 放在面包板上。使用熱膠槍或雙面膠帶,我可以將 PVC 管粘在額外的泡沫板上,然后將其粘貼到面包板上未使用的區(qū)域。在這一步中,我能夠?qū)⒁恍┙M件連接到面包板。面包板的左側(cè)區(qū)域?yàn)檎龢O,面包板的右側(cè)區(qū)域?yàn)樨?fù)極。
第七步,我把聲音模塊放在罐蓋的外面。這樣做是為了便于模塊稍后在 jar 外拾取聲音。放置模塊后,將其與電纜連接并按照給出的示意圖進(jìn)行匹配。然后,將所有電纜與傳感器和 Arduino 連接到面包板。Arduino 是垂直安裝的,因此用于為電路供電的電纜將能夠通過泡沫板輕松地與 Arduino 板連接。
到此,這個(gè)項(xiàng)目就完成了。我花了一段時(shí)間加上嘗試和錯(cuò)誤,但最終我依舊設(shè)法完成了它。
Coding For the Arduino:
#include
//The amount of LEDs in the setup
#define NUM_LEDS 60
//The pin that controls the LEDs
#define LED_PIN 6
//The pin that we read sensor values form
#define ANALOG_READ 0
//Confirmed microphone low value, and max value
#define MIC_LOW 0.0
#define MIC_HIGH 200.0
/** Other macros */
//How many previous sensor values effects the operating average?
#define AVGLEN 5
//How many previous sensor values decides if we are on a peak/HIGH (e.g. in a song)
#define LONG_SECTOR 20
//Mneumonics
#define HIGH 3
#define NORMAL 2
//How long do we keep the "current average" sound, before restarting the measuring
#define MSECS 30 * 1000
#define CYCLES MSECS / DELAY
/*Sometimes readings are wrong or strange. How much is a reading allowed
to deviate from the average to not be discarded? **/
#define DEV_THRESH 0.8
//Arduino loop delay
#define DELAY 1
float 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 visualize_music();
//How many LEDs to we display
int curshow = NUM_LEDS;
/*Not really used yet. Thought to be able to switch between sound reactive
mode, and general gradient pulsing/static color*/
int mode = 0;
//Showing different colors based on the mode.
int songmode = NORMAL;
//Average sound measurement the last CYCLES
unsigned long song_avg;
//The amount of iterations since the song_avg was reset
int iter = 0;
//The speed the LEDs fade to black if not relit
float fade_scale = 1.2;
//Led array
CRGB leds[NUM_LEDS];
/*Short sound avg used to "normalize" the input values.
We use the short average instead of using the sensor input directly */
int avgs[AVGLEN] = {-1};
//Longer sound avg
int long_avg[LONG_SECTOR] = {-1};
//Keeping track how often, and how long times we hit a certain mode
struct time_keeping {
unsigned long times_start;
short times;
};
//How much to increment or decrement each color every cycle
struct color {
int r;
int g;
int b;
};
struct time_keeping high;
struct color Color;
void setup() {
Serial.begin(9600);
//Set all lights to make sure all are working as expected
FastLED.addLeds
for (int i = 0; i < NUM_LEDS; i++)?
leds[i] = CRGB(0, 0, 255);
FastLED.show();
delay(1000);
//bootstrap average with some low values
for (int i = 0; i < AVGLEN; i++) { ?
insert(250, avgs, AVGLEN);
}
//Initial values
high.times = 0;
high.times_start = millis();
Color.r = 0;
Color.g = 0;
Color.b = 1;
}
/*With this we can change the mode if we want to implement a general
lamp feature, with for instance general pulsing. Maybe if the
sound is low for a while? */
void loop() {
switch(mode) {
case 0:
visualize_music();
break;
default:
break;
}
delay(DELAY); // delay in between reads for stability
}
/**Funtion to check if the lamp should either enter a HIGH mode,
or revert to NORMAL if already in HIGH. If the sensors report values
that are higher than 1.1 times the average values, and this has happened
more than 30 times the last few milliseconds, it will enter HIGH mode.
TODO: Not very well written, remove hardcoded values, and make it more
reusable and configurable. */
void check_high(int avg) {
if (avg > (song_avg/iter * 1.1)) {
if (high.times != 0) {
if (millis() - high.times_start > 200.0) {
high.times = 0;
songmode = NORMAL;
} else {
high.times_start = millis();
high.times++;
}
} else {
high.times++;
high.times_start = millis();
}
}
if (high.times > 30 && millis() - high.times_start < 50.0)
songmode = HIGH;
else if (millis() - high.times_start > 200) {
high.times = 0;
songmode = NORMAL;
}
}
//Main function for visualizing the sounds in the lamp
void visualize_music() {
int sensor_value, mapped, avg, longavg;
//Actual sensor value
sensor_value = analogRead(ANALOG_READ);
//If 0, discard immediately. Probably not right and save CPU.
if (sensor_value == 0)
return;
//Discard readings that deviates too much from the past avg.
mapped = (float)fscale(MIC_LOW, MIC_HIGH, MIC_LOW, (float)MIC_HIGH, (float)sensor_value, 2.0);
avg = compute_average(avgs, AVGLEN);
if (((avg - mapped) > avg*DEV_THRESH)) //|| ((avg - mapped) < -avg*DEV_THRESH))
return;
//Insert new avg. values
insert(mapped, avgs, AVGLEN);
insert(avg, long_avg, LONG_SECTOR);
//Compute the "song average" sensor value
song_avg += avg;
iter++;
if (iter > CYCLES) {
song_avg = song_avg / iter;
iter = 1;
}
longavg = compute_average(long_avg, LONG_SECTOR);
//Check if we enter HIGH mode
check_high(longavg);
if (songmode == HIGH) {
fade_scale = 3;
Color.r = 5;
Color.g = 3;
Color.b = -1;
}
else if (songmode == NORMAL) {
fade_scale = 2;
Color.r = -1;
Color.b = 2;
Color.g = 1;
}
//Decides how many of the LEDs will be lit
curshow = fscale(MIC_LOW, MIC_HIGH, 0.0, (float)NUM_LEDS, (float)avg, -1);
/*Set the different leds. Control for too high and too low values.
Fun thing to try: Dont account for overflow in one direction,
some interesting light effects appear! */
for (int i = 0; i < NUM_LEDS; i++)?
//The leds we want to show
if (i < curshow) {
if (leds[i].r + Color.r > 255)
leds[i].r = 255;
else if (leds[i].r + Color.r < 0)
leds[i].r = 0;
else
leds[i].r = leds[i].r + Color.r;
if (leds[i].g + Color.g > 255)
leds[i].g = 255;
else if (leds[i].g + Color.g < 0)
leds[i].g = 0;
else
leds[i].g = leds[i].g + Color.g;
if (leds[i].b + Color.b > 255)
leds[i].b = 255;
else if (leds[i].b + Color.b < 0)
leds[i].b = 0;
else
leds[i].b = leds[i].b + Color.b;
//All the other LEDs begin their fading journey to eventual total darkness
} else {
leds[i] = CRGB(leds[i].r/fade_scale, leds[i].g/fade_scale, leds[i].b/fade_scale);
}
FastLED.show();
}
//Compute average of a int array, given the starting pointer and the length
int compute_average(int *avgs, int len) {
int sum = 0;
for (int i = 0; i < len; i++)
sum += avgs[i];
return (int)(sum / len);
}
//Insert a value into an array, and shift it down removing
//the first value if array already full
void insert(int val, int *avgs, int len) {
for (int i = 0; i < len; i++) {
if (avgs[i] == -1) {
avgs[i] = val;
return;
}
}
for (int i = 1; i < len; i++) {
avgs[i - 1] = avgs[i];
}
avgs[len - 1] = val;
}
//Function imported from the arduino website.
//Basically map, but with a curve on the scale (can be non-uniform).
float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve){
float OriginalRange = 0;
float NewRange = 0;
float zeroRefCurVal = 0;
float normalizedCurVal = 0;
float rangedValue = 0;
boolean invFlag = 0;
// condition curve parameter
// limit range
if (curve > 10) curve = 10;
if (curve < -10) curve = -10;
curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function
// Check for out of range inputValues
if (inputValue < originalMin) {
inputValue = originalMin;
}
if (inputValue > originalMax) {
inputValue = originalMax;
}
// Zero Refference the values
OriginalRange = originalMax - originalMin;
if (newEnd > newBegin){
NewRange = newEnd - newBegin;
}
else
{
NewRange = newBegin - newEnd;
invFlag = 1;
}
zeroRefCurVal = inputValue - originalMin;
normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float
// Check for originalMin > originalMax - the math for all other cases i.e. negative numbers seems to work out fine
if (originalMin > originalMax ) {
return 0;
}
if (invFlag == 0){
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin;
}
else // invert the ranges
{
rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange);
}
return rangedValue;
}
-
led
+關(guān)注
關(guān)注
242文章
23609瀏覽量
668831 -
檢測(cè)器
+關(guān)注
關(guān)注
1文章
882瀏覽量
48254 -
音頻
+關(guān)注
關(guān)注
29文章
2995瀏覽量
82791 -
RGB
+關(guān)注
關(guān)注
4文章
803瀏覽量
59387 -
Arduino
+關(guān)注
關(guān)注
188文章
6485瀏覽量
189635
原文標(biāo)題:DIY音頻反應(yīng)臺(tái)燈(Arduino 代碼)
文章出處:【微信號(hào):電路一點(diǎn)通,微信公眾號(hào):電路一點(diǎn)通】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
構(gòu)建一個(gè)音頻反應(yīng)臺(tái)燈

基于AB32的遙控臺(tái)燈DIY過程記錄
用易拉罐環(huán)DIY制作臺(tái)燈
DIY自己的arduino項(xiàng)目

DIY簡(jiǎn)單的Arduino鍵盤

Diy Lillypad Arduino

基于Arduino平臺(tái)的DIY示波器

評(píng)論