diff --git a/main/accessors/settingsaccessors.h b/main/accessors/settingsaccessors.h index 6170d8e..50660a5 100644 --- a/main/accessors/settingsaccessors.h +++ b/main/accessors/settingsaccessors.h @@ -205,6 +205,9 @@ struct LedstripEnableBlinkAnimationAccessor : public NewSettingsAccessor { struct LedstripOtaAnimationAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.ledstrip.otaMode; } }; struct LedstripEnableVisualizeBlinkAnimationAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.ledstrip.enableVisualizeBlink; } }; struct LedstripAutomaticLightAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.ledstrip.automaticLight; } }; +struct LedstripBrakeLightUseAccelAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.ledstrip.brakeLights_useAccel; } }; +struct LedstripBrakeLightUsePowerAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.ledstrip.brakeLights_usePower; } }; + // Battery struct BatterySeriesCellsAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.battery.cellsSeries; } }; diff --git a/main/bobbyblinker.cpp b/main/bobbyblinker.cpp index 3754a77..20d7c0e 100644 --- a/main/bobbyblinker.cpp +++ b/main/bobbyblinker.cpp @@ -60,23 +60,18 @@ namespace bobbyblinker { } if (configs.ledstrip.enableBrakeLights.value() && espchrono::ago(*brake_last_time_sent) > 500ms) { - float avgPwm{}; - for (const Controller &controller: controllers) { - avgPwm += - controller.command.left.pwm * (controller.invertLeft ? -1 : 1) + - controller.command.right.pwm * (controller.invertRight ? -1 : 1); - } - avgPwm /= 4; - - if (avgPwm < -1.f) + if (brakeLightsStatus == brakeLightsOffSent) { - sendState("BRAKELIGHTSON"); - brakeLightsOffSent = false; - } - else if (!brakeLightsOffSent && avgPwm > -1.f) - { - sendState("BRAKELIGHTSOFF"); - brakeLightsOffSent = true; + if (brakeLightsStatus) + { + sendState("BRAKELIGHTSON"); + brakeLightsOffSent = false; + } + else if (!brakeLightsOffSent) + { + sendState("BRAKELIGHTSOFF"); + brakeLightsOffSent = true; + } } } } diff --git a/main/displays/menus/debugmenu.cpp b/main/displays/menus/debugmenu.cpp index 4eadaf9..327a546 100644 --- a/main/displays/menus/debugmenu.cpp +++ b/main/displays/menus/debugmenu.cpp @@ -62,6 +62,15 @@ constexpr char TEXT_ERASENVS[] = "Erase NVS (old)"; constexpr char TEXT_RESET_NVS_NEW[] = "Reset NVS (new)"; constexpr char TEXT_DYNAMICMENU[] = "GUI experiments"; constexpr char TEXT_BACK[] = "Back"; + +class AccelerationText : public virtual espgui::TextInterface +{ +public: + std::string text() const override + { + return fmt::format("Accel: {:.6f}", avgAccel); + } +}; } // namespace DebugMenu::DebugMenu() @@ -82,6 +91,7 @@ DebugMenu::DebugMenu() #ifdef FEATURE_CAN constructMenuItem, DisabledColor, DummyAction>>(); #endif + constructMenuItem, DisabledColor, DummyAction>>(); constructMenuItem>(); constructMenuItem, PushScreenAction>>(); constructMenuItem, PushScreenAction>>(); diff --git a/main/displays/menus/ledstripmenu.cpp b/main/displays/menus/ledstripmenu.cpp index 93ecf35..c4f108d 100644 --- a/main/displays/menus/ledstripmenu.cpp +++ b/main/displays/menus/ledstripmenu.cpp @@ -48,6 +48,8 @@ constexpr char TEXT_ANIMATION_MULTIPLIER[] = "Animation Multiplier"; constexpr char TEXT_LEDSTRIP_BRIGHTNESS[] = "Ledstrip Brightness"; constexpr char TEXT_LEDSTRIP_ALLCUSTOMOFF[] = "All custom off"; constexpr char TEXT_LEDSTRIP_CHANGE_OTA_ANIM[] = "Change Ota animation"; +constexpr char TEXT_LEDSTRIP_BRAKE_USE_ACCEL[] = "Brakelight use acceleration"; +constexpr char TEXT_LEDSTRIP_BRAKE_USE_POWER[] = "Brakelight use motor power"; constexpr char TEXT_BACK[] = "Back"; using LedsCountChangeScreen = espgui::makeComponent< @@ -179,6 +181,8 @@ LedstripMenu::LedstripMenu() if (!simplified) { constructMenuItem, espgui::PushScreenAction>>(); } if (!simplified) { constructMenuItem, espgui::PushScreenAction>>(); } if (!simplified) { constructMenuItem>>(); } + constructMenuItem, BobbyCheckbox, LedstripBrakeLightUseAccelAccessor>>(); + constructMenuItem, BobbyCheckbox, LedstripBrakeLightUsePowerAccessor>>(); constructMenuItem, espgui::PushScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); } diff --git a/main/displays/menus/ledstripselectanimationmenu.cpp b/main/displays/menus/ledstripselectanimationmenu.cpp deleted file mode 100644 index 6d7a6cf..0000000 --- a/main/displays/menus/ledstripselectanimationmenu.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "ledstripselectanimationmenu.h" - -// Local includes -#include "actions/dummyaction.h" -#include "actions/ledstripanimationactions.h" -#include "actions/popscreenaction.h" -#include "icons/back.h" -#include "ledstripdefines.h" -#include "ledstripmenu.h" -#include "newsettings.h" - -#ifdef FEATURE_LEDSTRIP -namespace { -constexpr char TEXT_SELECTANIMATION[] = "Select Animation"; -constexpr char TEXT_ANIMATION_DEFAULTRAINBOW[] = "Default Rainbow"; -constexpr char TEXT_ANIMATION_BETTERRAINBOW[] = "Better Rainbow"; -constexpr char TEXT_ANIMATION_SPEEDSYNCANIMATION[] = "Speed Sync"; -constexpr char TEXT_ANIMATION_CUSTOMCOLOR[] = "Custom Color"; -constexpr char TEXT_BACK[] = "Back"; - -class CurrentSelectedAnimationText : public virtual espgui::TextInterface -{ -public: - std::string text() const override; -}; - -} // namespace - -LedstripSelectAnimationMenu::LedstripSelectAnimationMenu() -{ - using namespace espgui; - - constructMenuItem>(); - constructMenuItem>(); - constructMenuItem, LedStripSetAnimationAction>>(); - constructMenuItem, LedStripSetAnimationAction>>(); - constructMenuItem, LedStripSetAnimationAction>>(); - constructMenuItem, LedStripSetAnimationAction>>(); - constructMenuItem, PopScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); -} - -std::string LedstripSelectAnimationMenu::text() const -{ - return TEXT_SELECTANIMATION; -} - -void LedstripSelectAnimationMenu::back() -{ - espgui::popScreen(); -} - -namespace { - -std::string CurrentSelectedAnimationText::text() const -{ - switch (configs.ledstrip.animationType.value) - { - case LedstripAnimation::DefaultRainbow: - return TEXT_ANIMATION_DEFAULTRAINBOW; - case LedstripAnimation::BetterRainbow: - return TEXT_ANIMATION_BETTERRAINBOW; - case LedstripAnimation::SpeedSync: - return TEXT_ANIMATION_SPEEDSYNCANIMATION; - case LedstripAnimation::CustomColor: - return TEXT_ANIMATION_CUSTOMCOLOR; - default: - return "Animation Unkown"; - } -} - -} // namespace -#endif diff --git a/main/globals.cpp b/main/globals.cpp index 30ec1b1..279e2b9 100644 --- a/main/globals.cpp +++ b/main/globals.cpp @@ -15,8 +15,12 @@ float gametrakDist; float avgSpeed{}; float avgSpeedKmh{}; float sumCurrent{}; +float lastAvgSpeedKmh{}; +float avgAccel{}; bool isLocked{}; +espchrono::millis_clock::time_point lastAvgSpeedKmhTs{}; + std::optional sunrise; std::optional sunset; std::optional sunrise_dt; diff --git a/main/globals.h b/main/globals.h index 1a92e71..ecf7c5e 100644 --- a/main/globals.h +++ b/main/globals.h @@ -53,8 +53,12 @@ extern esp_pm_config_esp32_t pm_config; extern float avgSpeed; extern float avgSpeedKmh; +extern float lastAvgSpeedKmh; +extern float avgAccel; extern float sumCurrent; +extern espchrono::millis_clock::time_point lastAvgSpeedKmhTs; + extern bool isLocked; #ifdef GLOBALS_PLUGIN diff --git a/main/ledstrip.cpp b/main/ledstrip.cpp index 91a775c..dc4dd3e 100644 --- a/main/ledstrip.cpp +++ b/main/ledstrip.cpp @@ -19,10 +19,53 @@ std::vector leds; uint8_t gHue = 0; float gLedPosition = 0; // yes, this is intendet as a float value! Do NOT change! +bool brakeLightsStatus; + +espchrono::millis_clock::time_point brakeLightTimer; + uint16_t blinkAnimation = LEDSTRIP_OVERWRITE_NONE; namespace { - bool initialized{false}; +bool initialized{false}; + +bool brakeLights() +{ + float avgPwm{}; + for (const Controller &controller : controllers) + { + avgPwm += + controller.command.left.pwm * (controller.invertLeft ? -1 : 1) + + controller.command.right.pwm * (controller.invertRight ? -1 : 1); + } + avgPwm /= 4; + + if (avgPwm < -1.f) + { + return true; + } + + if (configs.ledstrip.brakeLights_useAccel.value() && (avgAccel < -0.001f && avgSpeedKmh > 2.f)) + { + return true; + } + + if (espchrono::ago(brakeLightTimer) < 200ms) + { + return true; + } + + if (configs.ledstrip.brakeLights_usePower.value() && brakeLightsStatus) + { + if (const auto avgVoltage = controllers.getAvgVoltage(); avgVoltage) + { + const auto watt = sumCurrent * *avgVoltage; + + return watt < -1; + } + } + + return false; +} } // namespace void initLedStrip() @@ -140,20 +183,17 @@ void updateLedStrip() { if (configs.ledstrip.enableBrakeLights.value()) { - float avgPwm{}; - for (const Controller &controller : controllers) + // avgAccel in m/s/s + if (brakeLights()) { - avgPwm += - controller.command.left.pwm * (controller.invertLeft ? -1 : 1) + - controller.command.right.pwm * (controller.invertRight ? -1 : 1); - } - avgPwm /= 4; + if (!(espchrono::ago(brakeLightTimer) < 200ms)) + { + brakeLightTimer = espchrono::millis_clock::now(); + } - if (avgPwm < -1.f) - { auto color = avgSpeedKmh < -0.1f ? CRGB{255, 255, 255} : CRGB{255, 0, 0}; - const auto center = (std::begin(leds) + (leds.size() / 2) + configs.ledstrip.centerOffset.value()); + brakeLightsStatus = true; std::fill(std::begin(leds), std::end(leds), CRGB{0, 0, 0}); if (configs.ledstrip.enableFullBlink.value()) @@ -162,12 +202,15 @@ void updateLedStrip() } else if(!configs.ledstrip.enableAnimBlink.value()) { + const auto center = (std::begin(leds) + (leds.size() / 2) + configs.ledstrip.centerOffset.value()); + std::fill(center - configs.ledstrip.bigOffset.value() - 2, center - configs.ledstrip.smallOffset.value() + 2, color); std::fill(center + configs.ledstrip.smallOffset.value() - 2, center + configs.ledstrip.bigOffset.value() + 2, color); } } else { + brakeLightsStatus = false; showAnimation(); } } diff --git a/main/ledstrip.h b/main/ledstrip.h index 1f263c3..9f75e27 100644 --- a/main/ledstrip.h +++ b/main/ledstrip.h @@ -4,6 +4,7 @@ #include // 3rdparty lib includes +#include #include // local includes @@ -44,6 +45,10 @@ extern float gLedPosition; // yes, this is intendet as a float value! Do NOT cha extern uint16_t blinkAnimation; +extern bool brakeLightsStatus; + +extern espchrono::millis_clock::time_point brakeLightTimer; + void showDefaultLedstrip(); void showAnimation(); void showBetterRainbow(); diff --git a/main/newsettings.h b/main/newsettings.h index cb5f37e..2a2f6e2 100644 --- a/main/newsettings.h +++ b/main/newsettings.h @@ -415,6 +415,8 @@ public: }; ConfigWrapperLegacy leds_per_meter {144, DoReset, {}, "ledsPerMeter" }; ConfigWrapperLegacy automaticLight {false, DoReset, {}, "nightLights" }; + ConfigWrapperLegacy brakeLights_useAccel {false, DoReset, {}, "brakeLightsA" }; + ConfigWrapperLegacy brakeLights_usePower {false, DoReset, {}, "brakeLightsP" }; } ledstrip; struct { @@ -749,6 +751,8 @@ public: x(ledstrip.maxMilliamps) \ x(ledstrip.enableVisualizeBlink)\ x(ledstrip.automaticLight) \ + x(ledstrip.brakeLights_useAccel) \ + x(ledstrip.brakeLights_usePower) \ \ x(ledstrip.custom_color[0]) \ x(ledstrip.custom_color[1]) \ diff --git a/main/utils.cpp b/main/utils.cpp index 5ed372f..b6e00fb 100644 --- a/main/utils.cpp +++ b/main/utils.cpp @@ -248,6 +248,28 @@ void updateAccumulators() sumCurrent = fixCurrent(sumCurrent); avgSpeedKmh = convertToKmh(avgSpeed); + + // accel + EVERY_N_MILLIS(100) + { + const auto now = espchrono::millis_clock::now(); + const auto delta = now - lastAvgSpeedKmhTs; + const auto deltaSpeedKmh = avgSpeedKmh - lastAvgSpeedKmh; + + // ESP_LOGI("utils.cpp", "delta: %lli ms, deltaSpeedKmh: %f", delta.count() / 1000, deltaSpeedKmh); + + const auto deltaMilliseconds = delta.count() / 1000.f; + + const auto kmh_s = deltaSpeedKmh / deltaMilliseconds; // km/h / s + const auto m_s2 = kmh_s * 1000.f / 3600.f; // m/s^2 + + // ESP_LOGI("utils.cpp", "m_s2: %f", m_s2); + + avgAccel = avgAccel * 0.3f + m_s2 * 0.7f; + + lastAvgSpeedKmh = avgSpeedKmh; + lastAvgSpeedKmhTs = espchrono::millis_clock::now(); + } } float wattToAmpere(float watt) {