DIY Music Relative RGB Strip light

DIY Music Relative RGB Strip light © Apache-2.0

Hii friends Today I will Show You How To make Music Relative Strip Light

  • 12,949 views
  • 0 comments
  • 17 respects

Components and supplies

Apps and online services

About this project

Video

In this project I will be showing you How To Make DIY Music Relative Led Strip Light Using Arduino Nano Let's get started!

1st 🙏🏻Thanks🙏🏻 to NEXTPCB for sponsoring this video Visit NEXTPCB
to get professional PCBs for low prices Get start PCB From 0$ And Sign up This Link And Get Extra Coupan 👌

You Will Need Some Componenets For Make This Project

👉Parts list (): -👈 👇 Arduino UNO - https://amzn.to/3fljESD Arduino Nano - https://amzn.to/30a5VI3 RGB strip LED :- https://amzn.to/3gXEAPZ Sound Sensor :- https://amzn.to/38VsO5K Jumper Cable - https://amzn.to/2Zyt2vj

Componenets :-

The WS2812 however is a WS2811 placed inside a 5050 LED package.The 5050 LED is a very common 3 LED (Red, Green, Blue) package, in one 5mm x 5mm case.A WS2812 is the same package but with an additional WS2811 LED driver IC on board.

In the illustration below you’ll see the difference:On the left a 5050 RGB LED, on the right a WS2812 which combines a 5050 RGB LED with a WS2811 controller.Note how the layout of the “silver” tracks are almost identical in both images, yet the black (IC) block and the tiny wires are different (right).

5050 RGB LED (left) and WS2812 (right)

ANALOG LED STRIPS

These are NOT the kind of LED strips we use in this project!

In the illustration below we see first (top) a strip of single color LED’s – typically white, but can be purchased in different colors. The one below that is a multicolor strip (RGB pins are a give away) which allows us to set the color for the entire strip.

On each of these strips you’ll see (from left to right) first the LED as a white block, followed by an SMD resistor as a tiny back block.The examples below require 12V to operate.

Analog LED strips – Single color (top), Multicolor (bottom)

DIGITAL RGB LED strips

The digital strips are the ones we will use in this project.In particular: we will use the WS2812 in our project.

The cool part of a digital strip is that you address each LED individually, making very cool effects easy. Obviously the kind we’d like to use in our projects.

In the illustration below you can see the physical differences between the WS2801 and the WS2811/WS2812 strips.Unlike the analog strips: Most Digital RGB strips operate on 5 Volts!

Note:

  • Not all strips of the same “model”, look the same, but have typically a very similar layout.
  • strips can be sold as a white or a black strip (background strip).
  • Notice the arrows indicating Data direction.
  • WS2801 has 4 pins, where as the WS2811/WS2812 only has 3 pins.
  • There are digital strips that look like WS2801/WS2811/WS2812 strip, that are NOT based on any of these LED drivers.
  • Strips can be had in waterproof (in plastic “tube”) or for indoor use only.

Digital LED strip – WS2812 (top) and WS2801 (bottom)

WS2801 vs WS2812 pins

PIN

WS2801

WS2812

5V

Power (+5V)

Power (+5V)

CI

Clock signal Input

N/A

CO

Clock signal Output

N/A

DI

Data Input

Data Input

DO

Data Output

Data Output

GND

Ground or Common

Ground or Common

Making the Arduino WS2812 connection

Now that we have a WS2812 strip, time to hook it up to our Arduino (I used an Arduino UNO for this).

Power

Caution

A strip of LED’s will pull way too much power for your Arduino to handle, so always consider an additional 5V power supply.

Rule of thumb is : each RGB LED unit pulls about 60 mA (3x 20 mA, for Red, Green and Blue).

LED’s, even though they’re called power efficient, do need juice … and for each WS2812 we need up to 60 mA when the 3 LEDs inside are at maximum brightness at 5V.

Power Supply

You can use an external power supply for this purpose and even though my 1 meter strip theoretically needs 3.6 A at max brightness, my little 2A power supply managed to handle it – your milage may vary! (1 meter with 60 LEDs/meter = 60 * 60 mA = 3600 mA = 3.6 A max.)

A switching power supply is often ideal and pretty cheap – you might even have one or the other laying around from your old cellphone, just make sure it’s actually giving you 5 – 6V and not weird voltages like 12V or 16V or even more. Verification with a Voltage meter is recommended.

Arduino Connected to your Computer

Commonly, during testing, your Arduino is connected to your computer via a USB cable where the USB cable does not only program the microcontroller but will also provide power for the Arduino.

The DIN (data input) pin of the LED strip goes to Arduino PIN 6 with an optional 470Ω resistor in between.+5V of the LED strip goes to the +5V of extra power supply.GND of the LED strip goes to GND of the extra power supply and to the GND of the Arduino.The USB of the Arduino is connected to your computer.

Arduino & WS2812 – USB and External Power

Arduino Not connected to your computer

Once you’ve completed your prototyping, you could still keep using your Arduino for controlling the LED strip.

In that case you’d typically have the Arduino in a very different location, and thus not connected to your computer. In that case the extra power supply for the LEDs could be used to feed the Arduino as well.

The DIN (data input) pin of the LED strip goes to PIN 6 of the Arduino with an optional 470Ω resistor in between.+5V of the LED strip goes to the +5V of extra power supply and the +5V on your Arduino (or Vin).GND of the LED strip goes to GND of the extra power supply and to the GND of the Arduino.

Connect Strip Light with arduino


Step 15: Nextpcb

Nextpcb

if you don't make your PCBs yourself, where do you make them?Personally, I do not have the space and the courage (nor the skill) to do them myself.For SF, I turn to Util-Pocket, because I find that the quality is excellent for the price.For the DF (with metallic holes), I tried several companies, all of which do a good job, but it costs a lot.This time I addressed myself here. I had 3 circuits to do, totaling an average surface of 49 cm2.When I saw that the minimum quantity to order was 5 PCBs, I continued my order out of curiosity, just to see the quote.And when I saw the asking price, I placed the order. nextpcb


Also check out my other social media: Instagram: https://www.instagram.com/diyprojectslab/ Facebook: https://m.facebook.com/DiyProjectsLab/ Pinterest:https://www.pinterest.com/diyprojectslab

https://youtu.be/BQLkBnHP87I

Code

CodeArduino
#include <FastLED.h>

/** BASIC CONFIGURATION  **/

//The amount of LEDs in the setup
#define NUM_LEDS 60
//The pin that controls the LEDs
#define LED_PIN 6
//The pin that we read sensor values form
#define ANALOG_READ 0

//Confirmed microphone low value, and max value
#define MIC_LOW 0.0
#define MIC_HIGH 737.0
/** Other macros */
//How many previous sensor values effects the operating average?
#define AVGLEN 5
//How many previous sensor values decides if we are on a peak/HIGH (e.g. in a song)
#define LONG_SECTOR 50

//Mneumonics
#define HIGH 3
#define NORMAL 2

//How long do we keep the "current average" sound, before restarting the measuring
#define MSECS 30 * 1000
#define CYCLES MSECS / DELAY

/*Sometimes readings are wrong or strange. How much is a reading allowed
to deviate from the average to not be discarded? **/
#define DEV_THRESH 0.8

//Arduino loop delay
#define DELAY 1

float fscale( float originalMin, float originalMax, float newBegin, float newEnd, float inputValue, float curve);
void insert(int val, int *avgs, int len);
int compute_average(int *avgs, int len);
void visualize_music();

//How many LEDs to we display
int curshow = NUM_LEDS;

/*Not really used yet. Thought to be able to switch between sound reactive
mode, and general gradient pulsing/static color*/
int mode = 0;

//Showing different colors based on the mode.
int songmode = NORMAL;

//Average sound measurement the last CYCLES
unsigned long song_avg;

//The amount of iterations since the song_avg was reset
int iter = 0;

//The speed the LEDs fade to black if not relit
float fade_scale = 1.2;

//Led array
CRGB leds[NUM_LEDS];

/*Short sound avg used to "normalize" the input values.
We use the short average instead of using the sensor input directly */
int avgs[AVGLEN] = {-1};

//Longer sound avg
int long_avg[LONG_SECTOR] = {-1};

//Keeping track how often, and how long times we hit a certain mode
struct time_keeping {
  unsigned long times_start;
  short times;
};

//How much to increment or decrement each color every cycle
struct color {
  int r;
  int g;
  int b;
};

struct time_keeping high;
struct color Color; 

void setup() {
  Serial.begin(9600);
  //Set all lights to make sure all are working as expected
  FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
  for (int i = 0; i < NUM_LEDS; i++) 
    leds[i] = CRGB(0, 0, 255);
  FastLED.show(); 
  delay(1000);  

  //bootstrap average with some low values
  for (int i = 0; i < AVGLEN; i++) {  
    insert(250, avgs, AVGLEN);
  }

  //Initial values
  high.times = 0;
  high.times_start = millis();
  Color.r = 0;  
  Color.g = 0;
  Color.b = 1;
}

/*With this we can change the mode if we want to implement a general 
lamp feature, with for instance general pulsing. Maybe if the
sound is low for a while? */
void loop() {
  switch(mode) {
    case 0:
      visualize_music();
      break;
    default:
      break;
  }
    delay(DELAY);       // delay in between reads for stability
}


/**Funtion to check if the lamp should either enter a HIGH mode,
or revert to NORMAL if already in HIGH. If the sensors report values
that are higher than 1.1 times the average values, and this has happened
more than 30 times the last few milliseconds, it will enter HIGH mode. 
TODO: Not very well written, remove hardcoded values, and make it more
reusable and configurable.  */
void check_high(int avg) {
  if (avg > (song_avg/iter * 1.1))  {
    if (high.times != 0) {
      if (millis() - high.times_start > 200.0) {
        high.times = 0;
        songmode = NORMAL;
      } else {
        high.times_start = millis();  
        high.times++; 
      }
    } else {
      high.times++;
      high.times_start = millis();

    }
  }
  if (high.times > 30 && millis() - high.times_start < 50.0)
    songmode = HIGH;
  else if (millis() - high.times_start > 200) {
    high.times = 0;
    songmode = NORMAL;
  }
}

//Main function for visualizing the sounds in the lamp
void visualize_music() {
  int sensor_value, mapped, avg, longavg;
  
  //Actual sensor value
  sensor_value = analogRead(ANALOG_READ);
  
  //If 0, discard immediately. Probably not right and save CPU.
  if (sensor_value == 0)
    return;

  //Discard readings that deviates too much from the past avg.
  mapped = (float)fscale(MIC_LOW, MIC_HIGH, MIC_LOW, (float)MIC_HIGH, (float)sensor_value, 2.0);
  avg = compute_average(avgs, AVGLEN);

  if (((avg - mapped) > avg*DEV_THRESH)) //|| ((avg - mapped) < -avg*DEV_THRESH))
    return;
  
  //Insert new avg. values
  insert(mapped, avgs, AVGLEN); 
  insert(avg, long_avg, LONG_SECTOR); 

  //Compute the "song average" sensor value
  song_avg += avg;
  iter++;
  if (iter > CYCLES) {  
    song_avg = song_avg / iter;
    iter = 1;
  }
    
  longavg = compute_average(long_avg, LONG_SECTOR);

  //Check if we enter HIGH mode 
  check_high(longavg);  

  if (songmode == HIGH) {
    fade_scale = 3;
    Color.r = 5;
    Color.g = 3;
    Color.b = -1;
  }
  else if (songmode == NORMAL) {
    fade_scale = 2;
    Color.r = -1;
    Color.b = 2;
    Color.g = 1;
  }

  //Decides how many of the LEDs will be lit
  curshow = fscale(MIC_LOW, MIC_HIGH, 0.0, (float)NUM_LEDS, (float)avg, -1);

  /*Set the different leds. Control for too high and too low values.
          Fun thing to try: Dont account for overflow in one direction, 
    some interesting light effects appear! */
  for (int i = 0; i < NUM_LEDS; i++) 
    //The leds we want to show
    if (i < curshow) {
      if (leds[i].r + Color.r > 255)
        leds[i].r = 255;
      else if (leds[i].r + Color.r < 0)
        leds[i].r = 0;
      else
        leds[i].r = leds[i].r + Color.r;
          
      if (leds[i].g + Color.g > 255)
        leds[i].g = 255;
      else if (leds[i].g + Color.g < 0)
        leds[i].g = 0;
      else 
        leds[i].g = leds[i].g + Color.g;

      if (leds[i].b + Color.b > 255)
        leds[i].b = 255;
      else if (leds[i].b + Color.b < 0)
        leds[i].b = 0;
      else 
        leds[i].b = leds[i].b + Color.b;  
      
    //All the other LEDs begin their fading journey to eventual total darkness
    } else {
      leds[i] = CRGB(leds[i].r/fade_scale, leds[i].g/fade_scale, leds[i].b/fade_scale);
    }
  FastLED.show(); 
}
//Compute average of a int array, given the starting pointer and the length
int compute_average(int *avgs, int len) {
  int sum = 0;
  for (int i = 0; i < len; i++)
    sum += avgs[i];

  return (int)(sum / len);

}

