1、音乐动感节奏灯是个什么东西?

  前段时间听音乐觉得无聊,便想着音乐光听也没意思啊,能不能 “看见” 音乐呢?于是谷歌了一番,发现还真有人做了将音乐可视化的东西,那就是音乐节奏灯。说的简单点就是LED灯光颜色亮度等随着音乐的节奏而发生变化,看了下他们的实现方法有很多,不过大都比较复杂,而且灯只能够做节奏灯也比较浪费,于是我便动手做了一个既可以当作普通台灯使用,又可以随着音乐而闪烁的动感节奏灯,一举两得。

2、做这个东西需要准备哪些材料?

  工欲善其事,必先利其器。那么做这样一个音乐动感节奏等需要准备哪些材料呢?

  •   Arduino UNO 开发板
  • 声音传感器(最好买Arduino专用的)
  • BLE蓝牙4.0模块
  • WS2812B彩色灯带
  • 灯罩
  • 3D打印底座
  • 电源线和杜邦线若干

以上材料可以在淘宝买到,灯罩和3D打印的底座可以按照自己的实际需求来进行自己选择,为了防止打广告的嫌疑我就不放购买链接了,可以自行设计打印~

3、做这个东西需该怎么做?

  准备好上述的材料之后,我们就可以开始进行灯的制作啦~,节奏灯的主要结构如下图:

我们使用Arduino UNO作为主要的计算和处理模块,蓝牙4.0模块和手机进行通信,利用手机APP来选择模式(后续会讲),在节奏灯的模式下,通过声音传感器来采集声音,通过得到的声音来控制灯带的颜色和闪烁,在彩色灯的模式下,利用手机来控制灯的颜色,理论上的有160万可调颜色。接下来介绍下详细的步骤。

3.1 安装开发环境

  Arduino UNO 开发的环境为Arduino IDE,软件下载地址为 https://www.arduino.cn/thread-5838-1-1.html ,默认安装为最新版即可。安装完IDE之后还需要安装第三方的库。

  1) WS2812B的库 FastLED, 选择 项目->加载库->管理库,然后在输入栏输入FastLED,选择最新的版本安装,FastLED库的更多使用方法可以参考 http://www.taichi-maker.com/homepage/reference-index/arduino-library-index/fastled-library/

  2)  物联网开发平台库 Blinker, 在Blinker 官网https://doc.blinker.app 页面下载最新的Blinker库,然后:

    Window将下载好的blinker库解压到 我的电脑>文档>Arduino>libraries 文件夹中
    Mac OS将下载好的blinker库解压到
文稿>Arduino>libraries 文件夹中

    可以在文件->示例 查看库是否安装成功。

3.2 连接线路

  具体的线路图由于时间原因没有画,所以直接按照后续的代码可以找到每个模块的连接方式,当然这些连接方式都可以自定义,然后在代码内做简单修改即可。需要注意的是蓝牙模块采用软串口连接,即RX,TX连接在ARDUINO UNO的2 和 3 号脚,而不是0和1 号脚,这个在BLINKER的网站上会说明,如果你代码烧录不了,查查是不是这个原因。

3.3 代码编写

 #define BLINKER_PRINT Serial
