OpenDrumLights: Revival
The project: RGB drums! LED strips within the drum heads that are triggered when hit. I have a friend who is a drummer and wanted his drums to light up. Commercial versions exist but they are not that cheap and offer limited customization. So we figured why not try to DIY?
Goals:
- programmable RGB, set any drum to any color
- ideally a simple UI for the drummer to select colors / patterns, per drum. Stretch: perhaps per song / set?
- 4 inputs(sensors) and outputs(lights) → 4 drums: kick, snare, tom 1, tom 2
- MIDI trigger to feed into DAWS or software of choice
- robust enough to take on stage (handle being plugged and unplugged during setup/teardown)
- simple enough to take on stage
- Stretch: DMX support?
I started this project a while ago and moved 2 times so it’s in rough state due to said moving.
The moving was not kind to my documentation either:
Using an Arduino as the brains. For triggers I chose some cheap piezoelectric sensors to detect vibration. The prototype uses paper plates as placeholder drums. For LED strips we choose individually addressable RGB strips: WS2812B
Figured I could use a USB-like format for each drum:
- VCC = 5VDC
- Data - = peizo → arduino analog in
- Data + = arduino PWM out → lights
- Ground = Ground
Arduino can put out 5v but not enough current to drive the strips. So external additional power is required. NOTE: ground from external power must be tied to arduino ground, otherwise lights flicker and weird noisy circuit. Common ground!
If it looks like a bit of a hacky mess, well it is…but it worked at one point!
Here is a test demo hooked up to a single drum.
Then I hooked up all 4 strips. Success! until the lm317 let out the magic smoke… turns out LM317 is only rated for about 1.5A…
I found that the WS2812B which draw about ~60mA @ 5V per led (white & full brightness). Using 4 x 144LED/M (LED per Meter) strips our worst case scenario is 60mA * 144 LED’s * 4 strips = ~3.4A.
So worst case scenario: 12v supply → 12V-5V=7v. Power = 7Vx4A = ~28W dissipated as heat. Ouch. But that’s with all on all the time. Realistically only a couple strips are on at a time as they are triggered.
So I switched to a buck converter that can handle 5V @ 3A-5A out.
The prototype code is pretty simple. 4 analog pins to read the peizo, and 4 PWM pins out to control the lights:
#include "MIDIUSB.h"
#include "FastLED.h"
//peizo inputs
#define analogIn1 1
#define analogIn2 2
#define analogIn3 3
#define analogIn4 4
#define threshold 100
int val1 = 0;
int val2 = 0;
int val3 = 0;
int val4 = 0;
//led outputs
#define pwmLEDout1 2
#define pwmLEDout2 3
#define pwmLEDout3 4
#define pwmLEDout4 5
#define NUM_LEDS 150
CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];
CRGB leds3[NUM_LEDS];
CRGB leds4[NUM_LEDS];
//midi outputs
void setup() {
Serial.begin(9600);
pinMode(pwmLEDout1, OUTPUT);
pinMode(pwmLEDout2, OUTPUT);
pinMode(pwmLEDout3, OUTPUT);
pinMode(pwmLEDout4, OUTPUT);
FastLED.addLeds<WS2812B, pwmLEDout1>(leds1, NUM_LEDS);
FastLED.addLeds<WS2812B, pwmLEDout2>(leds2, NUM_LEDS);
FastLED.addLeds<WS2812B, pwmLEDout3>(leds3, NUM_LEDS);
FastLED.addLeds<WS2812B, pwmLEDout4>(leds4, NUM_LEDS);
}
void loop() {
//read inputs
val1 = analogRead(analogIn1);
val2 = analogRead(analogIn2);
val3 = analogRead(analogIn3);
val4 = analogRead(analogIn4);
//drum 1
if (val1 > threshold) {
for (int i = 0; i < NUM_LEDS; i++) {
leds1[i] = CRGB::Green;
}
noteOn(0, 48, 100);
} else {
for (int i = 0; i < NUM_LEDS; i++) {
leds1[i] = CRGB::Black;
}
noteOff(0, 48, 100);
}
//drum2
if (val2 > threshold) {
for (int i = 0; i < NUM_LEDS; i++) {
leds2[i] = CRGB::Green;
}
noteOn(0, 49, 100);
} else {
for (int i = 0; i < NUM_LEDS; i++) {
leds2[i] = CRGB::Black;
}
noteOff(0, 49, 100);
}
//drum 3
if (val3 > threshold) {
for (int i = 0; i < NUM_LEDS; i++) {
leds3[i] = CRGB::Red;
}
noteOn(0, 50, 100);
} else {
for (int i = 0; i < NUM_LEDS; i++) {
leds3[i] = CRGB::Black;
}
noteOff(0, 50, 100);
}
//drum 4
if (val4 > threshold) {
for (int i = 0; i < NUM_LEDS; i++) {
leds4[i] = CRGB::Blue;
}
noteOn(0, 51, 100);
} else {
for (int i = 0; i < NUM_LEDS; i++) {
leds4[i] = CRGB::Black;
}
noteOff(0, 51, 100);
}
FastLED.show();
//serial debug
Serial.print(val1);
Serial.print(",");
Serial.print(val2);
Serial.print(",");
Serial.print(val3);
Serial.print(",");
Serial.println(val4);
}
void noteOn(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
}
void noteOff(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
}
todo: de-bounce inputs
The threshold would be the trigger value in this case. How sensitive should the sensors be to trigger. We don’t want the vibrations from adjacent drums to falsely trigger.
Libraries:
This was the initial set up but the piezo sensors kept breaking when attaching them directly to the underside of the drum, this direct vibration seems to crack the ceramic. They also kept falling off with just tape. A new solution is required.
Lessons learned:
- LM317’s are only rated for about 1.5A out max
- peizo sensors are brittle
So given that the piezo sensors attached directly to the head isn’t going to work, slight change of plans…