muiscLED.ino 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*------------------------------------------------------------------------------
  2. 02/11/2020
  3. Author: Cisco • A C R O B O T I C
  4. Platforms: ESP32
  5. Language: C++/Arduino
  6. File: vu_meter.ino
  7. ------------------------------------------------------------------------------
  8. Description:
  9. Code for YouTube video tutorial demonstrating how to build a Volume Unit (VU)
  10. meter using an ESP32, a pair of NeoPixel/WS2812B LED sticks, and a MAX9814 mic.
  11. The audio signal is read from the mic, and a set of LEDs proportional to the
  12. amplitude lights up using a wide range of colors:
  13. https://youtu.be/xvG_kvhBECc
  14. ------------------------------------------------------------------------------
  15. Do you like my work? You can support me:
  16. https://patreon.com/acrobotic
  17. https://paypal.me/acrobotic
  18. https://buymeacoff.ee/acrobotic
  19. ------------------------------------------------------------------------------
  20. Please consider buying products and kits to help fund future Open-Source
  21. projects like this! We'll always put our best effort in every project, and
  22. release all our design files and code for you to use.
  23. https://acrobotic.com/
  24. https://amazon.com/shops/acrobotic
  25. ------------------------------------------------------------------------------
  26. License:
  27. Please see attached LICENSE.txt file for details.
  28. ------------------------------------------------------------------------------*/
  29. #include<FastLED.h>
  30. #include<MegunoLink.h>
  31. #include<Filter.h>
  32. // define necessary parameters
  33. #define N_PIXELS 12 //led灯珠数量
  34. #define MIC_PIN A0 //音频采集模块接口
  35. #define LED_PIN 13 //led灯带接口
  36. // the following parameters can be tweaked according to your audio levels
  37. #define NOISE 500
  38. #define TOP (N_PIXELS+2) // allow the max level to be slightly off scale
  39. #define LED_TYPE WS2811
  40. #define BRIGHTNESS 100 // a little dim for recording purposes
  41. #define COLOR_ORDER GRB
  42. // declare the LED array
  43. CRGB leds[N_PIXELS];
  44. // define the variables needed for the audio levels
  45. int lvl = 0, minLvl = 0, maxLvl = 40; // tweak the min and max as needed
  46. // instantiate the filter class for smoothing the raw audio signal
  47. ExponentialFilter<long> ADCFilter(5,0);
  48. void setup() {
  49. // put your setup code here, to run once:
  50. Serial.begin(115200);
  51. // initialize the LED object
  52. FastLED.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,N_PIXELS).setCorrection(TypicalLEDStrip);
  53. FastLED.setBrightness(BRIGHTNESS);
  54. }
  55. void loop() {
  56. // put your main code here, to run repeatedly:
  57. // read the audio signal and filter it
  58. int n, height;
  59. n = analogRead(MIC_PIN);
  60. // remove the MX9614 bias of 1.25VDC
  61. n = abs(1023 - n);
  62. // hard limit noise/hum
  63. //n = (n <= NOISE) ? 0 : abs(n - NOISE);
  64. // apply the exponential filter to smooth the raw signal
  65. ADCFilter.Filter(n);
  66. lvl = ADCFilter.Current();
  67. // plot the raw versus filtered signals
  68. //Serial.println(n);
  69. //Serial.print(" ");
  70. Serial.println(lvl);
  71. // calculate the number of pixels as a percentage of the range
  72. // TO-DO: can be done dynamically by using a running average of min/max audio levels
  73. height = TOP * (lvl - minLvl) / (long)(maxLvl - minLvl);
  74. if(height < 0L) height = 0;
  75. else if(height > TOP) height = TOP;
  76. // turn the LEDs corresponding to the level on/off
  77. for(uint8_t i = 0; i < N_PIXELS; i++) {
  78. // turn off LEDs above the current level
  79. if(i >= height) leds[i] = CRGB(0,0,0);
  80. // otherwise, turn them on!
  81. else leds[i] = Wheel( map( i, 0, N_PIXELS-1, 30, 150 ) );
  82. }
  83. FastLED.show();
  84. }
  85. CRGB Wheel(byte WheelPos) {
  86. // return a color value based on an input value between 0 and 255
  87. if(WheelPos < 85)
  88. return CRGB(WheelPos * 3, 255 - WheelPos * 3, 0);
  89. else if(WheelPos < 170) {
  90. WheelPos -= 85;
  91. return CRGB(255 - WheelPos * 3, 0, WheelPos * 3);
  92. } else {
  93. WheelPos -= 170;
  94. return CRGB(0, WheelPos * 3, 255 - WheelPos * 3);
  95. }
  96. }