CODE
#include <Adafruit_NeoPixel.h>
#define LED_PIN 6
#define LED_COUNT 60
#define MIC_PIN A0
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
int center = LED_COUNT / 2;
float smoothedLevel = 0;
float ballPos = 0;
const float fallSpeed = 0.20; // Gravity fall speed
float sensitivity = 5.0; // Adjust: 2–6 for bass intensity
int noiseFloor = 0;
void setup() {
strip.begin();
strip.show();
Serial.begin(9600);
// Detect ambient noise floor
long sum = 0;
for (int i = 0; i < 300; i++) {
sum += analogRead(MIC_PIN);
delay(4);
}
noiseFloor = sum / 300;
}
void loop() {
int micValue = analogRead(MIC_PIN);
int soundLevel = abs(micValue - noiseFloor);
if (soundLevel < 5) soundLevel = 0;
soundLevel *= sensitivity;
int level = map(soundLevel, 0, 50, 0, center);
level = constrain(level, 0, center);
// Smooth bar movement
smoothedLevel = (smoothedLevel * 0.85) + (level * 0.15);
// 🔴 Gravity ball control
if (smoothedLevel > ballPos) ballPos = smoothedLevel; // Jump
ballPos -= fallSpeed; // Fall slowly
if (ballPos < 0) ballPos = 0;
strip.clear();
// 🔴 Center LED always RED
strip.setPixelColor(center, 255, 0, 0);
// 🎨 Smooth gradient color bars
for (int i = 1; i < smoothedLevel; i++) {
int leftPixel = center - i;
int rightPixel = center + i;
byte r = 0, g = 0, b = 0;
float percent = (float)i / center;
if (percent <= 0.25) { // Blue → Green
float t = percent / 0.25;
r = 0;
g = 255 * t;
b = 255 * (1 - t);
}
else if (percent <= 0.50) { // Green → Yellow
float t = (percent - 0.25) / 0.25;
r = 255 * t;
g = 255;
b = 0;
}
else if (percent <= 0.75) { // Yellow → Orange
float t = (percent - 0.50) / 0.25;
r = 255;
g = 255 - (175 * t);
b = 0;
}
else { // Orange → Red
float t = (percent - 0.75) / 0.25;
r = 255;
g = 10 * (1 - t);
b = 0;
}
// ⚠ Skip pixels that overlap with ball or center
if (leftPixel != center - ballPos && leftPixel >= 0)
strip.setPixelColor(leftPixel, r, g, b);
if (rightPixel != center + ballPos && rightPixel < LED_COUNT)
strip.setPixelColor(rightPixel, r, g, b);
}
// 🔵 Dynamic 0–5 blue LEDs per side (bass reactive)
int bassLEDs = map(soundLevel, 0, 300, 0, 5);
bassLEDs = constrain(bassLEDs, 0, 5);
for (int j = 0; j < bassLEDs; j++) {
int leftPeak = center - ballPos - j;
int rightPeak = center + ballPos + j;
// ⚠ Only if not center or ball position
if (leftPeak >= 0 && leftPeak != center && leftPeak != center - ballPos)
strip.setPixelColor(leftPeak, 0, 0, 255);
if (rightPeak < LED_COUNT && rightPeak != center && rightPeak != center + ballPos)
strip.setPixelColor(rightPeak, 0, 0, 255);
}
// 🔴 Gravity balls (RED)
int leftBall = center - ballPos;
int rightBall = center + ballPos;
if (leftBall >= 0)
strip.setPixelColor(leftBall, 255, 0, 0);
if (rightBall < LED_COUNT)
strip.setPixelColor(rightBall, 255, 0, 0);
strip.show();
delay(1);
}
