Separate PW Limit calculation into own function and optimise. Add unit tests for this

This commit is contained in:
Josh Stewart 2024-01-16 22:25:15 +11:00
parent 288b98d31c
commit 1439750731
4 changed files with 58 additions and 9 deletions

View File

@ -20,6 +20,7 @@ void loop(void);
uint16_t PW(int REQ_FUEL, byte VE, long MAP, uint16_t corrections, int injOpen);
byte getVE1(void);
byte getAdvance1(void);
uint16_t calculatePWLimit();
void calculateStaging(uint32_t);
void calculateIgnitionAngles(int dwellAngle);
void checkLaunchAndFlatShift();

View File

@ -467,14 +467,7 @@ void loop(void)
#endif
//Check that the duty cycle of the chosen pulsewidth isn't too high.
uint32_t pwLimit = percentage(configPage2.dutyLim, revolutionTime); //The pulsewidth limit is determined to be the duty cycle limit (Eg 85%) by the total time it takes to perform 1 revolution
//Handle multiple squirts per rev
if (configPage2.strokes == FOUR_STROKE) { pwLimit = pwLimit * 2; }
// This requires 32-bit division, which is very slow on Mega 2560.
// So only divide if necessary - nSquirts is often only 1.
if (currentStatus.nSquirts!=1) {
pwLimit = pwLimit / currentStatus.nSquirts;
}
uint16_t pwLimit = calculatePWLimit();
//Apply the pwLimit if staging is disabled and engine is not cranking
if( (!BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) && (configPage10.stagingEnabled == false) ) { if (currentStatus.PW1 > pwLimit) { currentStatus.PW1 = pwLimit; } }
@ -1440,6 +1433,36 @@ void calculateIgnitionAngles(int dwellAngle)
}
}
uint16_t calculatePWLimit()
{
uint32_t tempLimit = percentage(configPage2.dutyLim, revolutionTime); //The pulsewidth limit is determined to be the duty cycle limit (Eg 85%) by the total time it takes to perform 1 revolution
//Handle multiple squirts per rev
if (configPage2.strokes == FOUR_STROKE) { tempLimit = tempLimit * 2; }
//Optimise for power of two divisions where possible
switch(currentStatus.nSquirts)
{
case 1:
//No action needed
break;
case 2:
tempLimit = tempLimit / 2;
break;
case 4:
tempLimit = tempLimit / 4;
break;
case 8:
tempLimit = tempLimit / 8;
break;
default:
//Non-PoT squirts value. Perform (slow) uint32_t division
tempLimit = tempLimit / currentStatus.nSquirts;
break;
}
if(tempLimit > UINT16_MAX) { tempLimit = UINT16_MAX; }
return tempLimit;
}
void calculateStaging(uint32_t pwLimit)
{
//Calculate staging pulsewidths if used

View File

@ -14,6 +14,8 @@ void testPW(void)
RUN_TEST(test_PW_Large_Correction);
RUN_TEST(test_PW_Very_Large_Correction);
RUN_TEST(test_PW_4Cyl_PW0);
RUN_TEST(test_PW_Limit_Long_Revolution);
RUN_TEST(test_PW_Limit_90pct);
}
int16_t REQ_FUEL;
@ -141,4 +143,25 @@ void test_PW_4Cyl_PW0(void)
loop();
TEST_ASSERT_EQUAL(0, currentStatus.PW3);
TEST_ASSERT_EQUAL(0, currentStatus.PW4);
}
//Tests the PW Limit calculation for a normal scenario
void test_PW_Limit_90pct(void)
{
revolutionTime = 10000UL; //6000 rpm
configPage2.dutyLim = 90;
//Duty limit of 90% for 10,000uS should give 9,000
TEST_ASSERT_EQUAL(9000, calculatePWLimit());
}
//Tests the PW Limit calculation when the revolution time is greater than the max UINT16 value
//Occurs at approx. 915rpm
void test_PW_Limit_Long_Revolution(void)
{
revolutionTime = 100000UL; //600 rpm, below 915rpm cutover point
configPage2.dutyLim = 90;
//Duty limit of 90% for 100,000uS should give 90,000, but as this would overflow the PW value, this should default to UINT16 Max
TEST_ASSERT_EQUAL(UINT16_MAX, calculatePWLimit());
}

View File

@ -6,4 +6,6 @@ void test_PW_MAP_Multiply_Compatibility(void);
void test_PW_ALL_Multiply(void);
void test_PW_Large_Correction();
void test_PW_Very_Large_Correction();
void test_PW_4Cyl_PW0(void);
void test_PW_4Cyl_PW0(void);
void test_PW_Limit_90pct(void);
void test_PW_Limit_Long_Revolution(void);