Advertisement
atuline

rainbow_sound.ino

Jan 8th, 2022
708
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.75 KB | None | 0 0
  1. /* rainbow sound
  2.  
  3.    By: Andrew Tuline
  4.  
  5.    Date: Jan, 2022
  6.  
  7.  
  8.    Running on an Arduino Nano, this sketch demonstrates the ability to add sound reactivity to non-reactive FastLED
  9.    animations without modifying their code.
  10.  
  11.    The concept here is to take away brightness from an animation instead of adding it (like usual).
  12.    
  13.    It does so by blending the results of the existing (and unmodified animation) with the results of the sound
  14.    reactive code prior to calling FastLED.show().
  15.  
  16.    In order to keep the code simple, this version uses a basic rainbow march, however the concept works well with
  17.    more complex animations.
  18.  
  19.    Instructions:
  20.  
  21.    * Comment out the soundAdjust(); routine in the loop to see the original animation.
  22.    * Remove the comment and see how it works with sound reactivity.
  23.  
  24.    This version has been developed around an Arduino Nano (old bootloader), with a MAX9814 microphone @40db gain.
  25.  
  26.    I've connected the AREF pin to 3.3V and connected VCC of the microphone to 3.3V as well.
  27.  
  28.    Am also considering changing the CRGB::Black (below) with a CRGB array that's more dynamic.
  29.  
  30. */
  31.  
  32.  
  33. #include <FastLED.h>
  34.  
  35. #define MIC_PIN   A5                                          // Analog port for microphone
  36. uint8_t squelch = 20;                                         // Anything below this is background noise, so we'll make it '0'.
  37. int sample;                                                   // Current sample.
  38. float sampleAvg = 0;                                          // Smoothed Average.
  39. float micLev = 0;                                             // Used to convert returned value to have '0' as minimum.
  40.  
  41. int sampleAgc;                                                // Automatic Gain Controlled value.
  42. int multAgc;                                                  // Multiplier for the AGC.
  43. uint8_t targetAgc = 60;                                       // This is our setPoint at 20% of max for the adjusted output.
  44.  
  45.  
  46. #define LED_DT 12
  47. #define COLOR_ORDER GRB
  48. #define LED_TYPE WS2812
  49. #define NUM_LEDS 64
  50.  
  51. struct CRGB leds[NUM_LEDS];
  52.  
  53. uint8_t vals[NUM_LEDS];                                       // Used for sound reactivity blending.
  54.  
  55.  
  56.  
  57. void setup() {
  58.   Serial.begin(115200);
  59.   analogReference(EXTERNAL);                                  // Nano or other 5V AVR when using a 3.3V microphone. Also connect AREF pin to 3.3V.
  60.   LEDS.addLeds<LED_TYPE, LED_DT, COLOR_ORDER>(leds, NUM_LEDS);
  61.   FastLED.setBrightness(92);
  62. } // setup()
  63.  
  64.  
  65.  
  66. void loop() {
  67.  
  68.   getSample();                        // Sample the microphone.
  69.   agcAvg();                           // Calculated the AGC average.
  70.  
  71.   rainbow();                          // Run the unmodified animation.
  72.  
  73.   soundAdjust();                      // Insert sound reactive modfications before displaying.
  74.   FastLED.show();                     // Display.
  75.  
  76. } // loop()
  77.  
  78.  
  79.  
  80. void soundAdjust() {
  81.  
  82.   vals[millis() % NUM_LEDS] = sampleAgc;              // This requires a high refresh rate.
  83.  
  84.   for (int i = 0; i < NUM_LEDS; i++) {                // Modifying the array prior to FastLED.show().
  85.     leds[i] = blend(CRGB::Black, leds[i], vals[i]);   // vals[i] is a uint8_t, which determines the blending between the two colours for the resultant value.
  86.   }
  87.  
  88. } // soundAdjust()
  89.  
  90.  
  91.  
  92. void rainbow() {
  93.   fill_rainbow(leds, NUM_LEDS, millis() / 10, 5);     // A real basic FastLED rainbow march.
  94. } // rainbow()
  95.  
  96.  
  97.  
  98. void getSample() {
  99.  
  100.   int16_t micIn;                                              // Current sample starts with negative values and large values, which is why it's 16 bit signed.
  101.  
  102.   micIn = analogRead(MIC_PIN);                                // Poor man's analog read.
  103.   micLev = ((micLev * 31) + micIn) / 32;                      // Use exponential smoothing over the last 32 samples for automatic centering.
  104.   micIn -= micLev;                                            // Let's center it to 0. This allows us to use ANY microphone without having to worry about offset calculations.
  105.   micIn = abs(micIn);                                         // And get the absolute value of each sample.
  106.  
  107.   sample = (micIn <= squelch) ? 0 : (sample + micIn) / 2;     // Let's filter out the background noise with a ternary operator and more exponential smoothing.
  108.   sampleAvg = ((sampleAvg * 31) + sample) / 32;               // Smooth it out over the last 32 samples. This is a non AGC average.
  109.  
  110. } // getSample()
  111.  
  112.  
  113.  
  114. void agcAvg() {                                                   // A simple averaging multiplier to automatically adjust sound sensitivity.
  115.   multAgc = (sampleAvg < 1) ? targetAgc : targetAgc / sampleAvg;  // Make the multiplier so that sampleAvg * multiplier = setpoint
  116.   sampleAgc = sample * multAgc;
  117.   if (sampleAgc > 255) sampleAgc = 255;
  118. } // agcAvg()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement