diff --git a/main/battery.cpp b/main/battery.cpp index 63e94e1..d058eea 100644 --- a/main/battery.cpp +++ b/main/battery.cpp @@ -1 +1,139 @@ #include "battery.h" + +#define CURVE(higherVoltage,lowerVoltage,fromAh,toAh) \ +if (cellVoltage >= lowerVoltage && cellVoltage <= higherVoltage) \ + return 100 * (expected_ah - cpputils::mapValue(cellVoltage, higherVoltage, lowerVoltage, fromAh, toAh)) / expected_ah; + +float getBatteryPercentage(float batVoltage, BatteryCellType cellType) +{ + const float cellVoltage = batVoltage / settings.battery.cellsSeries; + + switch (cellType) + { + case BatteryCellType::_22P: + { + const float expected_ah = 2.2; + if (cellVoltage > 4.15) + return 100; + + CURVE(4.15, 4.04, 0, 0.25) + CURVE(4.04, 3.95, 0.25, 0.5) + CURVE(3.95, 3.86, 0.5, 0.75) + CURVE(3.86, 3.74, 0.75, 1.0) + CURVE(3.74, 3.64, 1.0, 1.25) + CURVE(3.64, 3.59, 1.25, 1.5) + CURVE(3.59, 3.54, 1.5, 1.75) + CURVE(3.54, 3.43, 1.75, 2.0) + CURVE(3.43, 3.35, 2.0, 2.1) + CURVE(3.35, 2.50, 2.1, 2.2) + break; + } + case BatteryCellType::MH1: + { + const float expected_ah = 3.2; + if (cellVoltage > 4.15) + return 100; + + CURVE(4.15, 4.09, 0, 0.25) + CURVE(4.09, 4.04, 0.25, 0.5) + CURVE(4.04, 3.95, 0.5, 0.75) + CURVE(3.95, 3.88, 0.75, 1.0) + CURVE(3.88, 3.79, 1.0, 1.25) + CURVE(3.79, 3.70, 1.25, 1.5) + CURVE(3.70, 3.65, 1.5, 1.75) + CURVE(3.65, 3.60, 1.75, 2.0) + CURVE(3.60, 3.56, 2.0, 2.25) + CURVE(3.56, 3.50, 2.25, 2.5) + CURVE(3.50, 3.40, 2.5, 2.75) + CURVE(3.40, 3.30, 2.75, 3.0) + CURVE(3.30, 2.5, 3.0, 3.2) + break; + } + case BatteryCellType::HG2: + { + const float expected_ah = 3.0; + if (cellVoltage > 4.15) + return 100; + + CURVE(4.15, 4.08, 0, 0.25) + CURVE(4.08, 4.01, 0.25, 0.5) + CURVE(4.01, 3.92, 0.5, 0.75) + CURVE(3.92, 3.84, 0.75, 1.0) + CURVE(3.84, 3.75, 1.0, 1.25) + CURVE(3.75, 3.67, 1.25, 1.5) + CURVE(3.67, 3.62, 1.5, 1.75) + CURVE(3.62, 3.55, 1.75, 2.0) + CURVE(3.55, 3.44, 2.0, 2.25) + CURVE(3.44, 3.30, 2.25, 2.5) + CURVE(3.30, 3.05, 2.5, 2.75) + CURVE(3.05, 2.50, 2.75, 3.0) + break; + } + case BatteryCellType::VTC5: + { + const float expected_ah = 2.6; + if (cellVoltage > 4.15) + return 100; + + CURVE(4.15, 4.08, 0, 0.25) + CURVE(4.08, 3.98, 0.25, 0.5) + CURVE(3.98, 3.89, 0.5, 0.75) + CURVE(3.89, 3.79, 0.75, 1.0) + CURVE(3.79, 3.71, 1.0, 1.25) + CURVE(3.71, 3.64, 1.25, 1.5) + CURVE(3.64, 3.53, 1.5, 1.75) + CURVE(3.53, 3.44, 1.75, 2.0) + CURVE(3.44, 3.20, 2.0, 2.25) + CURVE(3.20, 2.80, 2.25, 2.5) + CURVE(2.80, 2.50, 2.5, 2.60) + break; + } + } + return 0.f; +} + +float getRemainingWattHours() +{ + float target_mah = 2000; //default + if(BatteryCellType(settings.battery.cellType) == BatteryCellType::_22P) target_mah = 2200; + if(BatteryCellType(settings.battery.cellType) == BatteryCellType::HG2) target_mah = 3000; + if(BatteryCellType(settings.battery.cellType) == BatteryCellType::MH1) target_mah = 3200; + if(BatteryCellType(settings.battery.cellType) == BatteryCellType::VTC5) target_mah = 2600; + + float avgVoltage = 0; + for (auto &controller : controllers) + { + avgVoltage += controller.getCalibratedVoltage(); + } + avgVoltage = avgVoltage / controllers.size(); + + return (target_mah / 1000.f) * 3.7 * settings.battery.cellsParallel * settings.battery.cellsSeries * (getBatteryPercentage(avgVoltage, BatteryCellType(settings.battery.cellType)) / 100); +} + +std::string getBatteryPercentageString() +{ + float avgVoltage = 0; + for (auto &controller : controllers) + { + avgVoltage += controller.getCalibratedVoltage(); + } + avgVoltage = avgVoltage / controllers.size(); + + std::string output = fmt::format("Battery: {:.1f}%", getBatteryPercentage(avgVoltage, BatteryCellType(settings.battery.cellType))); + return output; +} + +std::string getBatteryRemainingWattHoursString() +{ + return fmt::format("{:.1f} Wh", getRemainingWattHours()); +} + +std::string getBatteryCellTypeString() +{ + return fmt::format("Cells: {}", toString(BatteryCellType(settings.battery.cellType))); +} + +std::string getRemainingRangeString() +{ + return fmt::format("{:.1f} km", getRemainingWattHours() / settings.battery.watthoursPerKilometer); +} diff --git a/main/battery.h b/main/battery.h index 4e0a2eb..31f4e66 100644 --- a/main/battery.h +++ b/main/battery.h @@ -16,155 +16,14 @@ x(BAK_25R) DECLARE_TYPESAFE_ENUM(BatteryCellType, : uint8_t, BatteryCellTypeValues) -namespace { -#define CURVE(higherVoltage,lowerVoltage,fromAh,toAh) \ - if (cellVoltage >= lowerVoltage && cellVoltage <= higherVoltage) \ - return 100 * (expected_ah - cpputils::mapValue(cellVoltage, higherVoltage, lowerVoltage, fromAh, toAh)) / expected_ah; +float getBatteryPercentage(float batVoltage, BatteryCellType cellType); -float getBatteryPercentage(float batVoltage, BatteryCellType cellType) -{ - const float cellVoltage = batVoltage / settings.battery.cellsSeries; +float getRemainingWattHours(); - switch (cellType) { - case BatteryCellType::_22P: { - const float expected_ah = 2.2; - if(cellVoltage > 4.15){ - return 100; - } - CURVE(4.15, 4.04, 0, 0.25) - CURVE(4.04, 3.95, 0.25, 0.5) - CURVE(3.95, 3.86, 0.5, 0.75) - CURVE(3.86, 3.74, 0.75, 1.0) - CURVE(3.74, 3.64, 1.0, 1.25) - CURVE(3.64, 3.59, 1.25, 1.5) - CURVE(3.59, 3.54, 1.5, 1.75) - CURVE(3.54, 3.43, 1.75, 2.0) - CURVE(3.43, 3.35, 2.0, 2.1) - CURVE(3.35, 2.50, 2.1, 2.2) - break; - } - case BatteryCellType::MH1: { - const float expected_ah = 3.2; - if(cellVoltage > 4.15){ - return 100; - } - CURVE(4.15, 4.09, 0, 0.25) - CURVE(4.09, 4.04, 0.25, 0.5) - CURVE(4.04, 3.95, 0.5, 0.75) - CURVE(3.95, 3.88, 0.75, 1.0) - CURVE(3.88, 3.79, 1.0, 1.25) - CURVE(3.79, 3.70, 1.25, 1.5) - CURVE(3.70, 3.65, 1.5, 1.75) - CURVE(3.65, 3.60, 1.75, 2.0) - CURVE(3.60, 3.56, 2.0, 2.25) - CURVE(3.56, 3.50, 2.25, 2.5) - CURVE(3.50, 3.40, 2.5, 2.75) - CURVE(3.40, 3.30, 2.75, 3.0) - CURVE(3.30, 2.50, 3.0, 3.2) - break; - } - case BatteryCellType::HG2: { - const float expected_ah = 3.0; - if(cellVoltage > 4.15){ - return 100; - } - CURVE(4.15, 4.08, 0, 0.25) - CURVE(4.08, 4.01, 0.25, 0.5) - CURVE(4.01, 3.92, 0.5, 0.75) - CURVE(3.92, 3.84, 0.75, 1.0) - CURVE(3.84, 3.75, 1.0, 1.25) - CURVE(3.75, 3.67, 1.25, 1.5) - CURVE(3.67, 3.62, 1.5, 1.75) - CURVE(3.62, 3.55, 1.75, 2.0) - CURVE(3.55, 3.44, 2.0, 2.25) - CURVE(3.44, 3.30, 2.25, 2.5) - CURVE(3.30, 3.05, 2.5, 2.75) - CURVE(3.05, 2.50, 2.75, 3.0) - break; - } - case BatteryCellType::VTC5: { - const float expected_ah = 2.6; - if(cellVoltage > 4.15){ - return 100; - } - CURVE(4.15, 4.08, 0, 0.25) - CURVE(4.08, 3.98, 0.25, 0.5) - CURVE(3.98, 3.89, 0.5, 0.75) - CURVE(3.89, 3.79, 0.75, 1.0) - CURVE(3.79, 3.71, 1.0, 1.25) - CURVE(3.71, 3.64, 1.25, 1.5) - CURVE(3.64, 3.53, 1.5, 1.75) - CURVE(3.53, 3.44, 1.75, 2.0) - CURVE(3.44, 3.20, 2.0, 2.25) - CURVE(3.20, 2.80, 2.25, 2.5) - CURVE(2.80, 2.50, 2.5, 2.60) - break; - } - case BatteryCellType::BAK_25R: { - const float expected_ah = 2.5; - if(cellVoltage > 4.15){ - return 100; - } - CURVE(4.15, 4.06, 0, 0.25) - CURVE(4.06, 3.96, 0.25, 0.5) - CURVE(3.96, 3.88, 0.5, 0.75) - CURVE(3.88, 3.77, 0.75, 1) - CURVE(3.77, 3.68, 1, 1.25) - CURVE(3.68, 3.62, 1.25, 1.5) - CURVE(3.62, 3.56, 1.5, 1.75) - CURVE(3.56, 3.47, 1.75, 2) - CURVE(3.47, 3.31, 2, 2.25) - CURVE(3.31, 2.50, 2.25, 2.5) - break; - } - } - return 0.f; -} +std::string getBatteryPercentageString(); -float getRemainingWattHours() -{ - float target_mah = 2000; //default - if(BatteryCellType(settings.battery.cellType) == BatteryCellType::_22P) target_mah = 2200; - if(BatteryCellType(settings.battery.cellType) == BatteryCellType::HG2) target_mah = 3000; - if(BatteryCellType(settings.battery.cellType) == BatteryCellType::MH1) target_mah = 3200; - if(BatteryCellType(settings.battery.cellType) == BatteryCellType::VTC5) target_mah = 2600; +std::string getBatteryRemainingWattHoursString(); - float avgVoltage = 0; - for (auto &controller : controllers) - { - avgVoltage += controller.getCalibratedVoltage(); - } - avgVoltage = avgVoltage / controllers.size(); +std::string getBatteryCellTypeString(); - return (target_mah / 1000.f) * 3.7 * settings.battery.cellsParallel * settings.battery.cellsSeries * (getBatteryPercentage(avgVoltage, BatteryCellType(settings.battery.cellType)) / 100); -} - -std::string getBatteryPercentageString() -{ - float avgVoltage = 0; - for (auto &controller : controllers) - { - avgVoltage += controller.getCalibratedVoltage(); - } - avgVoltage = avgVoltage / controllers.size(); - - std::string output = fmt::format("Battery: {:.1f}%", getBatteryPercentage(avgVoltage, BatteryCellType(settings.battery.cellType))); - return output; -} - -std::string getBatteryRemainingWattHoursString() -{ - return fmt::format("{:.1f} Wh", getRemainingWattHours()); -} - -std::string getBatteryCellTypeString() -{ - return fmt::format("Cells: {}", toString(BatteryCellType(settings.battery.cellType))); -} - -std::string getRemainingRangeString() -{ - return fmt::format("{:.1f} km", getRemainingWattHours() / settings.battery.watthoursPerKilometer); -} - -} // namespace +std::string getRemainingRangeString(); diff --git a/main/ble_bobby.cpp b/main/ble_bobby.cpp index ece99bf..bbff0c6 100644 --- a/main/ble_bobby.cpp +++ b/main/ble_bobby.cpp @@ -24,6 +24,7 @@ WirelessSettingsCallbacks bleWirelessSettingsCallbacks; WiFiListCallbacks bleWiFiListCallbacks; #endif +namespace { void createBle() { ESP_LOGI("BOBBY", "called"); @@ -69,6 +70,7 @@ void destroyBle() getwifilist = {}; #endif } +} // namespace void initBle() { diff --git a/main/ble_bobby.h b/main/ble_bobby.h index 032f679..905ee2d 100644 --- a/main/ble_bobby.h +++ b/main/ble_bobby.h @@ -28,9 +28,6 @@ extern BLECharacteristic *wirelessConfig; extern BLECharacteristic *getwifilist; #endif -void createBle(); -void destroyBle(); - class RemoteControlCallbacks : public NimBLECharacteristicCallbacks { public: diff --git a/main/buttons.cpp b/main/buttons.cpp index e69de29..7faed9c 100644 --- a/main/buttons.cpp +++ b/main/buttons.cpp @@ -0,0 +1,164 @@ +#include "buttons.h" + +int rotated{}; +bool requestFullRedraw{}; + +bool confirmButtonPressed{}; +bool confirmButtonLongPressed{}; +bool backButtonPressed{}; +bool backButtonLongPressed{}; + +bool profileButtonDisabled{}; + +std::optional upPressedSince; +int upPressRepeat{}; +std::optional downPressedSince; +int downPressRepeat{}; + +void InputDispatcher::update() +{ + if (upPressedSince && espchrono::ago(*upPressedSince) > (upPressRepeat > 2 ? 50ms : 400ms)) + { + upPressedSince = espchrono::millis_clock::now(); + upPressRepeat++; + rotated -= 1; + } + + if (downPressedSince && espchrono::ago(*downPressedSince) > (downPressRepeat > 2 ? 50ms : 400ms)) + { + downPressedSince = espchrono::millis_clock::now(); + downPressRepeat++; + rotated += 1; + } +} + +void InputDispatcher::rotate(int offset) +{ + rotated += offset; +} + +void InputDispatcher::upButton(bool pressed) +{ + if (pressed) + { + upPressedSince = espchrono::millis_clock::now(); + upPressRepeat = 0; + rotated -= 1; + } + else + { + upPressedSince = std::nullopt; + } +} + +void InputDispatcher::downButton(bool pressed) +{ + if (pressed) + { + downPressedSince = espchrono::millis_clock::now(); + downPressRepeat = 0; + rotated += 1; + } + else + { + downPressedSince = std::nullopt; + } +} + +void InputDispatcher::confirmButton(bool pressed) +{ + static espchrono::millis_clock::time_point pressBegin{}; + + const auto now = espchrono::millis_clock::now(); + + if (pressed) + pressBegin = now; + else + { + const auto duration = now - pressBegin; + + if (duration < 500ms) + confirmButtonPressed = true; + else if (duration < 2000ms) + confirmButtonLongPressed = true; + else + requestFullRedraw = true; + + pressBegin = {}; + } +} + +void InputDispatcher::backButton(bool pressed) +{ + static espchrono::millis_clock::time_point pressBegin{}; + + const auto now = espchrono::millis_clock::now(); + + if (pressed) + pressBegin = now; + else + { + const auto duration = now - pressBegin; + + if (duration < 500ms) + backButtonPressed = true; + else + backButtonLongPressed = true; + + pressBegin = {}; + } +} + +void InputDispatcher::profileButton(uint8_t index, bool pressed) +{ + if (!pressed) + return; + + if (profileButtonDisabled) + return; + + switchProfile(index); +} + +void InputDispatcher::blinkLeftButton(bool pressed) +{ + if(!pressed)return; + +#ifdef FEATURE_LEDSTRIP + if(blinkAnimation == LEDSTRIP_OVERWRITE_NONE){ //transition from off to left + blinkAnimation = LEDSTRIP_OVERWRITE_BLINKLEFT; + } + else if(blinkAnimation == LEDSTRIP_OVERWRITE_BLINKRIGHT){ // transition to warning + blinkAnimation = LEDSTRIP_OVERWRITE_BLINKBOTH; + } + else{ // transition to off + blinkAnimation = LEDSTRIP_OVERWRITE_NONE; + } +#endif +} + +void InputDispatcher::blinkRightButton(bool pressed) +{ + if(!pressed)return; +#ifdef FEATURE_LEDSTRIP + if(blinkAnimation == LEDSTRIP_OVERWRITE_NONE){ //transition from off to right + blinkAnimation = LEDSTRIP_OVERWRITE_BLINKRIGHT; + } + else if(blinkAnimation == LEDSTRIP_OVERWRITE_BLINKLEFT){ // transition to warning + blinkAnimation = LEDSTRIP_OVERWRITE_BLINKBOTH; + } + else{ // transition to off + blinkAnimation = LEDSTRIP_OVERWRITE_NONE; + } +#endif +} + +void InputDispatcher::quickActionButtonDown(bool pressed) +{ + +} + +void InputDispatcher::quickActionButtonUp(bool pressed) +{ + +} diff --git a/main/buttons.h b/main/buttons.h index 5f91280..c01876d 100644 --- a/main/buttons.h +++ b/main/buttons.h @@ -14,168 +14,43 @@ #include "ledstrip.h" #endif -namespace { +extern int rotated; +extern bool requestFullRedraw; -int rotated{}; -bool requestFullRedraw{}; +extern bool confirmButtonPressed; +extern bool confirmButtonLongPressed; +extern bool backButtonPressed; +extern bool backButtonLongPressed; -bool confirmButtonPressed{}; -bool confirmButtonLongPressed{}; -bool backButtonPressed{}; -bool backButtonLongPressed{}; +extern bool profileButtonDisabled; -bool profileButtonDisabled{}; - -std::optional upPressedSince; -int upPressRepeat{}; -std::optional downPressedSince; -int downPressRepeat{}; +extern std::optional upPressedSince; +extern int upPressRepeat; +extern std::optional downPressedSince; +extern int downPressRepeat; class InputDispatcher { public: - static void update() - { - if (upPressedSince && espchrono::ago(*upPressedSince) > (upPressRepeat > 2 ? 50ms : 400ms)) - { - upPressedSince = espchrono::millis_clock::now(); - upPressRepeat++; - rotated -= 1; - } + static void update(); - if (downPressedSince && espchrono::ago(*downPressedSince) > (downPressRepeat > 2 ? 50ms : 400ms)) - { - downPressedSince = espchrono::millis_clock::now(); - downPressRepeat++; - rotated += 1; - } - } + static void rotate(int offset); - static void rotate(int offset) - { - rotated += offset; - } + static void upButton(bool pressed); - static void upButton(bool pressed) - { - if (pressed) - { - upPressedSince = espchrono::millis_clock::now(); - upPressRepeat = 0; - rotated -= 1; - } - else - { - upPressedSince = std::nullopt; - } - } + static void downButton(bool pressed); - static void downButton(bool pressed) - { - if (pressed) - { - downPressedSince = espchrono::millis_clock::now(); - downPressRepeat = 0; - rotated += 1; - } - else - { - downPressedSince = std::nullopt; - } - } + static void confirmButton(bool pressed); - static void confirmButton(bool pressed) - { - static espchrono::millis_clock::time_point pressBegin{}; + static void backButton(bool pressed); - const auto now = espchrono::millis_clock::now(); + static void profileButton(uint8_t index, bool pressed); - if (pressed) - pressBegin = now; - else - { - const auto duration = now - pressBegin; + static void blinkLeftButton(bool pressed); - if (duration < 500ms) - confirmButtonPressed = true; - else if (duration < 2000ms) - confirmButtonLongPressed = true; - else - requestFullRedraw = true; + static void blinkRightButton(bool pressed); - pressBegin = {}; - } - } + static void quickActionButtonDown(bool pressed); - static void backButton(bool pressed) - { - static espchrono::millis_clock::time_point pressBegin{}; - - const auto now = espchrono::millis_clock::now(); - - if (pressed) - pressBegin = now; - else - { - const auto duration = now - pressBegin; - - if (duration < 500ms) - backButtonPressed = true; - else - backButtonLongPressed = true; - - pressBegin = {}; - } - } - - static void profileButton(uint8_t index, bool pressed) - { - if (!pressed) - return; - - if (profileButtonDisabled) - return; - - switchProfile(index); - } - - static void blinkLeftButton(bool pressed){ - if(!pressed)return; - -#ifdef FEATURE_LEDSTRIP - if(blinkAnimation == LEDSTRIP_OVERWRITE_NONE){ //transition from off to left - blinkAnimation = LEDSTRIP_OVERWRITE_BLINKLEFT; - } - else if(blinkAnimation == LEDSTRIP_OVERWRITE_BLINKRIGHT){ // transition to warning - blinkAnimation = LEDSTRIP_OVERWRITE_BLINKBOTH; - } - else{ // transition to off - blinkAnimation = LEDSTRIP_OVERWRITE_NONE; - } -#endif - } - - static void blinkRightButton(bool pressed){ - if(!pressed)return; -#ifdef FEATURE_LEDSTRIP - if(blinkAnimation == LEDSTRIP_OVERWRITE_NONE){ //transition from off to right - blinkAnimation = LEDSTRIP_OVERWRITE_BLINKRIGHT; - } - else if(blinkAnimation == LEDSTRIP_OVERWRITE_BLINKLEFT){ // transition to warning - blinkAnimation = LEDSTRIP_OVERWRITE_BLINKBOTH; - } - else{ // transition to off - blinkAnimation = LEDSTRIP_OVERWRITE_NONE; - } -#endif - } - - static void quickActionButtonDown(bool pressed){ - - } - - static void quickActionButtonUp(bool pressed){ - - } + static void quickActionButtonUp(bool pressed); }; -} diff --git a/main/displays/statusdisplay.cpp b/main/displays/statusdisplay.cpp index d506076..3efd362 100644 --- a/main/displays/statusdisplay.cpp +++ b/main/displays/statusdisplay.cpp @@ -1,5 +1,8 @@ #include "statusdisplay.h" +// esp-idf includes +#include + // 3rdparty lib includes #include #include @@ -15,6 +18,10 @@ using namespace espgui; +namespace { +constexpr const char * const TAG = "STATUS"; +} // namespace + void StatusDisplay::initScreen() { Base::initScreen(); @@ -143,9 +150,15 @@ clearIp: void StatusDisplay::confirm() { + ESP_LOGI(TAG, "called"); switchScreen(); } +void StatusDisplay::back() +{ + +} + void StatusDisplay::rotate(int offset) { Base::rotate(offset); diff --git a/main/displays/statusdisplay.h b/main/displays/statusdisplay.h index e18e3b6..5f64f92 100644 --- a/main/displays/statusdisplay.h +++ b/main/displays/statusdisplay.h @@ -17,8 +17,7 @@ #include "battery.h" class StatusDisplay : - public espgui::Display, - public espgui::DummyBack + public espgui::Display { using Base = espgui::Display; @@ -27,6 +26,7 @@ public: void redraw() override; void confirm() override; + void back() override; void rotate(int offset) override; private: