Added reverse light and police flashing.

This commit is contained in:
ThePendulum
2026-04-30 17:38:26 +02:00
parent 58cb843106
commit c3c9299ca3

View File

@@ -7,6 +7,7 @@ constexpr int KEEPALIVE_TIMEOUT = 5000; // ms
constexpr int LEDS_TAIL_PIN = PA6;
constexpr int LEDS_TAIL_LENGTH = 10;
constexpr int LEDS_TAIL_BRIGHTNESS = 255;
constexpr int LEDS_TAIL_SIDE_LENGTH = 3;
constexpr int LEDS_LEFT_PIN = PA5;
constexpr int LEDS_RIGHT_PIN = PA7;
@@ -30,9 +31,9 @@ constexpr int PIN_PEDAL = PA0;
constexpr int PIN_PEDAL_FORWARD = PA3;
constexpr int PIN_PEDAL_REVERSE = PA4;
constexpr int PIN_BUTTON_MODE = PB8;
constexpr int PIN_BUTTON_LEFT = PB7;
constexpr int PIN_BUTTON_RIGHT = PB9;
constexpr int PIN_BUTTON_MODE = PA9;
constexpr int PIN_BUTTON_LEFT = PA8;
constexpr int PIN_BUTTON_RIGHT = PA10;
constexpr int LED_ON = LOW;
constexpr int LED_OFF = HIGH;
@@ -61,6 +62,8 @@ Adafruit_NeoPixel ledsDash(LEDS_DASH_LENGTH, LEDS_DASH_PIN, NEO_GRBW + NEO_KHZ80
const uint32_t COLOR_OFF = ledsTail.Color(0, 0, 0, 0);
const uint32_t COLOR_WHITE = ledsTail.Color(0, 0, 0, 255);
const uint32_t COLOR_WHITE_FULL = ledsTail.Color(255, 255, 255, 255);
const uint32_t COLOR_WHITE_DIM = ledsTail.Color(0, 0, 0, 100);
const uint32_t COLOR_RED = ledsTail.Color(255, 0, 0, 0);
const uint32_t COLOR_AMBER = ledsTail.Color(255, 50, 0, 0);
const uint32_t COLOR_POLICE_BLUE = ledsTail.Color(0, 0, 255, 0);
@@ -82,12 +85,15 @@ unsigned long animationFrame = 0;
unsigned long lastFrame = 0;
unsigned long lastPedalPress = millis();
bool isReversing = false;
unsigned long indicatorLeftStart = 0;
unsigned long indicatorRightStart = 0;
bool indicatorLeftActive = false;
bool indicatorRightActive = false;
bool policeActive = false;
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
@@ -138,6 +144,14 @@ void animateHeadlights() {
ledsHeadRight.fill(COLOR_WHITE);
}
void animateTailLight() {
ledsTail.fill(COLOR_RED);
}
void animateReverse() {
ledsTail.fill(COLOR_WHITE);
}
constexpr int INDICATOR_DURATION = 3000; // total ms
constexpr int INDICATOR_HOLD_FRAMES = 15;
constexpr int INDICATOR_OFF_FRAMES = 20;
@@ -186,24 +200,60 @@ void animateIndicator(Direction direction) {
ledsDash.fill(COLOR_OFF);
}
}
constexpr float POLICE_SPEED = 0.75;
void animate(long now) {
if (pedalForward.read() == Button::PRESSED) {
ledsTail.fill(ledsTail.Color(255, 0, 0, 0));
lastPedalPress = now;
enum PoliceStates { POLICE_LEFT, POLICE_RIGHT, POLICE_OFF };
Serial.println("PEDAL FORWARD");
} else if (pedalReverse.read() == Button::PRESSED) {
ledsTail.fill(ledsTail.Color(0, 0, 0, 255));
lastPedalPress = now;
const PoliceStates policeBeaconFrames[12] = {
POLICE_LEFT,
POLICE_OFF,
POLICE_LEFT,
POLICE_OFF,
POLICE_OFF,
POLICE_OFF,
POLICE_RIGHT,
POLICE_OFF,
POLICE_RIGHT,
POLICE_OFF,
POLICE_OFF,
POLICE_OFF,
};
Serial.println("PEDAL REVERSE");
void animatePolice() {
const long policeFrame = lround(animationFrame * POLICE_SPEED) % 12;
if (policeBeaconFrames[policeFrame] == POLICE_LEFT) {
ledsHeadLeft.fill(COLOR_POLICE_BLUE, 0, LEDS_EDGE_LENGTH);
ledsHeadRight.fill(COLOR_OFF, 0, LEDS_EDGE_LENGTH);
} else if (policeBeaconFrames[policeFrame] == POLICE_RIGHT) {
ledsHeadLeft.fill(COLOR_OFF, 0, LEDS_EDGE_LENGTH);
ledsHeadRight.fill(COLOR_POLICE_BLUE, 0, LEDS_EDGE_LENGTH);
} else {
ledsTail.fill(ledsTail.Color(100, 0, 0, 0));
ledsHeadLeft.fill(COLOR_OFF, 0, LEDS_EDGE_LENGTH);
ledsHeadRight.fill(COLOR_OFF, 0, LEDS_EDGE_LENGTH);
}
if (policeFrame < 6) {
ledsHeadLeft.fill(COLOR_WHITE_DIM, LEDS_EDGE_LENGTH, LEDS_EDGE_LENGTH + LEDS_RING_LENGTH);
ledsHeadRight.fill(COLOR_WHITE, LEDS_EDGE_LENGTH, LEDS_EDGE_LENGTH + LEDS_RING_LENGTH);
} else {
ledsHeadLeft.fill(COLOR_WHITE, LEDS_EDGE_LENGTH, LEDS_EDGE_LENGTH + LEDS_RING_LENGTH);
ledsHeadRight.fill(COLOR_WHITE_DIM, LEDS_EDGE_LENGTH, LEDS_EDGE_LENGTH + LEDS_RING_LENGTH);
}
}
void animate(long now) {
// always animate headlights, let other modes override
animateHeadlights();
animateTailLight();
if (isReversing) {
animateReverse();
}
if (activeMode == MODE_POLICE) {
animatePolice();
}
// we need the boolean to prevent the indicators from turning on right after boot
if (indicatorLeftActive && now - indicatorLeftStart < INDICATOR_DURATION) {
@@ -227,16 +277,15 @@ void loop() {
const unsigned long now = millis();
if (buttonMode.pressed()) {
ledsTail.fill(ledsTail.Color(0, 0, 255, 0));
activeMode = (Mode)((activeMode + 1) % MODE_COUNT);
animationFrame = 0; // ensures animations start cleanly instead of halfway
Serial.print("BUTTON MODE ");
Serial.println(activeMode);
}
if (buttonLeft.pressed()) {
animationFrame = 0; // ensures animations start cleanly instead of halfway
animationFrame = 0;
indicatorLeftActive = true;
indicatorLeftStart = now;
@@ -248,7 +297,7 @@ void loop() {
}
if (buttonRight.pressed()) {
animationFrame = 0; // ensures animations start cleanly instead of halfway
animationFrame = 0;
indicatorRightActive = true;
indicatorRightStart = now;
@@ -259,6 +308,21 @@ void loop() {
Serial.println("BUTTON RIGHT");
}
if (pedalReverse.read() == Button::PRESSED && pedalForward.read() != Button::PRESSED) {
lastPedalPress = now;
isReversing = true;
Serial.println("PEDAL REVERSE");
} else {
isReversing = false;
}
if (pedalForward.read() == Button::PRESSED) {
lastPedalPress = now;
Serial.println("PEDAL FORWARD");
}
if (now - lastFrame >= ANIMATION_INTERVAL) {
lastFrame += ANIMATION_INTERVAL;
animationFrame += 1;