#include <Adafruit_NeoPixel.h>
#define PIN 2
#define NUM_PIXELS 32
#define NUM_PER_RING 16
#define LEFT_BTN 3
#define RIGHT_BTN 4
#define BRAKE_PIN 5
#define HAZARD_BTN 6
Adafruit_NeoPixel pixels(NUM_PIXELS, PIN, NEO_GRB + NEO_KHZ800);
// states
bool leftOn = false;
bool rightOn = false;
bool hazardOn = false;
// positions
int posLeft = 0;
int posRight = 0;
// color list (auto change)
uint32_t colors[] = {
Adafruit_NeoPixel::Color(255, 150, 0),
Adafruit_NeoPixel::Color(255, 0, 0),
Adafruit_NeoPixel::Color(255, 255, 0),
Adafruit_NeoPixel::Color(0, 255, 0),
Adafruit_NeoPixel::Color(0, 150, 255),
Adafruit_NeoPixel::Color(255, 0, 255),
Adafruit_NeoPixel::Color(255, 255, 255)
};
int colorIndex = 0;
int totalColors = sizeof(colors)/sizeof(colors[0]);
int sweepCount = 0;
int sweepChange = 4;
uint32_t brakeColor = Adafruit_NeoPixel::Color(255, 0, 0); // solid RED
void setup() {
pixels.begin();
pinMode(LEFT_BTN, INPUT_PULLUP);
pinMode(RIGHT_BTN, INPUT_PULLUP);
pinMode(HAZARD_BTN, INPUT_PULLUP);
pinMode(BRAKE_PIN, INPUT_PULLUP);
}
void loop() {
// -------- BUTTON INPUT --------
if (digitalRead(LEFT_BTN) == LOW) {
delay(200);
leftOn = !leftOn;
rightOn = false;
hazardOn = false;
}
if (digitalRead(RIGHT_BTN) == LOW) {
delay(200);
rightOn = !rightOn;
leftOn = false;
hazardOn = false;
}
if (digitalRead(HAZARD_BTN) == LOW) {
delay(200);
hazardOn = !hazardOn;
leftOn = false;
rightOn = false;
}
bool brakeActive = (digitalRead(BRAKE_PIN) == LOW);
// -------- BRAKE MODE OVERRIDES EVERYTHING --------
if (brakeActive) {
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, brakeColor);
}
pixels.show();
return; // skip all indicator animation
}
// -------- CLEAR LEDs --------
for (int i = 0; i < NUM_PIXELS; i++) pixels.setPixelColor(i, 0);
uint32_t col = colors[colorIndex];
// ---------- HAZARD MODE (both rings sweep) ----------
if (hazardOn) {
// left ring sweep
for (int i = 0; i < 4; i++) {
int idx = (posLeft + i) % NUM_PER_RING;
pixels.setPixelColor(idx, col);
}
// right ring sweep
for (int i = 0; i < 4; i++) {
int idx = (posRight + i) % NUM_PER_RING;
pixels.setPixelColor(idx + NUM_PER_RING, col);
}
posLeft++;
posRight++;
if (posLeft >= NUM_PER_RING) posLeft = 0;
if (posRight >= NUM_PER_RING) posRight = 0;
sweepCount++;
if (sweepCount >= sweepChange) {
colorIndex++;
if (colorIndex >= totalColors) colorIndex = 0;
sweepCount = 0;
}
}
// ---------- LEFT INDICATOR ----------
else if (leftOn) {
for (int i = 0; i < 4; i++) {
int idx = (posLeft + i) % NUM_PER_RING;
pixels.setPixelColor(idx, col);
}
posLeft++;
if (posLeft >= NUM_PER_RING) {
posLeft = 0;
sweepCount++;
if (sweepCount >= sweepChange) {
colorIndex++;
if (colorIndex >= totalColors) colorIndex = 0;
sweepCount = 0;
}
}
}
// ---------- RIGHT INDICATOR ----------
else if (rightOn) {
for (int i = 0; i < 4; i++) {
int idx = (posRight + i) % NUM_PER_RING;
pixels.setPixelColor(idx + NUM_PER_RING, col);
}
posRight++;
if (posRight >= NUM_PER_RING) {
posRight = 0;
sweepCount++;
if (sweepCount >= sweepChange) {
colorIndex++;
if (colorIndex >= totalColors) colorIndex = 0;
sweepCount = 0;
}
}
}
pixels.show();
delay(80);
}