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