fome-fw/firmware/controllers/algo/gear_detector.cpp

84 lines
2.1 KiB
C++
Raw Normal View History

#include "pch.h"
static constexpr float geometricMean(float x, float y) {
return sqrtf(x * y);
}
void GearDetector::onConfigurationChange(engine_configuration_s const * /*previousConfig*/) {
// Compute gear thresholds between gears
for (size_t i = 0; i < efi::size(m_gearThresholds); i++) {
// Threshold i is the threshold between gears i and i+1
m_gearThresholds[i] = geometricMean(
engineConfiguration->gearRatio[i],
engineConfiguration->gearRatio[i + 1]
);
// TODO: validate gears are in correct order
}
}
void GearDetector::onSlowCallback() {
float ratio = computeGearboxRatio();
m_gearboxRatio = ratio;
m_currentGear = determineGearFromRatio(ratio);
}
size_t GearDetector::determineGearFromRatio(float ratio) const {
// 1.5x first gear is neutral or clutch slip or something
if (ratio > engineConfiguration->gearRatio[0] * 1.5f) {
return 0;
}
auto gearCount = engineConfiguration->totalGearsCount;
// 0.66x top gear is coasting with engine off or something
if (ratio < engineConfiguration->gearRatio[gearCount - 1] * 0.66f) {
return 0;
}
size_t currentGear = gearCount;
while (currentGear > 1) {
if (ratio < m_gearThresholds[currentGear - 2]) {
break;
}
currentGear--;
}
return currentGear;
}
float GearDetector::computeGearboxRatio() const {
auto vssKph = Sensor::getOrZero(SensorType::VehicleSpeed);
if (vssKph < 5) {
// Vehicle too slow to determine gearbox ratio, avoid div/0
return 0;
}
auto engineRpm = Sensor::getOrZero(SensorType::Rpm);
// Convert to wheel RPM
// km rev 1 hr
// ------ * ------------ * __________
// hr km 60 min
float wheelRpm = vssKph * engineConfiguration->driveWheelRevPerKm * (1 / 60.0f);
// Convert to driveshaft RPM
auto driveshaftRpm = wheelRpm * engineConfiguration->finalGearRatio;
return engineRpm / driveshaftRpm;
}
float GearDetector::getGearboxRatio() const {
return m_gearboxRatio;
}
size_t GearDetector::getCurrentGear() const {
return m_currentGear;
}