36浏览
查看: 36|回复: 2

[项目] 【Arduino 动手做】使用Max4466的音乐互动LED灯带

[复制链接]
这是使用 Arduino Nano 和驻极体麦克风/Max4466 放大器的另一个版本的音乐 LED 灯带。

我14岁的侄女开始喜欢音乐了,所以我想给她做点很酷的东西放在她的房间里。我一直对声音互动项目很感兴趣,所以这是一个很好的学习项目。

演示
这是 Youtube 上的演示。

介绍
这个项目非常简单,已经做过无数次了,但对我来说,把一堆碎片拼凑在一起并打包成一个有趣的“最终产品”很有趣。

我使用 Arduino Nano 作为基础。使用 FFT 库将声音解码成八度音阶,使用 FASTLed 库驱动 LED 灯带,并使用一个旧的 iPhone C 外壳将它们固定在一起。

关于软件/功能的一些说明:
1)我使用 10kOhm POT 来控制声音灵敏度
2) 麦克风/放大器对噪音很敏感,所以我用接地的金属胶带屏蔽了电线/导线……这很有帮助。
3)该漫画以几种方式作出回应。
根据每个八度的音量改变颜色/亮度/饱和度
在整个灯带上重复相同的 11 个 LED 图案(但会改变颜色并改变每个组的颜色,使其看起来更连续
随着声音越来越大,图案沿着条带追逐
音量最大时,它会短暂地闪烁白色
你需要测试粉红噪声才能正确调整。每个电路板的情况都不同
4) 我用了一个旧的12V 1.5A壁式电源作为电源。功率有点小……但如果她不太用力的话应该没问题。我觉得24V 2A的电源会更好。另外,我可以在LED的电源上放一个更大的电容(而不是只放一个470uF的)。这样可以减少电流的爆发。下次……

【Arduino 动手做】使用Max4466的音乐互动LED灯带图1

【Arduino 动手做】使用Max4466的音乐互动LED灯带图2

【Arduino 动手做】使用Max4466的音乐互动LED灯带图5

【Arduino 动手做】使用Max4466的音乐互动LED灯带图3

【Arduino 动手做】使用Max4466的音乐互动LED灯带图4

驴友花雕  中级技神
 楼主|

发表于 7 天前

【Arduino 动手做】使用Max4466的音乐互动LED灯带

项目代码

  1. #include "FastLED.h"
  2. // How many leds in your strip?
  3. #include <FastLED.h>
  4. #define OCTAVE 1 //   // Group buckets into octaves  (use the log output function LOG_OUT 1)
  5. #define OCT_NORM 0 // Don't normalise octave intensities by number of bins
  6. #define FHT_N 256 // set to 256 point fht
  7. #include <FHT.h> // include the library
  8. //int noise[] = {204,188,68,73,150,98,88,68}; // noise level determined by playing pink noise and seeing levels [trial and error]{204,188,68,73,150,98,88,68}
  9. // int noise[] = {204,190,108,85,65,65,55,60}; // noise for mega adk
  10. //int noise[] = {204,195,100,90,85,80,75,75}; // noise for NANO
  11. int noise[] = {204,198,100,85,85,80,80,80};
  12. float noise_fact[] = {15, 7, 1.5, 1, 1.2, 1.4, 1.7,3}; // noise level determined by playing pink noise and seeing levels [trial and error]{204,188,68,73,150,98,88,68}
  13. float noise_fact_adj[] = {15, 7, 1.5, 1, 1.2, 1.4, 1.7,3}; // noise level determined by playing pink noise and seeing levels [trial and error]{204,188,68,73,150,98,88,68}
  14. #define LED_PIN     5
  15. #define LED_TYPE    WS2811
  16. #define COLOR_ORDER GRB
  17. // Params for width and height
  18. const uint8_t kMatrixWidth = 11;
  19. const uint8_t kMatrixHeight = 27;
  20. #define NUM_LEDS (kMatrixWidth * kMatrixHeight)
  21. //#define NUM_LEDS    15
  22. CRGB leds[NUM_LEDS];
  23. int counter2=0;
  24. void setup() {
  25. //  Serial.begin(115200);
  26.   delay(1000);
  27.   FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  28.   
  29.   FastLED.setBrightness (200);
  30.   fill_solid(leds, NUM_LEDS, CRGB::Black);
  31.   FastLED.show();   
  32. // TIMSK0 = 0; // turn off timer0 for lower jitter
  33.   ADCSRA = 0xe5; // set the adc to free running mode
  34.   ADMUX = 0x40; // use adc0
  35.   DIDR0 = 0x01; // turn off the digital input for adc0
  36. }
  37. void loop() {
  38. int prev_j[8];
  39. int beat=0;
  40. int prev_oct_j;
  41. int counter=0;
  42. int prev_beat=0;
  43. int led_index=0;
  44. int saturation=0;
  45. int saturation_prev=0;
  46. int brightness=0;
  47. int brightness_prev=0;
  48. while (1) { // reduces jitter
  49.       cli();  // UDRE interrupt slows this way down on arduino1.0
  50.      
  51.   for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
  52.       while (!(ADCSRA & 0x10)); // wait for adc to be ready
  53.       ADCSRA = 0xf5; // restart adc
  54.       byte m = ADCL; // fetch adc data
  55.       byte j = ADCH;
  56.       int k = (j << 8) | m; // form into an int
  57.       k -= 0x0200; // form into a signed int
  58.       k <<= 6; // form into a 16b signed int
  59.       fht_input[i] = k; // put real data into bins
  60.     }
  61.     fht_window(); // window the data for better frequency response
  62.     fht_reorder(); // reorder the data before doing the fht
  63.     fht_run(); // process the data in the fht
  64.     fht_mag_octave(); // take the output of the fht  fht_mag_log()
  65.    // every 50th loop, adjust the volume accourding to the value on A2 (Pot)
  66.     if (counter >= 50) {
  67.       ADMUX = 0x40 | (1 & 0x07); // set admux to look at Analogpin A1 - Master Volume
  68.       while (!(ADCSRA & 0x10)); // wait for adc to be ready
  69.       ADCSRA = 0xf5; // restart adc
  70.   delay(10);      
  71.       while (!(ADCSRA & 0x10)); // wait for adc to be ready
  72.       ADCSRA = 0xf5; // restart adc
  73.       byte m = ADCL; // fetch adc data
  74.       byte j = ADCH;
  75.       int k = (j << 8) | m; // form into an int
  76.       float master_volume=(k+0.1)/1000 +.5;  // so the valu will be between ~0.5 and 1.5
  77. // Serial.println (master_volume);
  78.       for (int i=1; i<8; i++) {
  79.           noise_fact_adj[i]=noise_fact[i]*master_volume;
  80.       }
  81.       ADMUX = 0x40 | (0 & 0x07); // set admux back to look at A0 analog pin (to read the microphone input
  82.       counter = 0;
  83.     }
  84.         
  85.     sei();
  86.     counter++;
  87.      
  88.     // End of Fourier Transform code - output is stored in fht_oct_out[i].
  89.     // i=0-7 frequency (octave) bins (don't use 0 or 1), fht_oct_out[1]= amplitude of frequency for bin 1
  90.     // for loop a) removes background noise average and takes absolute value b) low / high pass filter as still very noisy
  91.     // c) maps amplitude of octave to a colour between blue and red d) sets pixel colour to amplitude of each frequency (octave)
  92.     for (int i = 1; i < 8; i++) {  // goes through each octave. skip the first 1, which is not useful
  93.       int j;      
  94.       j = (fht_oct_out[i] - noise[i]); // take the pink noise average level out, take the asbolute value to avoid negative numbers
  95.       if (j<10) {j=0;}  
  96.       j= j*noise_fact_adj[i];
  97.       
  98.       if (j<10) {j=0;}
  99.       else {  
  100.         j= j*noise_fact_adj[i];
  101.         if (j>180) {
  102.           if (i>=7) {
  103.             beat+=2;
  104.           }
  105.           else {
  106.             beat+=1;
  107.           }
  108.         }
  109.         j=j/30;
  110.         j=j*30; // (force it to more discrete values)
  111.       }
  112.       
  113.       prev_j[i]=j;
  114. //     Serial.print(j);
  115. //     Serial.print(" ");
  116. // this fills in 11 LED's with interpolated values between each of the 8 OCT values
  117.        if (i>=2) {
  118.         led_index=2*i-3;
  119.         prev_oct_j=(j+prev_j[i-1])/2;
  120.         
  121.         saturation=constrain(j+30, 0,255);
  122.         saturation_prev=constrain(prev_oct_j+30, 0,255);
  123.         brightness=constrain(j, 0,255);
  124.         brightness_prev=constrain(prev_oct_j, 0,255);
  125. if (brightness==255) {
  126.   saturation=50;
  127.   brightness=200;
  128. }
  129. if (brightness_prev==255) {
  130.   saturation_prev=50;
  131.   brightness_prev=200;
  132. }
  133.         for (uint8_t y=0;y<kMatrixHeight;y++){  
  134.           leds[XY(led_index-1,y)] = CHSV(j+y*30,saturation, brightness);        
  135.           if (i>2){         
  136.             prev_oct_j=(j+prev_j[i-1])/2;
  137.             leds[ XY(led_index-2,y)]=CHSV(prev_oct_j+y*30,saturation_prev, brightness_prev);            
  138.           }              
  139.         }
  140.        }
  141.     }
  142.       
  143.       if (beat>=7) {
  144.           fill_solid(leds, NUM_LEDS, CRGB::Gray);         
  145.           FastLED.setBrightness(120);
  146. //    FastLED.setBrightness(200);
  147.       }                 
  148.     else {
  149.       if (prev_beat!=beat) {
  150.         FastLED.setBrightness(40+beat*beat*5);
  151.         prev_beat=beat;
  152.       }
  153.     }
  154.     FastLED.show();
  155.     if (beat) {
  156.       counter2+=((beat+4)/2-2);
  157.       if (counter2<0) {counter2=1000;}
  158.       if (beat>3 && beat<7) {
  159.          FastLED.delay (20);
  160.       }
  161.       beat=0;
  162.     }
  163. // Serial.println();
  164. }
  165. }
  166. // Param for different pixel layouts
  167. const bool    kMatrixSerpentineLayout = true;
  168. // Set 'kMatrixSerpentineLayout' to false if your pixels are
  169. // laid out all running the same way, like this:
  170. // Set 'kMatrixSerpentineLayout' to true if your pixels are
  171. // laid out back-and-forth, like this:
  172. uint16_t XY( uint8_t x, uint8_t y)
  173. {
  174.   uint16_t i;
  175.   
  176.   if( kMatrixSerpentineLayout == false) {
  177.     i = (y * kMatrixWidth) + x;
  178.   }
  179.   if( kMatrixSerpentineLayout == true) {
  180.     if( y & 0x01) {
  181.       // Odd rows run backwards
  182.       uint8_t reverseX = (kMatrixWidth - 1) - x;
  183.       i = (y * kMatrixWidth) + reverseX;
  184.     } else {
  185.       // Even rows run forwards
  186.       i = (y * kMatrixWidth) + x;
  187.     }
  188.   }
  189.   
  190.   i=(i+counter2)%NUM_LEDS;  
  191.   return i;
  192. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 7 天前

【Arduino 动手做】使用Max4466的音乐互动LED灯带

【Arduino 动手做】音乐互动LED灯带
项目链接:https://www.hackster.io/buzzandy/music-reactive-led-strip-5645ed
项目作者:buzzandy

项目视频 :https://www.youtube.com/watch?v=lHRquzNed8s
项目代码:https://www.hackster.io/code_files/155345/download

【Arduino 动手做】使用Max4466的音乐互动LED灯带图1

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail