Sound-Reactive LED Strip using MSGEQ7 and FastLED

Creating a sound-reactive LED light show can be a fun and visually stunning project. In this post, we’ll be using an Arduino, the MSGEQ7 IC, and the FastLED library to create a vibrant LED strip that dances to the beat of your music. The full project can be seen here.

Project Components

  • An Arduino board.
  • An LED strip compatible with the FastLED library (we are using a WS2812B LED strip).
  • The MSGEQ7 IC to read audio data.
  • A suitable audio source.

The Code

First, we include the FastLED library and define some constants for our project:

#include "FastLED.h"

#define NUM_LEDS 60
#define FRAMES_PER_SECOND 60

#define MSGEQ7_STROBE_PIN 4
#define MSGEQ7_RESET_PIN 5
#define MSGEQ7_ANALOG_PIN A0
#define MSGEQ7_NUM_BANDS 7

Next, we create some global variables that we will use throughout the project:

CRGB leds[NUM_LEDS];
int MSGEQ7_values[MSGEQ7_NUM_BANDS];

float scale_factor = 3.0;
float bias = 1.2;
int max_brightness = 0;
int frame_count = 0;
float color_offset = 0;

In the setup() function, we initialize the LED strip and set up the pins for the MSGEQ7:

void setup() {
  FastLED.addLeds<WS2812B, 6, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(255);

  pinMode(MSGEQ7_STROBE_PIN, OUTPUT);
  pinMode(MSGEQ7_RESET_PIN, OUTPUT);
  
  digitalWrite(MSGEQ7_RESET_PIN, LOW);
  digitalWrite(MSGEQ7_STROBE_PIN, HIGH);
}

In the loop() function, we read the values from the MSGEQ7, calculate the brightness and hue for each LED, display the LEDs, and update the scale_factor and bias values:

void loop() {
  read_msgeq7();

  for (int i = 0; i < NUM_LEDS; i++) {
    int band = i % MSGEQ7_NUM_BANDS;

    int brightness = pow(MSGEQ7_values[band], scale_factor * bias);
    brightness = constrain(brightness, 0, 255);
    max_brightness = max(max_brightness, brightness);

    int hue = band * (256 / MSGEQ7_NUM_BANDS) + color_offset;
    leds[i] = CHSV(hue, 255, brightness);
  }

  color_offset = fmod(color_offset + 0.5, 256.0);

  FastLED.show();
  FastLED.delay(1000/FRAMES_PER_SECOND);

  frame_count++;
  if (frame_count >= 60) {
    if (max_brightness < 100) {
      scale_factor *= 1.2;
      bias += 0.1;
    } else if (max_brightness > 200) {
      scale_factor *= 0.9;
      bias -= 0.05;
    }

    scale_factor = constrain(scale_factor, 2.0, 4.0);
    bias = constrain(bias, 1.0, 1.5);

    max_brightness = 0;
    frame_count = 0;
  }
}

Finally, we have the read_msgeq7() function, which reads the audio data from the MSGEQ7 chip:

void read_msgeq7() {
  digitalWrite(MSGEQ7_RESET_PIN, HIGH);
  digitalWrite(MSGEQ7_RESET_PIN, LOW);

  for (int i = 0; i < MSGEQ7_NUM_BANDS; i++) {
    digitalWrite(MSGEQ7_STROBE_PIN, LOW);
    delayMicroseconds(30);

    MSGEQ7_values[i] = analogRead(MSGEQ7_ANALOG_PIN);
    digitalWrite(MSGEQ7_STROBE_PIN, HIGH);
  }
}

How It Works

  1. The MSGEQ7 chip splits the audio signal into 7 frequency bands (from low to high) and outputs a value for each band that represents the volume of that frequency band in the audio signal.
  2. We read these values into the MSGEQ7_values array using the read_msgeq7() function.
  3. For each LED, we calculate a brightness based on the corresponding frequency band’s value. We use a power function to enhance the contrast between low and high volumes, with the scale_factor controlling how much contrast there is and the bias allowing us to adjust the contrast dynamically.
  4. We also calculate a hue for each LED based on its frequency band and a color_offset, which we increment each frame to create a “rotating” color effect.
  5. We then use the FastLED library to set the color and brightness of each LED and update the LED strip.
  6. Every 60 frames (roughly once per second at 60 frames per second), we update the scale_factor and bias based on the maximum brightness observed in the last second. If the brightness was too low, we increase the scale_factor and bias to make the brightness changes more pronounced. If the brightness was too high, we decrease them to make the brightness changes less pronounced

Customizing Your Light Show

The beauty of this project lies in its flexibility. By tweaking a few parameters, you can create a unique LED light show that aligns perfectly with your personal preferences. Here are a few variables to consider adjusting:

  1. scale_factor and bias: These two variables directly influence the responsiveness of your LED strip to the music. They control the contrast in brightness between low and high volumes. If you want your LED strip to react more drastically to changes in the volume of the music, you can increase these values. Conversely, if you want a more subtle reaction, you can decrease them. Remember that increasing these values too much may cause the LEDs to be either too dim or too bright, so it’s all about finding a balance that suits your preferences. For example, to get more reactive LEDs simply adjust these lines:
if (max_brightness < 100) {
    scale_factor *= 2.0;
    bias += 0.3;
} else if (max_brightness > 200) {
    scale_factor *= 0.8;
    bias -= 0.05;
}

// Constrain the scale/bias factor to a reasonable range
scale_factor = constrain(scale_factor, 2.0, 10.0);
bias = constrain(bias, 1.0, 2.0);
  1. FRAMES_PER_SECOND: This constant controls the rate at which the LED colors are updated. A higher value will result in smoother color transitions but may be more demanding on your Arduino. Conversely, a lower value may be less smooth but easier on your Arduino.
  2. color_offset: This variable is used to create the rotating color effect. If you want the colors to rotate faster, you can increase the amount by which color_offset is incremented in each frame. Conversely, if you want the colors to rotate slower, you can decrease this amount. For example, to slow down the Hue rotation use:
color_offset = fmod(color_offset + 0.3, 256.0);
  1. NUM_LEDS and MSGEQ7_NUM_BANDS: The number of LEDs on your strip (NUM_LEDS) and the number of frequency bands from your MSGEQ7 (MSGEQ7_NUM_BANDS) also influence the look of your light show. If you want each frequency band to be represented by more LEDs, you can increase NUM_LEDS or decrease MSGEQ7_NUM_BANDS. Conversely, if you want each frequency band to be represented by fewer LEDs, you can decrease NUM_LEDS or increase MSGEQ7_NUM_BANDS.

And that’s it! This creates a dynamic light show that changes in both color and brightness in response to your music.

Leave a Reply

Your email address will not be published. Required fields are marked *