//Insert a value into an array, and shift it down removing
//the first value if array already full 
void insert(int val, int *avgs, int len) {
  for (int i = 0; i < len; i++) {
    if (avgs[i] == -1) {
      avgs[i] = val;
      return;
    }  
  }

  for (int i = 1; i < len; i++) {
    avgs[i - 1] = avgs[i];
  }
  avgs[len - 1] = val;
}

//Function imported from the arduino website.
//Basically map, but with a curve on the scale (can be non-uniform).
float fscale( float originalMin, float originalMax, float newBegin, float
    newEnd, float inputValue, float curve){

  float OriginalRange = 0;
  float NewRange = 0;
  float zeroRefCurVal = 0;
  float normalizedCurVal = 0;
  float rangedValue = 0;
  boolean invFlag = 0;


  // condition curve parameter
  // limit range

  if (curve > 10) curve = 10;
  if (curve < -10) curve = -10;

  curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output 
  curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function

  // Check for out of range inputValues
  if (inputValue < originalMin) {
    inputValue = originalMin;
  }
  if (inputValue > originalMax) {
    inputValue = originalMax;
  }

  // Zero Refference the values
  OriginalRange = originalMax - originalMin;

  if (newEnd > newBegin){ 
    NewRange = newEnd - newBegin;
  }
  else
  {
    NewRange = newBegin - newEnd; 
    invFlag = 1;
  }

  zeroRefCurVal = inputValue - originalMin;
  normalizedCurVal  =  zeroRefCurVal / OriginalRange;   // normalize to 0 - 1 float

  // Check for originalMin > originalMax  - the math for all other cases i.e. negative numbers seems to work out fine 
  if (originalMin > originalMax ) {
    return 0;
  }

  if (invFlag == 0){
    rangedValue =  (pow(normalizedCurVal, curve) * NewRange) + newBegin;

  }
  else     // invert the ranges
  {   
    rangedValue =  newBegin - (pow(normalizedCurVal, curve) * NewRange); 
  }

  return rangedValue;
}

Schematics

Comments

Similar projects you might like

Music Reactive LED Strip

Project showcase by buzzandy

  • 162,390 views
  • 96 comments
  • 266 respects

Arduino controlled RGB LED strip

Project tutorial by Raphael Nestler and Danilo Bargen

  • 31,925 views
  • 2 comments
  • 37 respects

Laser Stem RGB Matrix

Project showcase by Unexpected Maker

  • 11,631 views
  • 5 comments
  • 68 respects

DIY Arduino 1D Pong Game with WS2812 LED Strip

Project tutorial by Mirko Pavleski

  • 5,877 views
  • 10 comments
  • 17 respects

DIY ! Smartphone Controller Car ! Light & Horn

Project tutorial by DIY Projects Lab

  • 5,683 views
  • 2 comments
  • 20 respects
Add projectSign up / Login