lots of smaller fixes

This commit is contained in:
2021-08-09 20:59:55 +02:00
parent d75db8e18c
commit 1504fc779a
16 changed files with 233 additions and 100 deletions

View File

@ -9,7 +9,6 @@ add_definitions(
-DFEATURE_ADC_IN -DFEATURE_ADC_IN
-DPINS_GAS=34 -DPINS_GAS=34
-DPINS_BREMS=35 -DPINS_BREMS=35
# -DPINS_LED=23
-DILI9341_DRIVER=1 -DILI9341_DRIVER=1
-DTFT_MOSI=13 -DTFT_MOSI=13
-DTFT_SCLK=15 -DTFT_SCLK=15
@ -75,4 +74,7 @@ add_definitions(
# -DDEFAULT_GAMETRAKDISTMIN=0 # -DDEFAULT_GAMETRAKDISTMIN=0
# -DDEFAULT_GAMETRAKDISTMAX=4095 # -DDEFAULT_GAMETRAKDISTMAX=4095
# -DFEATURE_CLOUD # -DFEATURE_CLOUD
-DFEATURE_LEDBACKLIGHT
-DPINS_LEDBACKLIGHT=23
-DLEDBACKLIGHT_INVERTED
) )

View File

@ -1,4 +1,4 @@
if [[ $_ == $0 ]] if [[ $_ == $0 ]] && [[ "$1" != "--skip-source-check" ]]
then then
echo "export.sh has to be sourced, not run in a subshell" echo "export.sh has to be sourced, not run in a subshell"
echo ". export.sh" echo ". export.sh"

View File

@ -62,6 +62,10 @@ struct SwapFrontBackAccessor : public RefAccessorSaveSettings<bool> {
void setValue(bool value) override { RefAccessorSaveSettings<bool>::setValue(value); updateSwapFrontBack(); }; void setValue(bool value) override { RefAccessorSaveSettings<bool>::setValue(value); updateSwapFrontBack(); };
#endif #endif
}; };
#ifdef FEATURE_CAN
struct SendFrontCanCmdAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.controllerHardware.sendFrontCanCmd; } };
struct SendBackCanCmdAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.controllerHardware.sendBackCanCmd; } };
#endif
struct SampleCountAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.sampleCount; } }; struct SampleCountAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.sampleCount; } };
struct GasMinAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.gasMin; } }; struct GasMinAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.gasMin; } };

View File

@ -5,6 +5,7 @@
#include <driver/gpio.h> #include <driver/gpio.h>
#include <driver/twai.h> #include <driver/twai.h>
#include <esp_log.h>
#include <Arduino.h> #include <Arduino.h>
@ -219,11 +220,11 @@ bool parseBoardcomputerCanMessage(const twai_message_t &message)
bool tryParseCanInput() bool tryParseCanInput()
{ {
twai_message_t message; twai_message_t message;
if (const auto result = twai_receive(&message, pdMS_TO_TICKS(50)); result != ESP_OK) if (const auto result = twai_receive(&message, pdMS_TO_TICKS(10)); result != ESP_OK)
{ {
if (result != ESP_ERR_TIMEOUT) if (result != ESP_ERR_TIMEOUT)
{ {
//Serial.printf("CAN err twai_receive() failed with %s\r\n", esp_err_to_name(result)); ESP_LOGE(TAG, "CAN err twai_receive() failed with %s", esp_err_to_name(result));
} }
if (espchrono::millis_clock::now() - controllers.front.lastCanFeedback > 100ms) if (espchrono::millis_clock::now() - controllers.front.lastCanFeedback > 100ms)
@ -293,20 +294,27 @@ void sendCanCommands()
const auto result = twai_transmit(&message, pdMS_TO_TICKS(200)); const auto result = twai_transmit(&message, pdMS_TO_TICKS(200));
if (result != ESP_OK && result != ESP_ERR_TIMEOUT) if (result != ESP_OK && result != ESP_ERR_TIMEOUT)
{ {
//Serial.printf("ERROR: twai_transmit() failed with %s\r\n", esp_err_to_name(result)); ESP_LOGE(TAG, "ERROR: twai_transmit() failed with %s", esp_err_to_name(result));
} }
return result; return result;
}; };
const Controller &front = settings.controllerHardware.swapFrontBack ? controllers.back : controllers.front; const bool swap = settings.controllerHardware.swapFrontBack;
const Controller &back = settings.controllerHardware.swapFrontBack ? controllers.front : controllers.back; const Controller *front =
(swap ? settings.controllerHardware.sendBackCanCmd : settings.controllerHardware.sendFrontCanCmd ) ?
(swap ? &controllers.back : &controllers.front) :
nullptr;
const Controller *back =
(swap ? settings.controllerHardware.sendFrontCanCmd : settings.controllerHardware.sendBackCanCmd ) ?
(swap ? &controllers.front : &controllers.back) :
nullptr;
using namespace bobbycar::protocol::can; using namespace bobbycar::protocol::can;
send(MotorController<false, false>::Command::InpTgt, front.command.left.pwm); if (front) send(MotorController<false, false>::Command::InpTgt, front->command.left.pwm);
send(MotorController<false, true>::Command::InpTgt, front.command.right.pwm); if (front) send(MotorController<false, true>::Command::InpTgt, front->command.right.pwm);
send(MotorController<true, false>::Command::InpTgt, back.command.left.pwm); if (back) send(MotorController<true, false>::Command::InpTgt, back->command.left.pwm);
send(MotorController<true, true>::Command::InpTgt, back.command.right.pwm); if (back) send(MotorController<true, true>::Command::InpTgt, back->command.right.pwm);
uint16_t buttonLeds{}; uint16_t buttonLeds{};
if (const auto index = settingsPersister.currentlyOpenProfileIndex()) if (const auto index = settingsPersister.currentlyOpenProfileIndex())
@ -328,10 +336,10 @@ void sendCanCommands()
static int i{}; static int i{};
if (front.command.buzzer.freq != lastValues.front.freq || if ((front && front->command.buzzer.freq != lastValues.front.freq ) ||
front.command.buzzer.pattern != lastValues.front.pattern || (front && front->command.buzzer.pattern != lastValues.front.pattern ) ||
back.command.buzzer.freq != lastValues.back.freq || (back && back->command.buzzer.freq != lastValues.back.freq) ||
back.command.buzzer.pattern != lastValues.back.pattern) (back && back->command.buzzer.pattern != lastValues.back.pattern))
i = 10; i = 10;
else if (buttonLeds != lastValues.buttonLeds) else if (buttonLeds != lastValues.buttonLeds)
i = 12; i = 12;
@ -339,92 +347,92 @@ void sendCanCommands()
switch (i++) switch (i++)
{ {
case 0: case 0:
send(MotorController<false, false>::Command::Enable, front.command.left.enable); if (front) send(MotorController<false, false>::Command::Enable, front->command.left.enable);
send(MotorController<false, true>::Command::Enable, front.command.right.enable); if (front) send(MotorController<false, true>::Command::Enable, front->command.right.enable);
send(MotorController<true, false>::Command::Enable, back.command.left.enable); if (back) send(MotorController<true, false>::Command::Enable, back->command.left.enable);
send(MotorController<true, true>::Command::Enable, back.command.right.enable); if (back) send(MotorController<true, true>::Command::Enable, back->command.right.enable);
break; break;
case 1: case 1:
send(MotorController<false, false>::Command::CtrlTyp, front.command.left.ctrlTyp); if (front) send(MotorController<false, false>::Command::CtrlTyp, front->command.left.ctrlTyp);
send(MotorController<false, true>::Command::CtrlTyp, front.command.right.ctrlTyp); if (front) send(MotorController<false, true>::Command::CtrlTyp, front->command.right.ctrlTyp);
send(MotorController<true, false>::Command::CtrlTyp, back.command.left.ctrlTyp); if (back) send(MotorController<true, false>::Command::CtrlTyp, back->command.left.ctrlTyp);
send(MotorController<true, true>::Command::CtrlTyp, back.command.right.ctrlTyp); if (back) send(MotorController<true, true>::Command::CtrlTyp, back->command.right.ctrlTyp);
break; break;
case 2: case 2:
send(MotorController<false, false>::Command::CtrlMod, front.command.left.ctrlMod); if (front) send(MotorController<false, false>::Command::CtrlMod, front->command.left.ctrlMod);
send(MotorController<false, true>::Command::CtrlMod, front.command.right.ctrlMod); if (front) send(MotorController<false, true>::Command::CtrlMod, front->command.right.ctrlMod);
send(MotorController<true, false>::Command::CtrlMod, back.command.left.ctrlMod); if (back) send(MotorController<true, false>::Command::CtrlMod, back->command.left.ctrlMod);
send(MotorController<true, true>::Command::CtrlMod, back.command.right.ctrlMod); if (back) send(MotorController<true, true>::Command::CtrlMod, back->command.right.ctrlMod);
break; break;
case 3: case 3:
send(MotorController<false, false>::Command::IMotMax, front.command.left.iMotMax); if (front) send(MotorController<false, false>::Command::IMotMax, front->command.left.iMotMax);
send(MotorController<false, true>::Command::IMotMax, front.command.right.iMotMax); if (front) send(MotorController<false, true>::Command::IMotMax, front->command.right.iMotMax);
send(MotorController<true, false>::Command::IMotMax, back.command.left.iMotMax); if (back) send(MotorController<true, false>::Command::IMotMax, back->command.left.iMotMax);
send(MotorController<true, true>::Command::IMotMax, back.command.right.iMotMax); if (back) send(MotorController<true, true>::Command::IMotMax, back->command.right.iMotMax);
break; break;
case 4: case 4:
send(MotorController<false, false>::Command::IDcMax, front.command.left.iDcMax); if (front) send(MotorController<false, false>::Command::IDcMax, front->command.left.iDcMax);
send(MotorController<false, true>::Command::IDcMax, front.command.right.iDcMax); if (front) send(MotorController<false, true>::Command::IDcMax, front->command.right.iDcMax);
send(MotorController<true, false>::Command::IDcMax, back.command.left.iDcMax); if (back) send(MotorController<true, false>::Command::IDcMax, back->command.left.iDcMax);
send(MotorController<true, true>::Command::IDcMax, back.command.right.iDcMax); if (back) send(MotorController<true, true>::Command::IDcMax, back->command.right.iDcMax);
break; break;
case 5: case 5:
send(MotorController<false, false>::Command::NMotMax, front.command.left.nMotMax); if (front) send(MotorController<false, false>::Command::NMotMax, front->command.left.nMotMax);
send(MotorController<false, true>::Command::NMotMax, front.command.right.nMotMax); if (front) send(MotorController<false, true>::Command::NMotMax, front->command.right.nMotMax);
send(MotorController<true, false>::Command::NMotMax, back.command.left.nMotMax); if (back) send(MotorController<true, false>::Command::NMotMax, back->command.left.nMotMax);
send(MotorController<true, true>::Command::NMotMax, back.command.right.nMotMax); if (back) send(MotorController<true, true>::Command::NMotMax, back->command.right.nMotMax);
break; break;
case 6: case 6:
send(MotorController<false, false>::Command::FieldWeakMax, front.command.left.fieldWeakMax); if (front) send(MotorController<false, false>::Command::FieldWeakMax, front->command.left.fieldWeakMax);
send(MotorController<false, true>::Command::FieldWeakMax, front.command.right.fieldWeakMax); if (front) send(MotorController<false, true>::Command::FieldWeakMax, front->command.right.fieldWeakMax);
send(MotorController<true, false>::Command::FieldWeakMax, back.command.left.fieldWeakMax); if (back) send(MotorController<true, false>::Command::FieldWeakMax, back->command.left.fieldWeakMax);
send(MotorController<true, true>::Command::FieldWeakMax, back.command.right.fieldWeakMax); if (back) send(MotorController<true, true>::Command::FieldWeakMax, back->command.right.fieldWeakMax);
break; break;
case 7: case 7:
send(MotorController<false, false>::Command::PhaseAdvMax, front.command.left.phaseAdvMax); if (front) send(MotorController<false, false>::Command::PhaseAdvMax, front->command.left.phaseAdvMax);
send(MotorController<false, true>::Command::PhaseAdvMax, front.command.right.phaseAdvMax); if (front) send(MotorController<false, true>::Command::PhaseAdvMax, front->command.right.phaseAdvMax);
send(MotorController<true, false>::Command::PhaseAdvMax, back.command.left.phaseAdvMax); if (back) send(MotorController<true, false>::Command::PhaseAdvMax, back->command.left.phaseAdvMax);
send(MotorController<true, true>::Command::PhaseAdvMax, back.command.right.phaseAdvMax); if (back) send(MotorController<true, true>::Command::PhaseAdvMax, back->command.right.phaseAdvMax);
break; break;
case 8: case 8:
send(MotorController<false, false>::Command::CruiseCtrlEna, front.command.left.cruiseCtrlEna); if (front) send(MotorController<false, false>::Command::CruiseCtrlEna, front->command.left.cruiseCtrlEna);
send(MotorController<false, true>::Command::CruiseCtrlEna, front.command.right.cruiseCtrlEna); if (front) send(MotorController<false, true>::Command::CruiseCtrlEna, front->command.right.cruiseCtrlEna);
send(MotorController<true, false>::Command::CruiseCtrlEna, back.command.left.cruiseCtrlEna); if (back) send(MotorController<true, false>::Command::CruiseCtrlEna, back->command.left.cruiseCtrlEna);
send(MotorController<true, true>::Command::CruiseCtrlEna, back.command.right.cruiseCtrlEna); if (back) send(MotorController<true, true>::Command::CruiseCtrlEna, back->command.right.cruiseCtrlEna);
break; break;
case 9: case 9:
send(MotorController<false, false>::Command::CruiseMotTgt, front.command.left.nCruiseMotTgt); if (front) send(MotorController<false, false>::Command::CruiseMotTgt, front->command.left.nCruiseMotTgt);
send(MotorController<false, true>::Command::CruiseMotTgt, front.command.right.nCruiseMotTgt); if (front) send(MotorController<false, true>::Command::CruiseMotTgt, front->command.right.nCruiseMotTgt);
send(MotorController<true, false>::Command::CruiseMotTgt, back.command.left.nCruiseMotTgt); if (back) send(MotorController<true, false>::Command::CruiseMotTgt, back->command.left.nCruiseMotTgt);
send(MotorController<true, true>::Command::CruiseMotTgt, back.command.right.nCruiseMotTgt); if (back) send(MotorController<true, true>::Command::CruiseMotTgt, back->command.right.nCruiseMotTgt);
break; break;
case 10: case 10:
if (send(MotorController<false, false>::Command::BuzzerFreq, front.command.buzzer.freq) == ESP_OK) if (front && send(MotorController<false, false>::Command::BuzzerFreq, front->command.buzzer.freq) == ESP_OK)
lastValues.front.freq = front.command.buzzer.freq; lastValues.front.freq = front->command.buzzer.freq;
// if (send(MotorController<false, true>::Command::BuzzerFreq, front.command.buzzer.freq) == ESP_OK) // if (front && send(MotorController<false, true>::Command::BuzzerFreq, front->command.buzzer.freq) == ESP_OK)
// lastValues.front.freq = front.command.buzzer.freq; // lastValues.front.freq = front->command.buzzer.freq;
if (send(MotorController<true, false>::Command::BuzzerFreq, back.command.buzzer.freq) == ESP_OK) if (back && send(MotorController<true, false>::Command::BuzzerFreq, back->command.buzzer.freq) == ESP_OK)
lastValues.back.freq = back.command.buzzer.freq; lastValues.back.freq = back->command.buzzer.freq;
// if (send(MotorController<true, true>::Command::BuzzerFreq, back.command.buzzer.freq) == ESP_OK) // if (back && send(MotorController<true, true>::Command::BuzzerFreq, back->command.buzzer.freq) == ESP_OK)
// lastValues.back.freq = back.command.buzzer.freq; // lastValues.back.freq = back->command.buzzer.freq;
if (send(MotorController<false, false>::Command::BuzzerPattern, front.command.buzzer.pattern) == ESP_OK) if (front && send(MotorController<false, false>::Command::BuzzerPattern, front->command.buzzer.pattern) == ESP_OK)
lastValues.front.pattern = front.command.buzzer.pattern; lastValues.front.pattern = front->command.buzzer.pattern;
// if (send(MotorController<false, true>::Command::BuzzerPattern, front.command.buzzer.pattern) == ESP_OK) // if (front && send(MotorController<false, true>::Command::BuzzerPattern, front->command.buzzer.pattern) == ESP_OK)
// lastValues.front.pattern = front.command.buzzer.pattern; // lastValues.front.pattern = front->command.buzzer.pattern;
if (send(MotorController<true, false>::Command::BuzzerPattern, back.command.buzzer.pattern) == ESP_OK) if (back && send(MotorController<true, false>::Command::BuzzerPattern, back->command.buzzer.pattern) == ESP_OK)
lastValues.back.pattern = back.command.buzzer.pattern; lastValues.back.pattern = back->command.buzzer.pattern;
// if (send(MotorController<true, true>::Command::BuzzerPattern, back.command.buzzer.pattern) == ESP_OK) // if (back && send(MotorController<true, true>::Command::BuzzerPattern, back->command.buzzer.pattern) == ESP_OK)
// lastValues.back.pattern = back.command.buzzer.pattern; // lastValues.back.pattern = back->command.buzzer.pattern;
break; break;
case 11: case 11:
send(MotorController<false, false>::Command::Led, front.command.led); if (front) send(MotorController<false, false>::Command::Led, front->command.led);
//send(MotorController<false, true>::Command::Led, front.command.led); //if (front) send(MotorController<false, true>::Command::Led, front->command.led);
send(MotorController<true, false>::Command::Led, back.command.led); if (back) send(MotorController<true, false>::Command::Led, back->command.led);
//send(MotorController<true, true>::Command::Led, back.command.led); //if (back) send(MotorController<true, true>::Command::Led, back->command.led);
send(MotorController<false, false>::Command::Poweroff, front.command.poweroff); if (front) send(MotorController<false, false>::Command::Poweroff, front->command.poweroff);
//send(MotorController<false, true>::Command::Poweroff, front.command.poweroff); //if (front) send(MotorController<false, true>::Command::Poweroff, front->command.poweroff);
send(MotorController<true, false>::Command::Poweroff, back.command.poweroff); if (back) send(MotorController<true, false>::Command::Poweroff, back->command.poweroff);
//send(MotorController<true, true>::Command::Poweroff, back.command.poweroff); //if (back) send(MotorController<true, true>::Command::Poweroff, back->command.poweroff);
break; break;
case 12: case 12:
if (send(Boardcomputer::Feedback::ButtonLeds, buttonLeds) == ESP_OK) if (send(Boardcomputer::Feedback::ButtonLeds, buttonLeds) == ESP_OK)

View File

@ -61,6 +61,10 @@ public:
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_WHEELDIAMETERINCH>, SwitchScreenAction<WheelDiameterInchChangeScreen>>>(); constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_WHEELDIAMETERINCH>, SwitchScreenAction<WheelDiameterInchChangeScreen>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_NUMMAGNETPOLES>, SwitchScreenAction<NumMagnetPolesChangeScreen>>>(); constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_NUMMAGNETPOLES>, SwitchScreenAction<NumMagnetPolesChangeScreen>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_SWAPFRONTBACK>, ToggleBoolAction, CheckboxIcon, SwapFrontBackAccessor>>(); constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_SWAPFRONTBACK>, ToggleBoolAction, CheckboxIcon, SwapFrontBackAccessor>>();
#ifdef FEATURE_CAN
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_FRONTSENDCAN>, ToggleBoolAction, CheckboxIcon, SendFrontCanCmdAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACKSENDCAN>, ToggleBoolAction, CheckboxIcon, SendBackCanCmdAccessor>>();
#endif
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<SettingsMenu>, StaticMenuItemIcon<&icons::back>>>(); constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<SettingsMenu>, StaticMenuItemIcon<&icons::back>>>();
} }
}; };