#define BLINKER_BLE #include <FastLED.h>
#include <Blinker.h> /** BASIC CONFIGURATION **/ //The amount of LEDs in the setup
#define NUM_LEDS 100
//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 300.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 CYCLES 30 * 1000 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 = ; //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 = ; //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] = {-}; //Longer sound avg
int long_avg[LONG_SECTOR] = {-}; // LED Model 1/Music LED 2/Color LED
int LED_Model = ; //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;
// when you use the MusicLED as a Color LED
CRGB LEDColor(,,);
uint8_t Bright = ; // declare the button
BlinkerRGB RGB1("RGBKey");
BlinkerButton Button1("switch"); // rgb1_callback
void rgb1_callback(uint8_t r_value, uint8_t g_value, uint8_t b_value, uint8_t bright_value)
{
// change the color of strip by your set on Blinker
LEDColor.r = r_value;
LEDColor.g = g_value;
LEDColor.b = b_value;
Bright = bright_value;
fill_solid(leds,NUM_LEDS,LEDColor); FastLED.show();
} void button1_callback(const String & state) {
if(LED_Model == )
{
LEDColor.r = ;
LEDColor.g = ;
LEDColor.b = ;
Bright = ;
fill_solid(leds,NUM_LEDS,LEDColor);
BLINKER_LOG2("strip_state: ","OFF");
LED_Model = ;
}
else if(LED_Model == )
{
LED_Model = ;
}
FastLED.show();
} void setup() {
Serial.begin();
//Set all lights to make sure all are working as expected
FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
for (int i = ; i < NUM_LEDS; i++)
leds[i] = CRGB(, , );
FastLED.show();
delay(); //bootstrap average with some low values
for (int i = ; i < AVGLEN; i++) {
insert(, avgs, AVGLEN);
} //Initial values
high.times = ;
high.times_start = millis();
Color.r = ;
Color.g = ;
Color.b = ; Blinker.begin();
//attach the RGB1 SlidersRGB
RGB1.attach(rgb1_callback);
Button1.attach(button1_callback);
} /*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() {
Blinker.run(); if(LED_Model == )
visualize_music(); 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 != ) {
if (millis() - high.times_start > 200.0) {
high.times = ;
songmode = NORMAL;
} else {
high.times_start = millis();
high.times++;
}
} else {
high.times++;
high.times_start = millis(); }
}
if (high.times > && millis() - high.times_start < 50.0)
songmode = HIGH;
else if (millis() - high.times_start > ) {
high.times = ;
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);
Serial.println(sensor_value); //If 0, discard immediately. Probably not right and save CPU.
if (sensor_value == )
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*0.8)) //|| ((avg - mapped) < -avg*0.8))
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 = ;
} longavg = compute_average(long_avg, LONG_SECTOR); //Check if we enter HIGH mode
check_high(longavg); if (songmode == HIGH) {
fade_scale = ;
Color.r = ;
Color.g = ;
Color.b = -;
}
else if (songmode == NORMAL) {
fade_scale = ;
Color.r = -;
Color.b = ;
Color.g = ;
} //Decides how many of the LEDs will be lit
curshow = fscale(MIC_LOW, MIC_HIGH, 0.0, (float)NUM_LEDS, (float)avg, -); /*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 = ; i < NUM_LEDS; i++)
//The leds we want to show
if (i < curshow) {
if (leds[i].r + Color.r > )
leds[i].r = ;
else if (leds[i].r + Color.r < )
leds[i].r = ;
else
leds[i].r = leds[i].r + Color.r; if (leds[i].g + Color.g > )
leds[i].g = ;
else if (leds[i].g + Color.g < )
leds[i].g = ;
else
leds[i].g = leds[i].g + Color.g; if (leds[i].b + Color.b > )
leds[i].b = ;
else if (leds[i].b + Color.b < )
leds[i].b = ;
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 = ;
for (int i = ; 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 = ; i < len; i++) {
if (avgs[i] == -) {
avgs[i] = val;
return;
}
} for (int i = ; i < len; i++) {
avgs[i - ] = avgs[i];
}
avgs[len - ] = 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 = ;
float NewRange = ;
float zeroRefCurVal = ;
float normalizedCurVal = ;
float rangedValue = ;
boolean invFlag = ; // condition curve parameter
// limit range if (curve > ) curve = ;
if (curve < -) curve = -; curve = (curve * -.) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
curve = pow(, 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 = ;
} 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 ;
} if (invFlag == ){
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin; }
else // invert the ranges
{
rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange);
} return rangedValue;
}

上述代码编译无误后上传到Arduino UNO即可。

3.4 下载并使用Blinker软件连接

  Blinker软件的安装包可以在官网上找到:

安装好之后注册账号,登陆,在主页面右上角选择-->添加设备-->Arduino-->蓝牙接入,然后会自动发现我们的蓝牙,连接上之后,如图。

上面表示是否已经连接,现在表示已连接。然后添加上面的两个组件,编辑组件参数如下:

完成之后便可以通过RGB滑条来控制颜色,通过模式按钮来控制灯的模式。

3.5 灯的组装

  我是自己在网上买的灯罩,然后根据自己的需求3D打印的底座,大家可以发挥自己的想象力来创作出不一样的外观~

 然后来一波安装完成的照片:

最后更新一波实测视频(由于不能同时录像和控制,所以只放了节奏灯效果):

地址:https://www.bilibili.com/video/av38471827/

  

基于Arduino的音乐动感节奏灯的更多相关文章

  1. arduino 蓝牙控制RGB LED灯

    /* 日期:2016.9.2 功能:arduino 蓝牙控制RGB LED灯 元件: 跳线公公头 * 8 rgbled, 220欧电阻 蓝牙模块 接线: 蓝牙模块VCC,GND分别接5V,GND;TX ...

  2. Recommending music on Spotify with deep learning 采用深度学习算法为Spotify做基于内容的音乐推荐

    本文参考http://blog.csdn.net/zdy0_2004/article/details/43896015译文以及原文file:///F:/%E6%9C%BA%E5%99%A8%E5%AD ...

  3. Android基于发展Service音乐播放器

    这是一个基于Service组件的音乐播放器,程序的音乐将会由后台的Service组件负责播放,当后台的播放状态改变时,程序将会通过发送广播通知前台Activity更新界面:当用户单击前台Activit ...

  4. 基于jQuery虾米音乐播放器样式代码

    分享一款基于jQuery虾米音乐播放器样式代码.这是一款基于jquery+html5实现的虾米音乐播放器源码下载.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div c ...

  5. 基于 Arduino 开发板,这款插座是可编程且开源的

    基于 Arduino 开发板,这款插座是可编程且开源的 https://www.oschina.net/news/74861/open-source-socket https://github.com ...

  6. 基于Arduino开发的智能蓝牙小车

    基于Arduino的智能蓝牙小车 材料准备: Arduino开发板一块.四驱小车底板及相关配件一套.L298N驱动模块一个.HC-05/06蓝牙模块一块,九伏电源一块(用于主板供电).12V锂电池一块 ...

  7. 基于arduino的红外传感系统

    一.作品背景 在这个科技飞速发展的时代,物联网已经成为了我们身边必不可少的技术模块,我这次课程设计做的是一个基于arduino+树莓派+OneNet的红外报警系统,它主要通过识别人或者动物的运动来判断 ...

  8. 基于arduino UNO R3+ESP8266控制LED灯的开关(无USB转TTL工具实现)

    最近由于项目要求,需要开发物联网云平台,而本人对硬件和通信技术一窍不通,故而选择arduino这一简单单片机来实现学习掌握基础的硬件和通信技术. 下面就是本人通过查阅大佬资料做的一个整合版本的通过手机 ...

  9. 基于 Arduino 的 RFID 识别实验

    http://www.it165.net/embed/html/201512/3287.html 2015年12月04日(周五) 上午  博士的智能卡实验--RFID识别实验,基于51单片机: 我们的 ...

随机推荐

  1. ios逆向工程

    原 ios逆向工程-内部钩子(Method Swizzling)   Method+Swizzling ios hook Method Swizzling(方法调配) 怎么说呢,先了解什么是钩子为什么 ...

  2. JS高级技巧学习小结

    安全类型检測 var isArray = value instanceof Array; 以上代码要返回true,value必须是一个数组,并且还必须与Array构造函数在同一个全局作用域中(Arra ...

  3. JAVA设计模式之:訪问者模式

    訪问者模式: 一个作用于某对象结构中各元素的操作,使你能够在不改变各元素类数据结构的前提下添加作用于这些元素的新操作. 结构对象是訪问者模式必备条件.且这个结构对象必须存在遍历自身各个对象的方法. 适 ...

  4. tiny4412学习(三)之移植linux-4.x驱动(1)支持网卡驱动【转】

    本文转载自:http://blog.csdn.net/fengyuwuzu0519/article/details/74160686 一.思路 上一节我们通过DNW将内核.文件系统.设备树文件烧入到内 ...

  5. SQL SERVER 语句大全

    ·SQL的简单查询实例教程关键词:SQL语句大全 中文网 整理编辑,经典SQL语句大全(SQL语句大总结),欢迎网友投稿 下列语句部分是Mssql语句,不可以在access中使用.SQL分类:DDL— ...

  6. 【HAOI 2008】 糖果传递

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1045 [算法] 环形均分纸牌问题 [代码] #include<bits/std ...

  7. B2242 [SDOI2011]计算器

    这个题就是把三个数论基础合在了一起,算是一道比较全面的题. 1的时候就是快速幂 2的时候是exgcd求逆元,特殊的,只有两数互质才有逆元. 3就是bsgs啦,还是不太熟 题干: Description ...

  8. P3178 [HAOI2015]树上操作 树链剖分

    这个题就是一道树链剖分的裸题,但是需要有一个魔性操作___编号数组需要开longlong!!!震惊!真的神奇. 题干: 题目描述 有一棵点数为 N 的树,以点 为根,且树点有边权.然后有 M 个操作, ...

  9. bzoj1833

    http://www.lydsy.com/JudgeOnline/problem.php?id=1833 2.5个小时就花在这上面了... 水到200题了...然并卵,天天做水题有什么前途... #i ...

  10. SQL数据库还原的二种方式和区别

    1.数据库还原 在SQL中,直接选择选择“还原数据库”:选中.bak 文件即可. 2.生成脚本 新建同样的DB名字,在SQL打开脚本,执行脚本语言.数据库里面就会自动填充内容.