Inflatable LED ball responds to bumps with bright lights.
First topic
Hey, this one’s about how I crammed a bunch of LEDs, accelerometer, and a battery into a clear inflatable ball. It worked, it was great fun for weeks, the ball eventually popped. I call it another completed project. ![]()
![]() |
|---|
| Reactive LED ball prototype |
Hassles
Tuning the accelerometer was a small pile of trouble. Getting the ball to respond to the right frequency of successive acceleration peaks but not ‘double-trigger’ (“bounce” might be confusing here) proved tricky.
I ended up with a floor (baseline reading), threshhold (must peak past here to trigger), and de-bounce time (delay before another trigger is allowed). I have the LEDs fading quickly after each trigger to accentuate the next trigger.
You can see here how when I kick it it ‘double-triggers’ both from successive impacts and from some springy-ness netween the central tube and the outer ball.
![]() |
|---|
| Reactive LED ball prototype |
Full Code
//This program loops through very fast and if the total acceleration is greater than the threshhold, it will increment the hue and set the brightness of the LEDs up to a mapped value. Otherwise it will slowly decrease the brightness of the LEDs.
#include <MPU9250_asukiaaa.h>
#include "FastLED.h"
//#include "printf.h"
//#define FASTLED_INTERRUPT_RETRY_COUNT 5
#define DATA_PIN 4
#define NUM_LEDS 144
//#define BRIGHTNESS 30
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
#define UPDATES_PER_SECOND 100
CRGB leds[NUM_LEDS];
int h = 0; //prelim hue value
int s = 255; //saturation value
int v = 0; //prelim brightness value
int sampleLength = 40; //milliseconds between brightness adjustments
int accelThreshhold = 230; //threshhold for peak detection based on (sum of measured accelerations in each axis * 100)
int accelLimit = 400; //typical max acceleration - used to map measured acceleration values to brightness range
int hueIncrement = 32; //amount to jump down the hue scale
int vLowerBound = 15; //lowest brightness to return to after acceleration spike
int lastPeak = 0; //initialize acceleration peak time placeholder
int vMax = 235; //max allowable brightness
int vIncrement = 4; //every sampleLength, lower the brightness this much
int peakDelay = 2 00; //peaks in accelleration must be at least this many milliseconds apart to be detected
MPU9250 mySensor;
uint8_t sensorId;
float aX, aY, aZ, aSqrt, gX, gY, gZ, mDirection, mX, mY, mZ;
void setup() {
//while(!Serial);
Serial.begin(115200);
Serial.println("started");
Wire.begin();
mySensor.setWire(&Wire);
mySensor.beginAccel();
sensorId = mySensor.readId();
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
}
void loop() {
mySensor.accelUpdate();
aX = mySensor.accelX();
aY = mySensor.accelY();
aZ = mySensor.accelZ();
double accelTotal = (abs(aX) + abs(aY) + abs(aZ))*100; //sum of measured accelerations in each axis * 100;
if (accelTotal > accelThreshhold && millis() - lastPeak > peakDelay) {
lastPeak = millis();
v = map(constrain(accelTotal, 1, accelLimit), 1, accelLimit, 15, vMax); //set up map of acceleration values to brightness values
h = int(random(1, 255));
Serial.println("Peak detected!");
Serial.println("Acceleration: " + String(int(accelTotal))); //print accelTotal
Serial.println("HSV Values: " + String(h) + ", " + String(s) + ", " + String(v)); //print HSV values
}
EVERY_N_MILLISECONDS(sampleLength) { //slowly lower the brightness to 15
if (v > vLowerBound) {
v = v - vIncrement;
Serial.println("Brightness now: " + String(v));
}
}
FastLED.setBrightness(v); //publish to LEDs
fill_solid(leds, NUM_LEDS, CHSV(h, s, v));
FastLED.show();
}