View File

@ -32,6 +32,13 @@ class MainMenu;
} }
namespace { namespace {
#ifdef FEATURE_LEDBACKLIGHT
struct BacklightAccessor : public virtual AccessorInterface<bool>
{
bool getValue() const override { return digitalRead(PINS_LEDBACKLIGHT) != ledBacklightInverted; }
void setValue(bool value) override { digitalWrite(PINS_LEDBACKLIGHT, value != ledBacklightInverted); }
};
#endif
struct FrontLedAccessor : public RefAccessor<bool> { bool &getRef() const override { return controllers.front.command.led; } }; struct FrontLedAccessor : public RefAccessor<bool> { bool &getRef() const override { return controllers.front.command.led; } };
struct BackLedAccessor : public RefAccessor<bool> { bool &getRef() const override { return controllers.back.command.led; } }; struct BackLedAccessor : public RefAccessor<bool> { bool &getRef() const override { return controllers.back.command.led; } };
@ -43,6 +50,9 @@ class SettingsMenu :
public: public:
SettingsMenu() SettingsMenu()
{ {
#ifdef FEATURE_LEDBACKLIGHT
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACKLIGHT>, ToggleBoolAction, CheckboxIcon, BacklightAccessor>>();
#endif
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LIMITSSETTINGS>, SwitchScreenAction<LimitsSettingsMenu>>>(); constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LIMITSSETTINGS>, SwitchScreenAction<LimitsSettingsMenu>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_WIFISETTINGS>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&icons::wifi>>>(); constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_WIFISETTINGS>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&icons::wifi>>>();
#ifdef FEATURE_BLUETOOTH #ifdef FEATURE_BLUETOOTH

View File

@ -1,7 +1,11 @@
#pragma once #pragma once
// system includes
#include <optional>
// 3rdparty lib includes // 3rdparty lib includes
#include <fmt/core.h> #include <fmt/core.h>
#include <espchrono.h>
// local includes // local includes
#include "display.h" #include "display.h"
@ -103,6 +107,15 @@ private:
Label m_labelProfile{205, bottomLines[3]}; // 35, 15 Label m_labelProfile{205, bottomLines[3]}; // 35, 15
static const constexpr int bottomLines[4] { 251, 266, 281, 296 }; static const constexpr int bottomLines[4] { 251, 266, 281, 296 };
struct CachedString
{
std::string text;
espchrono::millis_clock::time_point timestamp = espchrono::millis_clock::now();
};
std::optional<CachedString> m_cachedWifiStatus;
std::optional<CachedString> m_cachedWifiIP;
}; };
void StatusDisplay::initScreen() void StatusDisplay::initScreen()
@ -141,6 +154,9 @@ void StatusDisplay::initScreen()
m_labelProfile.start(); m_labelProfile.start();
tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setTextColor(TFT_WHITE, TFT_BLACK);
m_cachedWifiStatus = std::nullopt;
m_cachedWifiIP = std::nullopt;
} }
void StatusDisplay::redraw() void StatusDisplay::redraw()
@ -157,13 +173,38 @@ void StatusDisplay::redraw()
m_backStatus.redraw(controllers.back); m_backStatus.redraw(controllers.back);
tft.setTextFont(2); tft.setTextFont(2);
m_labelWifiStatus.redraw(wifi_stack::toString(wifi_stack::get_sta_status()));
m_labelLimit0.redraw(std::to_string(controllers.front.command.left.iMotMax) + "A"); if (!m_cachedWifiStatus || espchrono::ago(m_cachedWifiStatus->timestamp) >= 500ms)
{
const auto staStatus = wifi_stack::get_sta_status();
if (staStatus == wifi_stack::WiFiStaStatus::WL_CONNECTED)
{
if (const auto result = wifi_stack::get_sta_ap_info(); result)
{
m_cachedWifiStatus = CachedString{ .text = std::string{reinterpret_cast<const char*>(result->ssid)} };
}
else
{
ESP_LOGW("BOBBY", "get_sta_ap_info() failed with %.*s", result.error().size(), result.error().data());
goto showStaStatus;
}
}
else
{
showStaStatus:
m_cachedWifiStatus = CachedString{ .text = wifi_stack::toString(staStatus) };
}
}
assert(m_cachedWifiStatus);
m_labelWifiStatus.redraw(m_cachedWifiStatus->text);
m_labelLimit0.redraw(fmt::format("{}A", controllers.front.command.left.iMotMax));
if (const auto result = wifi_stack::get_ip_info(TCPIP_ADAPTER_IF_STA)) if (const auto result = wifi_stack::get_ip_info(TCPIP_ADAPTER_IF_STA))
m_labelIpAddress.redraw(wifi_stack::toString(result->ip)); m_labelIpAddress.redraw(wifi_stack::toString(result->ip));
else else
m_labelIpAddress.clear(); m_labelIpAddress.clear();
m_labelLimit1.redraw(std::to_string(controllers.front.command.left.iDcMax) + "A"); m_labelLimit1.redraw(fmt::format("{}A", controllers.front.command.left.iDcMax));
m_labelPerformance.redraw(std::to_string(performance.last)); m_labelPerformance.redraw(std::to_string(performance.last));
m_labelMode.redraw(currentMode->displayName()); m_labelMode.redraw(currentMode->displayName());
m_labelName.redraw(deviceName); m_labelName.redraw(deviceName);

