在這個項目構建中,我們將使用簡單的組件和一些基本的Arduino編程來制作一個與所有聲音和音樂共舞的漂亮燈。站在桌子上玩游戲、播放音樂和其他任何真正能發(fā)出聲音的東西時,它都會產生令人驚嘆的效果。讓我們開始吧!
第 1 步:主要用品首先要做的事情是:規(guī)劃我們需要什么樣的用品,它們的成本是多少?它們在很大程度上是可選的,并且可以通過所需功能進行變動。但雖然如此,還是有一些關鍵的東西是必需的:根據您想要的外觀,您可能希望以不同的方式排列條帶或以其他方式漫射光。這是你可以發(fā)揮創(chuàng)造力的地方。如果您喜歡我的方法,我使用了以下項目:
- 最高的宜家 Droppar 罐
- 一小段PVC管。
- 泡沫板
- 熱膠槍
該部分的核心是聲音檢測器模塊。這將為 Arduino 提供模擬信號,我們可以用它巧妙地點亮 RGB 燈。為了能夠做到這一點,我們需要為這兩個設備供電。(關注公眾號 電路一點通)幸運的是,它們都需要 5 伏輸入。我正在使用降壓模塊從 12 伏降到 5 伏,但直接使用 5 伏電源會更容易。將 Arduino 和聲音檢測器板上的 VIN 連接到正極輸入。然后將 Arduino 上的 GND 和檢測器連接到負極。我們還需要將 LED 燈條上的正負輸入連接到電源。
第 3 步:檢測器和條帶
將所有三個部分連接到電源后,我們需要將它們相互連接。聲音檢測器模塊將通過模擬輸入引腳與 Arduino 通信。在這種情況下,我將使用 0 號引腳。
LED 燈條需要一個數(shù)字脈沖才能了解我們要處理的 LED。因此,我們需要將數(shù)字輸出引腳連接到 Arduino nano。我將使用 6 號引腳。
在選擇區(qū)域使用收縮管,這樣電纜以后就不會在狹窄的空間內相互碰撞。太棒了,現(xiàn)在我們大部分都完成了電子設備!
第 4 步:上傳代碼這個構建中最重要的部分可以說是代碼。它可以將這個構建從非??嶙?yōu)榉浅0簟V饕硎菍⑽覀儚?a href="http://ttokpm.com/v/tag/117/" target="_blank">傳感器獲得的模擬值映射到要顯示的 LED 數(shù)量。
第 5 步:準備外殼
一開始我以為蓋子是亞克力做的,后來我買了罐子,發(fā)現(xiàn)它不是亞克力而是玻璃。所以我需要重新調整我的計劃,制作一個易于戳和安裝 Arduino 和 LED 的蓋子。所以我選擇了泡沫板。
第一步,我需要切割泡沫板,使其完全呈圓形,并且與罐子的玻璃蓋具有相同的直徑。我沒有合適的測量直徑工具,所以我使用濕記號筆即興創(chuàng)作了該方法,并標記了玻璃的直徑并將其印在一張紙上。之后,我將紙粘貼到泡沫板上,但沿著紙上圓圈的邊緣粘貼到板上。它并不完美,但應該足以容納所有 Arduino 和 LED 組件。
第二步,我需要打破罐蓋上的玻璃。警告!請用厚塑料袋蓋住罐子,以防止玻璃散落在房間周圍,并在空曠的地方進行。了解您的周圍環(huán)境。打碎玻璃后,請確保所有粘在罐蓋側面裂縫處的玻璃都被清除。這是為了防止您或其他人因將它們自己切割到卡住的玻璃上而受傷。
第三步,將圓形泡沫板放在罐蓋的中心。確保泡沫是緊的,不要太松,它們正好適合罐子。
第四步,我才意識到我需要改變這個項目的布局。我想讓用戶在出現(xiàn)故障時可以輕松訪問 Arduino 組件。所以,我決定使用迷你面包板并將其放在蓋子的中心。不僅如此,我還為聲音模塊上的電纜剪了兩個孔,我將把它們放在罐蓋的底部,進入罐子和面包板上,還有一個孔讓 Arduino 與 USB 電纜連接以發(fā)揮作用作為電路的電源。
第五步,我用膠帶標記pvc管并在膠帶的中心畫線。然后,我把它貼在 pvc 管上。標記是我均勻切割 pvc 管并嘗試干凈切割的指標。
在測量了我需要使用的 pvc 長度后,我按照我提供的標記仔細切割它。pvc 管的長度取決于您的罐子高度。你可以使用任何你想要的長度。
第六步,我將用 LED 燈條切割的 PVC 管翹曲,使其略微傾斜并螺旋到 PVC 的頂部。我確保為多余的電纜長度創(chuàng)建一個小孔,以便將其隱藏在 PVC 罐內以進行電纜管理。然后我需要找到一種方法將 PVC 放在面包板上。使用熱膠槍或雙面膠帶,我可以將 PVC 管粘在額外的泡沫板上,然后將其粘貼到面包板上未使用的區(qū)域。在這一步中,我能夠將一些組件連接到面包板。面包板的左側區(qū)域為正極,面包板的右側區(qū)域為負極。
第七步,我把聲音模塊放在罐蓋的外面。這樣做是為了便于模塊稍后在 jar 外拾取聲音。放置模塊后,將其與電纜連接并按照給出的示意圖進行匹配。然后,將所有電纜與傳感器和 Arduino 連接到面包板。Arduino 是垂直安裝的,因此用于為電路供電的電纜將能夠通過泡沫板輕松地與 Arduino 板連接。
到此,這個項目就完成了。我花了一段時間加上嘗試和錯誤,但最終我依舊設法完成了它。
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
+關注
關注
240文章
23062瀏覽量
657060 -
檢測器
+關注
關注
1文章
857瀏覽量
47623 -
音頻
+關注
關注
29文章
2830瀏覽量
81257 -
RGB
+關注
關注
4文章
796瀏覽量
58336 -
Arduino
+關注
關注
187文章
6457瀏覽量
186502
原文標題:DIY音頻反應臺燈(Arduino 代碼)
文章出處:【微信號:電路一點通,微信公眾號:電路一點通】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論