Files
bobbycar-boardcomputer-firm…/main/utils.cpp
T

284 lines
9.0 KiB
C++
Raw Normal View History

2021-11-01 20:44:57 +01:00
#include "utils.h"
2021-11-21 01:36:44 +01:00
// local includes
2021-11-15 01:53:35 +01:00
#include "globals.h"
2021-12-29 03:32:01 +01:00
#include "newsettings.h"
2021-11-01 20:44:57 +01:00
using namespace std::chrono_literals;
2021-12-19 16:48:42 +01:00
bool currentlyReverseBeeping{};
2021-11-01 20:44:57 +01:00
bool reverseBeepToggle;
espchrono::millis_clock::time_point lastReverseBeepToggle;
float convertToKmh(float val)
{
return val /* / settings.controllerHardware.numMagnetPoles */ / 60.f * settings.controllerHardware.wheelDiameter / 1000.f * 3.14159265359f * 3.6f;
}
float convertFromKmh(float val)
{
return val /* * settings.controllerHardware.numMagnetPoles */ * 60.f / settings.controllerHardware.wheelDiameter * 1000.f / 3.14159265359f / 3.6f;
}
float convertToInch(float val)
{
return val / 25.4f;
}
float convertFromInch(float val)
{
return val * 25.4f;
}
float fixCurrent(int16_t value)
{
return -value/50.;
}
float fixBoardTemp(int16_t value)
{
return value/10.;
}
std::string hallString(const bobbycar::protocol::serial::MotorFeedback &motor)
{
return std::string{} + (motor.hallA ? '1' : '0') + (motor.hallB ? '1' : '0') + (motor.hallC ? '1' : '0');
}
std::string to_string(bobbycar::protocol::ControlType value)
{
switch (value)
{
using namespace bobbycar::protocol;
case ControlType::Commutation: return "Commutation";
case ControlType::Sinusoidal: return "Sinusoidal";
case ControlType::FieldOrientedControl: return "FieldOrientedControl";
}
return fmt::format("Unknown ControlType({})", std::to_underlying(value));
}
std::string to_string(bobbycar::protocol::ControlMode value)
{
switch (value)
{
using namespace bobbycar::protocol;
case ControlMode::OpenMode: return "OpenMode";
case ControlMode::Voltage: return "Voltage";
case ControlMode::Speed: return "Speed";
case ControlMode::Torque: return "Torque";
}
return fmt::format("Unknown ControlMode({})", std::to_underlying(value));
}
std::array<std::reference_wrapper<bobbycar::protocol::serial::MotorState>, 2> motorsInController(Controller &controller)
{
return {std::ref(controller.command.left), std::ref(controller.command.right)};
}
std::array<std::reference_wrapper<const bobbycar::protocol::serial::MotorState>, 2> motorsInController(const Controller &controller)
{
return {std::ref(controller.command.left), std::ref(controller.command.right)};
}
std::array<std::reference_wrapper<bobbycar::protocol::serial::MotorFeedback>, 2> motorFeedbacksInController(Controller &controller)
{
return {std::ref(controller.feedback.left), std::ref(controller.feedback.right)};
}
std::array<std::reference_wrapper<const bobbycar::protocol::serial::MotorFeedback>, 2> motorFeedbacksInController(const Controller &controller)
{
return {std::ref(controller.feedback.left), std::ref(controller.feedback.right)};
}
std::array<std::reference_wrapper<bobbycar::protocol::serial::MotorState>, 4> motors()
{
return {
std::ref(controllers.front.command.left), std::ref(controllers.front.command.right),
std::ref(controllers.back.command.left), std::ref(controllers.back.command.right)
};
}
void fixCommonParams()
{
for (bobbycar::protocol::serial::MotorState &motor : motors())
{
motor.iMotMax = settings.limits.iMotMax;
motor.iDcMax = settings.limits.iDcMax;
motor.nMotMax = settings.limits.nMotMax;
motor.fieldWeakMax = settings.limits.fieldWeakMax;
motor.phaseAdvMax = settings.limits.phaseAdvMax;
}
2021-12-29 03:32:01 +01:00
if (configs.reverseBeep.value)
2021-11-01 20:44:57 +01:00
{
const auto x = motors();
const auto shouldBeep = std::all_of(std::begin(x), std::end(x), [](const bobbycar::protocol::serial::MotorState &motor){ return motor.pwm < 0; });
if (shouldBeep != currentlyReverseBeeping)
{
if (shouldBeep)
{
reverseBeepToggle = true;
lastReverseBeepToggle = espchrono::millis_clock::now();
for (auto &controller : controllers)
2021-12-29 03:32:01 +01:00
controller.command.buzzer = {.freq=configs.reverseBeepFreq0.value, .pattern=0};
2021-11-01 20:44:57 +01:00
}
else
for (auto &controller : controllers)
controller.command.buzzer = {};
currentlyReverseBeeping = shouldBeep;
}
2021-12-29 03:32:01 +01:00
else if (shouldBeep && espchrono::millis_clock::now() - lastReverseBeepToggle >= std::chrono::milliseconds{reverseBeepToggle?configs.reverseBeepDuration0.value:configs.reverseBeepDuration1.value})
2021-11-01 20:44:57 +01:00
{
reverseBeepToggle = !reverseBeepToggle;
for (auto &controller : controllers)
2021-12-29 03:32:01 +01:00
controller.command.buzzer = {.freq=uint8_t(reverseBeepToggle?configs.reverseBeepFreq0.value:configs.reverseBeepFreq1.value), .pattern=0};
2021-11-01 20:44:57 +01:00
lastReverseBeepToggle = espchrono::millis_clock::now();
}
}
else if (currentlyReverseBeeping)
{
for (auto &controller : controllers)
controller.command.buzzer = {};
currentlyReverseBeeping = false;
}
controllers.front.command.left.enable = settings.controllerHardware.enableFrontLeft;
controllers.front.command.right.enable = settings.controllerHardware.enableFrontRight;
controllers.back.command.left.enable = settings.controllerHardware.enableBackLeft;
controllers.back.command.right.enable = settings.controllerHardware.enableBackRight;
if (settings.controllerHardware.invertFrontLeft)
{
controllers.front.command.left.pwm = -controllers.front.command.left.pwm;
controllers.front.command.left.nCruiseMotTgt = -controllers.front.command.left.nCruiseMotTgt;
}
if (settings.controllerHardware.invertFrontRight)
{
controllers.front.command.right.pwm = -controllers.front.command.right.pwm;
controllers.front.command.right.nCruiseMotTgt = -controllers.front.command.right.nCruiseMotTgt;
}
if (settings.controllerHardware.invertBackLeft)
{
controllers.back.command.left.pwm = -controllers.back.command.left.pwm;
controllers.back.command.left.nCruiseMotTgt = -controllers.back.command.left.nCruiseMotTgt;
}
if (settings.controllerHardware.invertBackRight)
{
controllers.back.command.right.pwm = -controllers.back.command.right.pwm;
controllers.back.command.right.nCruiseMotTgt = -controllers.back.command.right.nCruiseMotTgt;
}
}
void sendCommands()
{
#ifdef FEATURE_SERIAL
using namespace bobbycar::protocol::serial;
for (Controller &controller : controllers)
{
controller.command.start = Command::VALID_HEADER;
controller.command.checksum = calculateChecksum(controller.command);
controller.serial.get().write((uint8_t *) &controller.command, sizeof(controller.command));
}
#endif
#ifdef FEATURE_CAN
can::sendCanCommands();
#endif
}
#ifdef FEATURE_SERIAL
void updateSwapFrontBack()
{
controllers.front.serial = settings.controllerHardware.swapFrontBack ? Serial2 : Serial1;
controllers.back.serial = settings.controllerHardware.swapFrontBack ? Serial1 : Serial2;
}
#endif
bool loadSettings()
{
bool result{true};
if (!settingsPersister.load(settings))
result = false;
return result;
}
bool saveSettings()
{
if (simplified) return true;
bool result{true};
if (!settingsPersister.save(settings))
result = false;
return result;
}
void updateAccumulators()
{
avgSpeed = 0.f;
sumCurrent = 0.f;
uint8_t count{0};
for (const Controller &controller : controllers)
{
if (!controller.feedbackValid)
continue;
avgSpeed +=
controller.feedback.left.speed * (controller.invertLeft ? -1 : 1) +
controller.feedback.right.speed * (controller.invertRight ? -1 : 1);
sumCurrent +=
controller.feedback.left.dcLink +
controller.feedback.right.dcLink;
count +=2;
}
if (count)
avgSpeed /= count;
sumCurrent = fixCurrent(sumCurrent);
avgSpeedKmh = convertToKmh(avgSpeed);
}
2021-11-05 20:12:18 +01:00
float wattToAmpere(float watt) {
float voltage = std::max(controllers.front.feedback.batVoltage, controllers.back.feedback.batVoltage);
if (voltage > 50) voltage = 50;
if (voltage < 30) voltage = 30;
return watt / voltage;
}
2021-11-21 01:36:44 +01:00
float wattToMotorCurrent(float watt)
{
2021-11-05 20:12:18 +01:00
return wattToAmpere(watt) / 4;
}
2021-11-15 01:53:35 +01:00
2021-11-21 02:16:37 +01:00
uint8_t time_to_percent(espchrono::milliseconds32 repeat, espchrono::milliseconds32 riseTime, espchrono::milliseconds32 fullTime, size_t numLeds, bool invert)
2021-11-15 20:38:54 +01:00
{
const auto now = espchrono::millis_clock::now().time_since_epoch() % repeat;
if (now <= riseTime)
{
if (invert)
2021-11-21 02:16:37 +01:00
return numLeds - ((now*numLeds) / riseTime);
2021-11-15 20:38:54 +01:00
else
2021-11-21 02:16:37 +01:00
return (now*numLeds) / riseTime;
2021-11-15 20:38:54 +01:00
}
else if (now < riseTime + fullTime)
2021-11-21 02:16:37 +01:00
return invert ? 0 : numLeds;
2021-11-15 20:38:54 +01:00
else
2021-11-21 02:16:37 +01:00
return invert ? numLeds : 0;
2021-11-15 20:38:54 +01:00
}
2021-12-13 22:13:39 +01:00
std::string local_clock_string()
{
#ifdef CONFIG_ESPCHRONO_SUPPORT_DEFAULT_TIMEZONE
const auto now = espchrono::local_clock::now();
#else // mir egal ob die lokalzeit richtig is
const auto now = espchrono::utc_clock::now() + configs.timezoneOffset.value;
#endif
const auto dt = espchrono::toDateTime(now);
2021-12-13 22:13:39 +01:00
return fmt::format("{:02d}:{:02d}:{:02d}", dt.hour, dt.minute, dt.second);
}