rusefi/firmware/controllers/algo/dynoview.cpp

156 lines
4.8 KiB
C++

/*
* @file dynoview.cpp
*
* @date Jan 05, 2025
* @author Alexey Ershov, (c) 2012-2025
*/
#include "pch.h"
#ifndef DYNO_TPS_THRESHOLD
#define DYNO_TPS_THRESHOLD 80
#endif
#if EFI_DYNO_VIEW
#include "dynoview.h"
void DynoView::init()
{
if (isInitialized) {
return;
}
isInitialized = true;
wheelOverallDiameterMm = (uint16_t)(config->dynoCarWheelDiaInch * 25.4 + config->dynoCarWheelTireWidthMm * config->dynoCarWheelAspectRatio * 0.01 * 2);
saeVaporPressure = 6.1078 * pow(10.0, (7.5 * config->dynoSaeTemperatureC) / (237.3 + config->dynoSaeTemperatureC)) * .02953 * (config->dynoSaeRelativeHumidity / 100.0);
saeBaroMmhg = 29.23 * (config->dynoSaeBaro / 100.0);
saeBaroCorrectionFactor = 29.23 / (saeBaroMmhg - saeVaporPressure);
saeTempCorrectionFactor = pow(((config->dynoSaeTemperatureC + 273.0) / 298.0), 0.5);
saeCorrectionFactor = 1.176 * (saeBaroCorrectionFactor * saeTempCorrectionFactor) - .176;
reset();
}
void DynoView::update()
{
init();
float rpm = Sensor::getOrZero(SensorType::Rpm);
rpm = efiRound(rpm, 1.0);
int intRpm = (int)rpm;
float tps = Sensor::getOrZero(SensorType::Tps1);
if(intRpm > 0) {
efitimeus_t timeStamp = getTimeNowUs();
float timeInSec = (float)(timeStamp) / US_PER_SECOND;
onRpm(intRpm, timeInSec, tps);
}
}
void DynoView::reset()
{
dynoViewPointPrev.rpm = -1;
dynoViewPointPrev.time = -1;
dynoViewPointPrev.tps = -1;
count = 0;
currentTorque = 0;
currentHP = 0;
}
bool DynoView::onRpm(int rpm, float time, float tps)
{
if (tps < dynoViewPointPrev.tps || tps < DYNO_TPS_THRESHOLD) {
reset();
return false;
}
if (dynoViewPointPrev.rpm > 0 && dynoViewPointPrev.time > 0) {
if(time < dynoViewPointPrev.time || rpm < dynoViewPointPrev.rpm)
{
return false;
}
int rpmDiff = rpm - dynoViewPointPrev.rpm;
if (rpmDiff < config->dynoRpmStep) {
return false;
}
}
dynoViewPoint.rpm = rpm;
dynoViewPoint.time = time;
dynoViewPoint.tps = tps;
dynoViewPoint.engineRps = dynoViewPoint.rpm / 60.0;
dynoViewPoint.axleRps = dynoViewPoint.engineRps / (config->dynoCarGearPrimaryReduction * config->dynoCarGearRatio * config->dynoCarGearFinalDrive);
dynoViewPoint.vMs = dynoViewPoint.axleRps * (wheelOverallDiameterMm / 1000.f) * 3.1416;
dynoViewPoint.mph = dynoViewPoint.vMs * 2.2369363;
if (dynoViewPointPrev.rpm > 0 && dynoViewPointPrev.time > 0)
{
dynoViewPoint.distanceM = ((dynoViewPoint.vMs + dynoViewPointPrev.vMs) / 2.0) * (dynoViewPoint.time - dynoViewPointPrev.time);
dynoViewPoint.aMs2 = (dynoViewPoint.vMs - dynoViewPointPrev.vMs) / (dynoViewPoint.time - dynoViewPointPrev.time);
dynoViewPoint.forceN = (config->dynoCarCargoMassKg + config->dynoCarCarMassKg) * dynoViewPoint.aMs2;
dynoViewPoint.forceDragN = 0.5 * airDensityKgM3 * (dynoViewPoint.vMs * dynoViewPoint.vMs) * config->dynoCarFrontalAreaM2 * config->dynoCarCoeffOfDrag;
dynoViewPoint.forceDragN = dynoViewPoint.forceDragN * saeCorrectionFactor;
dynoViewPoint.forceTotalN = dynoViewPoint.forceN + dynoViewPoint.forceDragN;
dynoViewPoint.torqueWheelNm = dynoViewPoint.forceTotalN * ((wheelOverallDiameterMm / 2.0) / 1000.0);
dynoViewPoint.torqueNm = dynoViewPoint.torqueWheelNm / (config->dynoCarGearPrimaryReduction * config->dynoCarGearRatio * config->dynoCarGearFinalDrive);
dynoViewPoint.torqueLbFt = dynoViewPoint.torqueNm * 0.737562;
dynoViewPoint.hp = dynoViewPoint.torqueLbFt * dynoViewPoint.rpm / 5252.0;
for(int i = 0; i < window_size-1; ++i)
{
memcpy(&tail_hp[i], &tail_hp[i + 1], sizeof(float));
memcpy(&tail_torque[i], &tail_torque[i + 1], sizeof(float));
}
tail_torque[window_size-1] = dynoViewPoint.torqueNm;
tail_hp[window_size-1] = dynoViewPoint.hp;
if(count == 0)
{
for(int i = 0; i < window_size-1; ++i) {
memcpy(&tail_hp[i], &tail_hp[window_size-1], sizeof(float));
memcpy(&tail_torque[i], &tail_torque[window_size-1], sizeof(float));
}
}
if (count < window_size) {
++count;
}
int accumulate_window_size = std::min(count, window_size);
currentTorque = accumulate_window(accumulate_window_size, tail_torque);
currentHP = accumulate_window(accumulate_window_size, tail_hp);
dynoViewPointPrev = dynoViewPoint;
return true;
}
dynoViewPointPrev = dynoViewPoint;
return false;
}
int getDynoviewHP() {
return engine->dynoInstance.currentHP;
}
int getDynoviewTorque() {
return engine->dynoInstance.currentTorque;
}
/**
* Periodic update function called from SlowCallback.
*/
void updateDynoView() {
engine->dynoInstance.update();
}
#endif /* EFI_DYNO_VIEW */