View File

@ -90,4 +90,14 @@ ModeInterface *lastMode{};
ModeInterface *currentMode{}; ModeInterface *currentMode{};
std::unique_ptr<Display> currentDisplay; std::unique_ptr<Display> currentDisplay;
#ifdef FEATURE_LEDBACKLIGHT
constexpr const bool ledBacklightInverted =
#ifdef LEDBACKLIGHT_INVERTED
true
#else
false
#endif
;
#endif
} }

View File

@ -102,11 +102,15 @@ using namespace std::chrono_literals;
#include "wifi_bobbycar.h" #include "wifi_bobbycar.h"
namespace { namespace {
std::optional<espchrono::millis_clock::time_point> lastWifiUpdate;
std::optional<espchrono::millis_clock::time_point> lastPotiRead; std::optional<espchrono::millis_clock::time_point> lastPotiRead;
std::optional<espchrono::millis_clock::time_point> lastModeUpdate; std::optional<espchrono::millis_clock::time_point> lastModeUpdate;
std::optional<espchrono::millis_clock::time_point> lastStatsUpdate; std::optional<espchrono::millis_clock::time_point> lastStatsUpdate;
std::optional<espchrono::millis_clock::time_point> lastDisplayUpdate; std::optional<espchrono::millis_clock::time_point> lastDisplayUpdate;
std::optional<espchrono::millis_clock::time_point> lastDisplayRedraw; std::optional<espchrono::millis_clock::time_point> lastDisplayRedraw;
#ifdef FEATURE_CAN
std::optional<espchrono::millis_clock::time_point> lastCanParse;
#endif
#ifdef FEATURE_BLE #ifdef FEATURE_BLE
std::optional<espchrono::millis_clock::time_point> lastBleUpdate; std::optional<espchrono::millis_clock::time_point> lastBleUpdate;
#endif #endif
@ -126,9 +130,9 @@ extern "C" void app_main()
//Serial.setDebugOutput(true); //Serial.setDebugOutput(true);
//Serial.println("setup()"); //Serial.println("setup()");
#ifdef PINS_LED #ifdef FEATURE_LEDBACKLIGHT
pinMode(PINS_LED, OUTPUT); pinMode(PINS_LEDBACKLIGHT, OUTPUT);
digitalWrite(PINS_LED, LOW); digitalWrite(PINS_LEDBACKLIGHT, ledBacklightInverted ? LOW : HIGH);
#endif #endif
printMemoryStats("setup()"); printMemoryStats("setup()");
@ -268,18 +272,22 @@ extern "C" void app_main()
printMemoryStats("readPotis()"); printMemoryStats("readPotis()");
#ifdef FEATURE_CLOUD #ifdef FEATURE_CLOUD
bootLabel.redraw("startCloud");
startCloud(); startCloud();
printMemoryStats("readPotis()");
#endif #endif
bootLabel.redraw("switchScreen");
#if defined(FEATURE_DPAD_5WIRESW) && defined(DPAD_5WIRESW_DEBUG) #if defined(FEATURE_DPAD_5WIRESW) && defined(DPAD_5WIRESW_DEBUG)
switchScreen<DPad5WireDebugDisplay>(); switchScreen<DPad5WireDebugDisplay>();
return; #else
#endif
if (!gas || !brems || *gas > 200.f || *brems > 200.f) if (!gas || !brems || *gas > 200.f || *brems > 200.f)
switchScreen<CalibrateDisplay>(true); switchScreen<CalibrateDisplay>(true);
else else
switchScreen<StatusDisplay>(); switchScreen<StatusDisplay>();
#endif
printMemoryStats("switchScreen()"); printMemoryStats("switchScreen()");
@ -290,7 +298,12 @@ extern "C" void app_main()
const auto now = espchrono::millis_clock::now(); const auto now = espchrono::millis_clock::now();
wifi_update(); if (!lastWifiUpdate || now - *lastWifiUpdate >= 100ms)
{
wifi_update();
lastWifiUpdate = now;
}
#ifdef FEATURE_DPAD #ifdef FEATURE_DPAD
dpad::update(); dpad::update();
@ -359,7 +372,12 @@ extern "C" void app_main()
} }
#ifdef FEATURE_CAN #ifdef FEATURE_CAN
can::parseCanInput(); if (!lastCanParse || now - *lastCanParse >= 50ms)
{
can::parseCanInput();
lastCanParse = now;
}
#endif #endif
#ifdef FEATURE_SERIAL #ifdef FEATURE_SERIAL

