Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* rainbow sound
- By: Andrew Tuline
- Date: Jan, 2022
- Running on an Arduino Nano, this sketch demonstrates the ability to add sound reactivity to non-reactive FastLED
- animations without modifying their code.
- The concept here is to take away brightness from an animation instead of adding it (like usual).
- It does so by blending the results of the existing (and unmodified animation) with the results of the sound
- reactive code prior to calling FastLED.show().
- In order to keep the code simple, this version uses a basic rainbow march, however the concept works well with
- more complex animations.
- Instructions:
- * Comment out the soundAdjust(); routine in the loop to see the original animation.
- * Remove the comment and see how it works with sound reactivity.
- This version has been developed around an Arduino Nano (old bootloader), with a MAX9814 microphone @40db gain.
- I've connected the AREF pin to 3.3V and connected VCC of the microphone to 3.3V as well.
- Am also considering changing the CRGB::Black (below) with a CRGB array that's more dynamic.
- */
- #include <FastLED.h>
- #define MIC_PIN A5 // Analog port for microphone
- uint8_t squelch = 20; // Anything below this is background noise, so we'll make it '0'.
- int sample; // Current sample.
- float sampleAvg = 0; // Smoothed Average.
- float micLev = 0; // Used to convert returned value to have '0' as minimum.
- int sampleAgc; // Automatic Gain Controlled value.
- int multAgc; // Multiplier for the AGC.
- uint8_t targetAgc = 60; // This is our setPoint at 20% of max for the adjusted output.
- #define LED_DT 12
- #define COLOR_ORDER GRB
- #define LED_TYPE WS2812
- #define NUM_LEDS 64
- struct CRGB leds[NUM_LEDS];
- uint8_t vals[NUM_LEDS]; // Used for sound reactivity blending.
- void setup() {
- Serial.begin(115200);
- analogReference(EXTERNAL); // Nano or other 5V AVR when using a 3.3V microphone. Also connect AREF pin to 3.3V.
- LEDS.addLeds<LED_TYPE, LED_DT, COLOR_ORDER>(leds, NUM_LEDS);
- FastLED.setBrightness(92);
- } // setup()
- void loop() {
- getSample(); // Sample the microphone.
- agcAvg(); // Calculated the AGC average.
- rainbow(); // Run the unmodified animation.
- soundAdjust(); // Insert sound reactive modfications before displaying.
- FastLED.show(); // Display.
- } // loop()
- void soundAdjust() {
- vals[millis() % NUM_LEDS] = sampleAgc; // This requires a high refresh rate.
- for (int i = 0; i < NUM_LEDS; i++) { // Modifying the array prior to FastLED.show().
- 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.
- }
- } // soundAdjust()
- void rainbow() {
- fill_rainbow(leds, NUM_LEDS, millis() / 10, 5); // A real basic FastLED rainbow march.
- } // rainbow()
- void getSample() {
- int16_t micIn; // Current sample starts with negative values and large values, which is why it's 16 bit signed.
- micIn = analogRead(MIC_PIN); // Poor man's analog read.
- micLev = ((micLev * 31) + micIn) / 32; // Use exponential smoothing over the last 32 samples for automatic centering.
- micIn -= micLev; // Let's center it to 0. This allows us to use ANY microphone without having to worry about offset calculations.
- micIn = abs(micIn); // And get the absolute value of each sample.
- sample = (micIn <= squelch) ? 0 : (sample + micIn) / 2; // Let's filter out the background noise with a ternary operator and more exponential smoothing.
- sampleAvg = ((sampleAvg * 31) + sample) / 32; // Smooth it out over the last 32 samples. This is a non AGC average.
- } // getSample()
- void agcAvg() { // A simple averaging multiplier to automatically adjust sound sensitivity.
- multAgc = (sampleAvg < 1) ? targetAgc : targetAgc / sampleAvg; // Make the multiplier so that sampleAvg * multiplier = setpoint
- sampleAgc = sample * multAgc;
- if (sampleAgc > 255) sampleAgc = 255;
- } // agcAvg()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement