音随律动 您所在的位置:网站首页 氛围灯音乐随动 音随律动

音随律动

2024-06-18 21:35| 来源: 网络整理| 查看: 265

音随律动-基于arduino-nano、ws2812灯带、KEYES麦克风检测模块的声光互动

利用arduino-nano,ws2812灯带以及KEYES麦克风检测模块做了个小项目,灯光可以随着音浪大小而起伏波动,貌似很带感(可以在宿舍蹦迪了(狗头)) 在这里插入图片描述

模块

如标题所述,主要就用到了三个模块,nano控制板,ws2812灯带以及麦克风模块。均可在淘宝购置。

方案

麦克风模块直接读取音量的大小,灯带是一个16X16的阵列。阵列的高度与音量是正相关的,音量越大,每一列亮的灯的数量也就越多,并在此基础上利用随机数模拟音浪起起伏伏的感觉。话不多说,上代码。

代码

首先是音量数据的读取。

int soundReadAndProcess() { int sum = 0; bool silence = false; for (int i=0;iVolumeValue = 250;} //主要是根据模拟量的大小,做了个限幅,这个可以根据你实际情况修改 if(VolumeValue silence = false; if(VolumeValue/50.0 columnLedNumber = 8;} else if(VolumeValue/50.0 columnLedNumber = 14;} else {columnLedNumber = 16;} //根据音量的大小分级,每级的初始化列亮的灯数不同 } if (silence) //如果静音,则不亮灯 { for (int i=0; i for (int i=0; irandonArray[i] = 16;} //每列最多有16个灯 //波浪灯光模拟,3表示波浪幅度大小,可调。 } } }

由于音量是模拟量,数据比较波动,所以简单的做了个均值处理,然后就是根据音量大小做了分级,每一级对应的各列初始化亮的灯数是不一样的。静音状态下不亮灯,超过两百则是全量。当然这个值也得根据自己测量而定,先用串口输出读取的模拟量值,然后测试一下最大,最低值即可。 randonArray这个数组就是记录16列每列实际亮的灯数,这个数就是在分级后的初始化灯数columnLedNumber加上或减去一个随机值,从而达到模拟音浪效果。

接下来就是对上面计算好的每列灯阵实际应该亮的进行控制。

void soundWaveAnalog() // 16*16 { int beginSeq = 0; for (int i=0; ibeginSeq = 16*i; numMinOrPlusFlag=true;} //根据点阵灯的结构,索引有加有减 else{beginSeq = 16*(i+1) -1; numMinOrPlusFlag=false;} for (int j=0; jbeginSeq++;} else{beginSeq--;} } for (int k=randonArray[i]; kbeginSeq++;} else{beginSeq--;} } } }

基本逻辑就是对16列进行遍历,每一列随机灯的颜色,由于这个灯带的顺序是“S”型的,所以有numMinOrPlusFlag标志来判断每列的灯带是递增或递减的。然后每列剩下的灯就置黑不亮了。

最后在loop函数中调用即可

void loop() { //Serial.println(VolumeValue); soundReadAndProcess(); if (millis() - waveTimer > waveInterval) { soundWaveAnalog(); waveTimer = millis(); } flawLed(); FastLED.show(); // 显示效果 }

首先读取麦克风音量值,然后每隔一段时间间隔执行音量模拟程序,这里之所以要间隔一段时间(大约是50ms),主要是不让灯变化的那么快,时间自己而定。最后FastLED.show();即可。

火焰金睛的你是后还发现了一个函数flawed(),哈哈哈哈这个是因为我之前还有一条灯带,所以本着不浪费的原则就充分利用了,主要就是一个辅助流水灯的效果。

void flawLed() { switch (flawState) { case 1: if (millis() - flawTimer > flawInterval1) { leds[second] = colorArray[color_order]; second++; if (second==256+60){second=256; color_order++;} if(color_order==8){color_order=0;flawState=2;} flawTimer = millis(); } break; case 2: if (millis() - flawTimer > flawInterval2) { int color_random = random(8); for (int i=256;istate_2_counter=0;flawState=1;} flawTimer = millis(); } break; } }

由于灯带是接在灯带阵列后面的,所以序号数是在原来256的基础上加了60。这里逻辑比较简单,就不赘诉了。状态一实现顺序亮并且变色的效果,状态二是随机不用颜色亮灭效果,两个效果自动切换。

最后附上所有代码

#include #define LED_PIN 7 //灯的引脚 #define NUM_LEDS 256+60 //灯的数量 CRGB leds[NUM_LEDS]; #define soundReadPin A0 //读取音量大小引脚 int VolumeValue = 0; int columnLedNumber = 0; int randonArray[16]; // 用于存放每列点阵中具体要量的灯的个数 bool numMinOrPlusFlag = false; // 由于点阵是s型的,所有灯的索引有加或者减 int second = 256; unsigned long waveTimer = 0; unsigned long waveInterval = 50; //用于控制每轮灯闪烁的时间,可调。 unsigned long flawTimer = 0; unsigned long flawInterval1 = 20; //用于控制每轮灯闪烁的时间,可调。 unsigned long flawInterval2 = 200; //用于控制每轮灯闪烁的时间,可调。 #define NUM_COLORS 8 CRGB colorArray[NUM_COLORS] = { CRGB::Red, // 红色 CRGB::Green, // 绿色 CRGB::Blue, // 蓝色 CRGB::Yellow, // 黄色 CRGB::Purple, // 紫色 CRGB::Cyan, // 青色 CRGB::Orange, // 橙色 CRGB::Pink // 粉色 }; int flawState = 1; int color_order = 0; int state_2_counter = 0; void setup() { FastLED.addLeds(leds, NUM_LEDS); //灯初始化 //Serial.begin(115200); } void loop() { //Serial.println(VolumeValue); soundReadAndProcess(); if (millis() - waveTimer > waveInterval) { soundWaveAnalog(); waveTimer = millis(); } flawLed(); FastLED.show(); // 显示效果 } int soundReadAndProcess() { int sum = 0; bool silence = false; for (int i=0;iVolumeValue = 250;} //主要是根据模拟量的大小,做了个限幅,这个可以根据你实际情况修改 if(VolumeValue silence = false; if(VolumeValue/50.0 columnLedNumber = 8;} else if(VolumeValue/50.0 columnLedNumber = 14;} else {columnLedNumber = 16;} //根据音量的大小分级,每级的初始化列亮的灯数不同 } if (silence) //如果静音,则不亮灯 { for (int i=0; i for (int i=0; irandonArray[i] = 16;} //每列最多有16个灯 //波浪灯光模拟,3表示波浪幅度大小,可调。 } } } void soundWaveAnalog() // 16*16 { int beginSeq = 0; for (int i=0; ibeginSeq = 16*i; numMinOrPlusFlag=true;} //根据点阵灯的结构,索引有加有减 else{beginSeq = 16*(i+1) -1; numMinOrPlusFlag=false;} for (int j=0; jbeginSeq++;} else{beginSeq--;} } for (int k=randonArray[i]; kbeginSeq++;} else{beginSeq--;} } } // FastLED.show(); // 显示效果 } void flawLed() { switch (flawState) { case 1: if (millis() - flawTimer > flawInterval1) { leds[second] = colorArray[color_order]; second++; if (second==256+60){second=256; color_order++;} if(color_order==8){color_order=0;flawState=2;} flawTimer = millis(); } break; case 2: if (millis() - flawTimer > flawInterval2) { int color_random = random(8); for (int i=256;istate_2_counter=0;flawState=1;} flawTimer = millis(); } break; } } 演示视频

链接: [https://www.bilibili.com/video/BV1vw411P7vE/?vd_source=60baa4220f53b74733d257650536919b]

总结

自己第一次分享,属于边学边记录,也想以此激励自己。所言有误之处恳请批评指正。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有