View File

@ -32,7 +32,11 @@ constexpr Settings::ControllerHardware defaultControllerHardware {
.wheelDiameter = DEFAULT_WHEELDIAMETER, .wheelDiameter = DEFAULT_WHEELDIAMETER,
.numMagnetPoles = 15, .numMagnetPoles = 15,
.swapFrontBack = false .swapFrontBack = false,
#ifdef FEATURE_CAN
.sendFrontCanCmd = true,
.sendBackCanCmd = true,
#endif
}; };
constexpr Settings::ControllerHardware mosfetsOffControllerHardware { constexpr Settings::ControllerHardware mosfetsOffControllerHardware {
@ -48,7 +52,11 @@ constexpr Settings::ControllerHardware mosfetsOffControllerHardware {
.wheelDiameter = 165, .wheelDiameter = 165,
.numMagnetPoles = 15, .numMagnetPoles = 15,
.swapFrontBack = false .swapFrontBack = false,
#ifdef FEATURE_CAN
.sendFrontCanCmd = true,
.sendBackCanCmd = true,
#endif
}; };
constexpr Settings::WifiSettings defaultWifiSettings { constexpr Settings::WifiSettings defaultWifiSettings {
@ -75,7 +83,11 @@ constexpr Settings::ControllerHardware spinnerControllerHardware {
.wheelDiameter = 165, .wheelDiameter = 165,
.numMagnetPoles = 15, .numMagnetPoles = 15,
.swapFrontBack = false .swapFrontBack = false,
#ifdef FEATURE_CAN
.sendFrontCanCmd = true,
.sendBackCanCmd = true,
#endif
}; };
constexpr Settings::BoardcomputerHardware::TimersSettings defaultTimersSettings { constexpr Settings::BoardcomputerHardware::TimersSettings defaultTimersSettings {
@ -87,7 +99,7 @@ constexpr Settings::BoardcomputerHardware::TimersSettings defaultTimersSettings
}; };
constexpr Settings::BoardcomputerHardware defaultBoardcomputerHardware { constexpr Settings::BoardcomputerHardware defaultBoardcomputerHardware {
.sampleCount = 100, .sampleCount = 50,
.gasMin = DEFAULT_GASMIN, .gasMin = DEFAULT_GASMIN,
.gasMax = DEFAULT_GASMAX, .gasMax = DEFAULT_GASMAX,
.bremsMin = DEFAULT_BREMSMIN, .bremsMin = DEFAULT_BREMSMIN,

View File

@ -51,7 +51,13 @@ struct Settings
int16_t wheelDiameter; // in mm int16_t wheelDiameter; // in mm
int16_t numMagnetPoles; // virtual RPM per one real RPM int16_t numMagnetPoles; // virtual RPM per one real RPM
bool swapFrontBack; bool swapFrontBack;
#ifdef FEATURE_CAN
bool sendFrontCanCmd;
bool sendBackCanCmd;
#endif
} controllerHardware; } controllerHardware;
struct BoardcomputerHardware { struct BoardcomputerHardware {
@ -143,6 +149,10 @@ void Settings::executeForEverySetting(T &&callable)
callable("wheelDiameter", controllerHardware.wheelDiameter); callable("wheelDiameter", controllerHardware.wheelDiameter);
callable("numMagnetPoles", controllerHardware.numMagnetPoles); callable("numMagnetPoles", controllerHardware.numMagnetPoles);
callable("swapFrontBack", controllerHardware.swapFrontBack); callable("swapFrontBack", controllerHardware.swapFrontBack);
#ifdef FEATURE_CAN
callable("sendFrontCanCmd", controllerHardware.sendFrontCanCmd);
callable("sendBackCanCmd", controllerHardware.sendBackCanCmd);
#endif
callable("sampleCount", boardcomputerHardware.sampleCount); callable("sampleCount", boardcomputerHardware.sampleCount);
callable("gasMin", boardcomputerHardware.gasMin); callable("gasMin", boardcomputerHardware.gasMin);
@ -161,6 +171,7 @@ void Settings::executeForEverySetting(T &&callable)
callable("gametrakDistMax", boardcomputerHardware.gametrakDistMax); callable("gametrakDistMax", boardcomputerHardware.gametrakDistMax);
#endif #endif
callable("swapScreenBytes", boardcomputerHardware.swapScreenBytes); callable("swapScreenBytes", boardcomputerHardware.swapScreenBytes);
callable("potiReadRate", boardcomputerHardware.timersSettings.potiReadRate); callable("potiReadRate", boardcomputerHardware.timersSettings.potiReadRate);
callable("modeUpdateRate", boardcomputerHardware.timersSettings.modeUpdateRate); callable("modeUpdateRate", boardcomputerHardware.timersSettings.modeUpdateRate);
callable("statsUpdateRate", boardcomputerHardware.timersSettings.statsUpdateRate); callable("statsUpdateRate", boardcomputerHardware.timersSettings.statsUpdateRate);

View File

@ -74,6 +74,7 @@ constexpr char TEXT_DEBUG[] = "Debug";
//SettingsMenu //SettingsMenu
//constexpr char TEXT_SETTINGS[] = "Settings"; //constexpr char TEXT_SETTINGS[] = "Settings";
constexpr char TEXT_BACKLIGHT[] = "Backlight";
constexpr char TEXT_LIMITSSETTINGS[] = "Limits settings"; constexpr char TEXT_LIMITSSETTINGS[] = "Limits settings";
constexpr char TEXT_WIFISETTINGS[] = "WiFi settings"; constexpr char TEXT_WIFISETTINGS[] = "WiFi settings";
//constexpr char TEXT_BLUETOOTHSETTINGS[] = "Bluetooth settings"; //constexpr char TEXT_BLUETOOTHSETTINGS[] = "Bluetooth settings";
@ -95,6 +96,10 @@ constexpr char TEXT_NUMMAGNETPOLES[] = "Num magnet poles";
constexpr char TEXT_SETENABLED[] = "Set enabled"; constexpr char TEXT_SETENABLED[] = "Set enabled";
constexpr char TEXT_SETINVERTED[] = "Set inverted"; constexpr char TEXT_SETINVERTED[] = "Set inverted";
constexpr char TEXT_SWAPFRONTBACK[] = "Swap front/back"; constexpr char TEXT_SWAPFRONTBACK[] = "Swap front/back";
#ifdef FEATURE_CAN
constexpr char TEXT_FRONTSENDCAN[] = "Front send CAN";
constexpr char TEXT_BACKSENDCAN[] = "Back send CAN";
#endif
//constexpr char TEXT_BACK[] = "Back"; //constexpr char TEXT_BACK[] = "Back";
//StationWifiSettingsMenu //StationWifiSettingsMenu

View File

@ -4,8 +4,6 @@
#include <utility> #include <utility>
#include <string> #include <string>
#include <driver/twai.h>
#ifdef FEATURE_SERIAL #ifdef FEATURE_SERIAL
#include <HardwareSerial.h> #include <HardwareSerial.h>
#endif #endif

View File

@ -14,7 +14,7 @@ public:
int y() const { return m_y; }; int y() const { return m_y; };
void start(); void start();
void redraw(const std::string &str, bool forceRedraw = false); void redraw(std::string_view str, bool forceRedraw = false);
void clear(); void clear();
private: private:
@ -45,7 +45,7 @@ void Label::start()
m_lastHeight = 0; m_lastHeight = 0;
} }
void Label::redraw(const std::string &str, bool forceRedraw) void Label::redraw(std::string_view str, bool forceRedraw)
{ {
if (m_lastStr == str && if (m_lastStr == str &&
m_lastFont == tft.textfont && m_lastFont == tft.textfont &&
@ -53,7 +53,7 @@ void Label::redraw(const std::string &str, bool forceRedraw)
!forceRedraw) !forceRedraw)
return; return;
const auto renderedWidth = tft.drawString(str.c_str(), m_x, m_y); const auto renderedWidth = tft.drawString(str.data(), m_x, m_y);
const auto renderedHeight = tft.fontHeight(); const auto renderedHeight = tft.fontHeight();
if (renderedWidth < m_lastWidth) if (renderedWidth < m_lastWidth)

View File

@ -9,14 +9,14 @@
namespace { namespace {
wifi_stack::config wifi_create_config() wifi_stack::config wifi_create_config()
{ {
return wifi_stack::config { static wifi_stack::config config {
.wifiEnabled = true, .wifiEnabled = true,
.hostname = deviceName, .hostname = deviceName,
.sta = { .sta = {
.wifis = std::array<wifi_stack::wifi_entry, 10> { .wifis = std::array<wifi_stack::wifi_entry, 10> {
wifi_stack::wifi_entry { .ssid = "realraum", .key = "r3alraum" }, wifi_stack::wifi_entry { .ssid = "realraum", .key = "r3alraum" },
wifi_stack::wifi_entry { .ssid = "McDonalds Free WiFi", .key = "Passwort_123" }, wifi_stack::wifi_entry { .ssid = "McDonalds Free WiFi", .key = "Passwort_123" },
wifi_stack::wifi_entry { .ssid = "***REMOVED***", .key = "***REMOVED***" }, wifi_stack::wifi_entry { .ssid = {}, .key = {} },
wifi_stack::wifi_entry { .ssid = {}, .key = {} }, wifi_stack::wifi_entry { .ssid = {}, .key = {} },
wifi_stack::wifi_entry { .ssid = {}, .key = {} }, wifi_stack::wifi_entry { .ssid = {}, .key = {} },
wifi_stack::wifi_entry { .ssid = {}, .key = {} }, wifi_stack::wifi_entry { .ssid = {}, .key = {} },
@ -42,6 +42,8 @@ wifi_stack::config wifi_create_config()
.beacon_interval = 100 .beacon_interval = 100
} }
}; };
return config;
} }
void wifi_begin() void wifi_begin()

8
open_ide.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
if [[ -z "$IDF_PATH" ]]
then
source export.sh --skip-source-check
fi
qtcreator "bobbycar-boardcomputer-firmware" 2>&1 >/dev/null &