resolve VVT phase using every tooth, not just sync point (#4434)

* resolve VVT phase using every tooth, not just sync point

* fix tests

* comment

* changelog
This commit is contained in:
Matthew Kennedy 2022-08-12 05:08:23 -07:00 committed by GitHub
parent 0907c009bd
commit fcb9897443
5 changed files with 35 additions and 13 deletions

View File

@ -35,6 +35,7 @@ Release template (copy/paste this for new release):
- Additional CAN messages #4401
- Option to invert VVT control (exhaust cams, etc) #4424
- Raw Battery gauge
- More accurate/stable VVT angle calculation #4433
### Fixed
- Lua CAN reception fixed for 11-bit IDs where the frame would be received, but a corrupt ID was passed to the handler function. #4321

View File

@ -79,7 +79,18 @@ expected<float> TriggerCentral::getCurrentEnginePhase(efitick_t nowNt) const {
return unexpected;
}
return m_syncPointTimer.getElapsedUs(nowNt) / oneDegreeUs;
float elapsed;
float toothPhase;
{
// under lock to avoid mismatched tooth phase and time
chibios_rt::CriticalSectionLocker csl;
elapsed = m_lastToothTimer.getElapsedUs(nowNt);
toothPhase = m_lastToothPhaseFromSyncPoint;
}
return toothPhase + elapsed / oneDegreeUs;
}
/**
@ -685,19 +696,28 @@ void TriggerCentral::handleShaftSignal(trigger_event_e signal, efitick_t timesta
int crankDivider = getCrankDivider(triggerShape.getOperationMode());
int crankInternalIndex = triggerState.getTotalRevolutionCounter() % crankDivider;
int triggerIndexForListeners = decodeResult.Value.CurrentIndex + (crankInternalIndex * triggerShape.getSize());
if (triggerIndexForListeners == 0) {
m_syncPointTimer.reset(timestamp);
}
reportEventToWaveChart(signal, triggerIndexForListeners);
// Compute the current engine absolute phase, 0 means currently at #1 TDC
auto currentPhase = engine->triggerCentral.triggerFormDetails.eventAngles[triggerIndexForListeners] - tdcPosition();
// Look up this tooth's angle from the sync point. If this tooth is the sync point, we'll get 0 here.
auto currentPhaseFromSyncPoint = engine->triggerCentral.triggerFormDetails.eventAngles[triggerIndexForListeners];
// Adjust so currentPhase is in engine-space angle, not trigger-space angle
auto currentPhase = currentPhaseFromSyncPoint - tdcPosition();
wrapAngle(currentPhase, "currentEnginePhase", CUSTOM_ERR_6555);
#if EFI_TUNER_STUDIO
engine->outputChannels.currentEnginePhase = currentPhase;
#endif // EFI_TUNER_STUDIO
// Record precise time and phase of the engine. This is used for VVT decode.
{
// under lock to avoid mismatched tooth phase and time
chibios_rt::CriticalSectionLocker csl;
m_lastToothTimer.reset(timestamp);
m_lastToothPhaseFromSyncPoint = currentPhaseFromSyncPoint;
}
#if TRIGGER_EXTREME_LOGGING
efiPrintf("trigger %d %d %d", triggerIndexForListeners, getRevolutionCounter(), (int)getTimeNowUs());
#endif /* TRIGGER_EXTREME_LOGGING */

View File

@ -140,9 +140,10 @@ public:
private:
void decodeMapCam(efitick_t nowNt, float currentPhase);
// Keep track of the last time we saw the sync tooth go by (trigger index 0)
// not TDC point
Timer m_syncPointTimer;
// Time since the last tooth
Timer m_lastToothTimer;
// Phase of the last tooth relative to the sync point
float m_lastToothPhaseFromSyncPoint;
};
void triggerInfo(void);

View File

@ -173,7 +173,7 @@ TEST(trigger, testNB2CamInput) {
eth.moveTimeForwardUs(MS2US( 30));
hwHandleVvtCamSignal(TV_RISE, getTimeNowNt(), 0);
EXPECT_NEAR(288.0f, engine->triggerCentral.getVVTPosition(0, 0), EPS2D);
EXPECT_NEAR(290.5f, engine->triggerCentral.getVVTPosition(0, 0), EPS2D);
// actually position based on VVT!
ASSERT_EQ(totalRevolutionCountBeforeVvtSync + 3, engine->triggerCentral.triggerState.getTotalRevolutionCounter());

View File

@ -23,13 +23,13 @@ TEST(realCrankingVQ40, normalCranking) {
float vvt1 = engine->triggerCentral.getVVTPosition(/*bankIndex*/0, /*camIndex*/0);
if (vvt1 != 0 && !hasSeenFirstVvt) {
EXPECT_NEAR(vvt1, -33.204, 1);
EXPECT_NEAR(vvt1, -45.56, 1);
hasSeenFirstVvt = true;
}
}
EXPECT_NEAR(engine->triggerCentral.getVVTPosition(/*bankIndex*/0, /*camIndex*/0), -46.817, 1e-2);
EXPECT_NEAR(engine->triggerCentral.getVVTPosition(/*bankIndex*/1, /*camIndex*/0), -47.411, 1e-2);
EXPECT_NEAR(engine->triggerCentral.getVVTPosition(/*bankIndex*/0, /*camIndex*/0), -45.67, 1e-2);
EXPECT_NEAR(engine->triggerCentral.getVVTPosition(/*bankIndex*/1, /*camIndex*/0), -45.47, 1e-2);
ASSERT_EQ(241, round(Sensor::getOrZero(SensorType::Rpm)))<< reader.lineIndex();
// TODO: why warnings?