Add unit tests for staging and update other tests

This commit is contained in:
Josh Stewart 2023-06-26 11:48:54 +10:00
parent e44f4c7b54
commit 2a6c6bd8ed
6 changed files with 219 additions and 16 deletions

View File

@ -13,6 +13,7 @@ void testPW(void)
RUN_TEST(test_PW_AFR_Multiply);
RUN_TEST(test_PW_Large_Correction);
RUN_TEST(test_PW_Very_Large_Correction);
RUN_TEST(test_PW_4Cyl_PW0);
}
int16_t REQ_FUEL;
@ -125,4 +126,19 @@ void test_PW_Very_Large_Correction()
uint16_t result = PW(REQ_FUEL, VE, MAP, corrections, injOpen);
TEST_ASSERT_UINT16_WITHIN(PW_ALLOWED_ERROR+30, 21670, result); //Additional allowed error here
}
//Test that unused pulse width values are set to 0
//This test is for a 4 cylinder using paired injection where only INJ 1 and 2 should have PW > 0
void test_PW_4Cyl_PW0(void)
{
test_PW_setCommon();
configPage2.nCylinders = 4;
configPage2.injLayout = INJ_PAIRED;
configPage10.stagingEnabled = false; //Staging must be off or channels 3 and 4 will be used
loop();
TEST_ASSERT_EQUAL(0, currentStatus.PW3);
TEST_ASSERT_EQUAL(0, currentStatus.PW4);
}

View File

@ -5,4 +5,5 @@ void test_PW_AFR_Multiply(void);
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_Very_Large_Correction();
void test_PW_4Cyl_PW0(void);

View File

@ -5,6 +5,7 @@
#include "test_corrections.h"
#include "test_PW.h"
#include "test_staging.h"
#define UNITY_EXCLUDE_DETAILS
@ -21,6 +22,7 @@ void setup()
initialiseAll(); //Run the main initialise function
testCorrections();
testPW();
testStaging();
UNITY_END(); // stop unit testing
}

View File

@ -0,0 +1,175 @@
#include <globals.h>
#include <speeduino.h>
#include <unity.h>
#include "test_staging.h"
void testStaging(void)
{
RUN_TEST(test_Staging_Off);
RUN_TEST(test_Staging_4cyl_Auto_Inactive);
RUN_TEST(test_Staging_4cyl_Table_Inactive);
RUN_TEST(test_Staging_4cyl_Auto_50pct);
RUN_TEST(test_Staging_4cyl_Auto_33pct);
RUN_TEST(test_Staging_4cyl_Table_50pct);
}
void test_Staging_setCommon()
{
configPage2.nCylinders = 4;
currentStatus.RPM = 3000;
currentStatus.fuelLoad = 50;
inj_opentime_uS = 1000; //1ms inj open time
/*
These values are a percentage of the req_fuel value that would be required for each injector channel to deliver that much fuel.
Eg:
Pri injectors are 250cc
Sec injectors are 500cc
Total injector capacity = 750cc
staged_req_fuel_mult_pri = 300% (The primary injectors would have to run 3x the overall PW in order to be the equivalent of the full 750cc capacity
staged_req_fuel_mult_sec = 150% (The secondary injectors would have to run 1.5x the overall PW in order to be the equivalent of the full 750cc capacity
*/
configPage10.stagedInjSizePri = 250;
configPage10.stagedInjSizeSec = 500;
uint32_t totalInjector = configPage10.stagedInjSizePri + configPage10.stagedInjSizeSec;
staged_req_fuel_mult_pri = (100 * totalInjector) / configPage10.stagedInjSizePri;
staged_req_fuel_mult_sec = (100 * totalInjector) / configPage10.stagedInjSizeSec;
}
void test_Staging_Off(void)
{
test_Staging_setCommon();
BIT_SET(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE);
configPage10.stagingEnabled = false;
uint32_t pwLimit = 9000; //90% duty cycle at 6000rpm
calculateStaging(pwLimit);
TEST_ASSERT_FALSE(BIT_CHECK(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE));
}
void test_Staging_4cyl_Auto_Inactive(void)
{
test_Staging_setCommon();
uint16_t testPW = 3000;
BIT_SET(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE);
configPage2.injLayout = INJ_PAIRED;
configPage10.stagingEnabled = true;
configPage10.stagingMode = STAGING_MODE_AUTO;
currentStatus.PW1 = testPW; //Over open time but below the pwLimit set below
uint32_t pwLimit = 9000; //90% duty cycle at 6000rpm
calculateStaging(pwLimit);
//PW 1 and 2 should be normal, 3 and 4 should be 0 as that testPW is below the pwLimit
//PW1/2 should be (PW - openTime) * staged_req_fuel_mult_pri = (3000 - 1000) * 3.0 = 6000
TEST_ASSERT_EQUAL(6000, currentStatus.PW1);
TEST_ASSERT_EQUAL(6000, currentStatus.PW2);
TEST_ASSERT_EQUAL(0, currentStatus.PW3);
TEST_ASSERT_EQUAL(0, currentStatus.PW4);
TEST_ASSERT_FALSE(BIT_CHECK(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE));
}
void test_Staging_4cyl_Table_Inactive(void)
{
test_Staging_setCommon();
uint16_t testPW = 3000;
BIT_SET(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE);
configPage2.injLayout = INJ_PAIRED;
configPage10.stagingEnabled = true;
configPage10.stagingMode = STAGING_MODE_TABLE;
currentStatus.PW1 = testPW; //Over open time but below the pwLimit set below
//Load the staging table with all 0
//For this test it doesn't matter what the X and Y axis are, as the table is all 0 values
for(byte x=0; x<64; x++) { stagingTable.values.values[x] = 0; }
uint32_t pwLimit = 9000; //90% duty cycle at 6000rpm
calculateStaging(pwLimit);
//PW 1 and 2 should be normal, 3 and 4 should be 0 as that testPW is below the pwLimit
//PW1/2 should be (PW - openTime) * staged_req_fuel_mult_pri = (3000 - 1000) * 3.0 = 6000
TEST_ASSERT_EQUAL(7000, currentStatus.PW1);
TEST_ASSERT_EQUAL(7000, currentStatus.PW2);
TEST_ASSERT_EQUAL(0, currentStatus.PW3);
TEST_ASSERT_EQUAL(0, currentStatus.PW4);
TEST_ASSERT_FALSE(BIT_CHECK(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE));
}
void test_Staging_4cyl_Auto_50pct(void)
{
test_Staging_setCommon();
uint16_t testPW = 9000;
BIT_CLEAR(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE);
configPage2.injLayout = INJ_PAIRED;
configPage10.stagingEnabled = true;
configPage10.stagingMode = STAGING_MODE_AUTO;
currentStatus.PW1 = testPW; //Over open time but below the pwLimit set below
uint32_t pwLimit = 9000; //90% duty cycle at 6000rpm
calculateStaging(pwLimit);
//PW 1 and 2 should be maxed out at the pwLimit, 3 and 4 should be based on their relative size
TEST_ASSERT_EQUAL(pwLimit, currentStatus.PW1); //PW1/2 run at maximum available limit
TEST_ASSERT_EQUAL(pwLimit, currentStatus.PW2);
TEST_ASSERT_EQUAL(9000, currentStatus.PW3);
TEST_ASSERT_EQUAL(9000, currentStatus.PW4);
TEST_ASSERT_TRUE(BIT_CHECK(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE));
}
void test_Staging_4cyl_Auto_33pct(void)
{
test_Staging_setCommon();
uint16_t testPW = 7000;
BIT_CLEAR(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE);
configPage2.injLayout = INJ_PAIRED;
configPage10.stagingEnabled = true;
configPage10.stagingMode = STAGING_MODE_AUTO;
currentStatus.PW1 = testPW; //Over open time but below the pwLimit set below
uint32_t pwLimit = 9000; //90% duty cycle at 6000rpm
calculateStaging(pwLimit);
//PW 1 and 2 should be maxed out at the pwLimit, 3 and 4 should be based on their relative size
TEST_ASSERT_EQUAL(pwLimit, currentStatus.PW1); //PW1/2 run at maximum available limit
TEST_ASSERT_EQUAL(pwLimit, currentStatus.PW2);
TEST_ASSERT_EQUAL(6000, currentStatus.PW3);
TEST_ASSERT_EQUAL(6000, currentStatus.PW4);
TEST_ASSERT_TRUE(BIT_CHECK(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE));
}
void test_Staging_4cyl_Table_50pct(void)
{
test_Staging_setCommon();
uint16_t testPW = 3000;
BIT_CLEAR(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE);
configPage2.injLayout = INJ_PAIRED;
configPage10.stagingEnabled = true;
configPage10.stagingMode = STAGING_MODE_TABLE;
currentStatus.PW1 = testPW; //Over open time but below the pwLimit set below
//Load the staging table with all 0
//For this test it doesn't matter what the X and Y axis are, as the table is all 50 values
for(byte x=0; x<64; x++) { stagingTable.values.values[x] = 50; }
uint32_t pwLimit = 9000; //90% duty cycle at 6000rpm
//Need to change the lookup values so we don't get a cached value
currentStatus.RPM += 1;
currentStatus.fuelLoad += 1;
calculateStaging(pwLimit);
TEST_ASSERT_EQUAL(4000, currentStatus.PW1);
TEST_ASSERT_EQUAL(4000, currentStatus.PW2);
TEST_ASSERT_EQUAL(2500, currentStatus.PW3);
TEST_ASSERT_EQUAL(2500, currentStatus.PW4);
TEST_ASSERT_TRUE(BIT_CHECK(currentStatus.status4, BIT_STATUS4_STAGING_ACTIVE));
}

View File

@ -0,0 +1,7 @@
void testStaging();
void test_Staging_Off(void);
void test_Staging_4cyl_Auto_Inactive(void);
void test_Staging_4cyl_Table_Inactive(void);
void test_Staging_4cyl_Auto_50pct(void);
void test_Staging_4cyl_Auto_33pct(void);
void test_Staging_4cyl_Table_50pct(void);

View File

@ -13,15 +13,15 @@ static constexpr uint16_t reqFuel = 86; // ms * 10
static void __attribute__((noinline)) assert_fuel_channel(bool enabled, uint16_t angle, uint8_t cmdBit, int channelInjDegrees, voidVoidCallback startFunction, voidVoidCallback endFunction)
{
char msg[32];
char msg[39];
sprintf_P(msg, PSTR("channel%" PRIu8 "InjDegrees.isEnabled"), cmdBit+1);
TEST_ASSERT_EQUAL_MESSAGE(enabled, BIT_CHECK(channelInjEnabled, cmdBit), msg);
sprintf_P(msg, PSTR("channe%" PRIu8 "InjDegrees"), cmdBit+1);
sprintf_P(msg, PSTR("channel%" PRIu8 ".InjChannelIsEnabled. Max:%" PRIu8), cmdBit+1, maxInjOutputs);
TEST_ASSERT_TRUE_MESSAGE(!enabled || (cmdBit+1)<=maxInjOutputs, msg);
sprintf_P(msg, PSTR("channe%" PRIu8 ".InjDegrees"), cmdBit+1);
TEST_ASSERT_EQUAL_MESSAGE(angle, channelInjDegrees, msg);
sprintf_P(msg, PSTR("inj%" PRIu8 "StartFunction"), cmdBit+1);
sprintf_P(msg, PSTR("inj%" PRIu8 ".StartFunction"), cmdBit+1);
TEST_ASSERT_TRUE_MESSAGE(!enabled || (startFunction!=nullCallback), msg);
sprintf_P(msg, PSTR("inj%" PRIu8 "EndFunction"), cmdBit+1);
sprintf_P(msg, PSTR("inj%" PRIu8 ".EndFunction"), cmdBit+1);
TEST_ASSERT_TRUE_MESSAGE(!enabled || (endFunction!=nullCallback), msg);
}
@ -308,7 +308,8 @@ static void cylinder3_stroke4_semiseq_nostage(void)
initialiseAll(); //Run the main initialise function
const bool enabled[] = {true, true, true, false, false, false, false, false};
const uint16_t angle[] = {0,80,160,0,0,0,0,0};
assert_fuel_schedules(240U, reqFuel * 50U, enabled, angle);
//assert_fuel_schedules(240U, reqFuel * 50U, enabled, angle);
assert_fuel_schedules(720U, reqFuel * 50U, enabled, angle); //Special case as 3 squirts per cycle MUST be over 720 degrees
}
static void cylinder3_stroke4_seq_staged(void)
@ -340,7 +341,8 @@ static void cylinder3_stroke4_semiseq_staged(void)
#else
const bool enabled[] = {true, true, true, true, false, false, false, false};
const uint16_t angle[] = {0,80,160,0,0,0,0,0};
assert_fuel_schedules(240U, reqFuel * 50U, enabled, angle);
//assert_fuel_schedules(240U, reqFuel * 50U, enabled, angle);
assert_fuel_schedules(720U, reqFuel * 50U, enabled, angle); //Special case as 3 squirts per cycle MUST be over 720 degrees
#endif
}
@ -350,7 +352,7 @@ static void run_3_cylinder_4stroke_tests(void)
configPage2.strokes = FOUR_STROKE;
configPage2.engineType = EVEN_FIRE;
configPage2.reqFuel = reqFuel;
configPage2.divider = 1;
configPage2.divider = 1; //3 squirts per cycle for a 3 cylinder
RUN_TEST_P(cylinder3_stroke4_seq_nostage);
RUN_TEST_P(cylinder3_stroke4_semiseq_nostage);
@ -364,8 +366,8 @@ static void cylinder3_stroke2_seq_nostage(void)
configPage10.stagingEnabled = false;
initialiseAll(); //Run the main initialise function
const bool enabled[] = {true, true, true, false, false, false, false, false};
const uint16_t angle[] = {0,80,160,0,0,0,0,0};
assert_fuel_schedules(120U, reqFuel * 100U, enabled, angle);
const uint16_t angle[] = {0,120,240,0,0,0,0,0};
assert_fuel_schedules(360U, reqFuel * 100U, enabled, angle);
}
static void cylinder3_stroke2_semiseq_nostage(void)
@ -385,12 +387,12 @@ static void cylinder3_stroke2_seq_staged(void)
initialiseAll(); //Run the main initialise function
#if INJ_CHANNELS>=6
const bool enabled[] = {true, true, true, true, true, true, false, false};
const uint16_t angle[] = {0,80,160,0,80,160,0,0};
assert_fuel_schedules(120U, reqFuel * 100U, enabled, angle);
const uint16_t angle[] = {0,120,240,0,120,240,0,0};
assert_fuel_schedules(360U, reqFuel * 100U, enabled, angle);
#else
const bool enabled[] = {true, true, true, true, false, false, false, false};
const uint16_t angle[] = {0,80,160,0,0,0,0,0};
assert_fuel_schedules(120U, reqFuel * 100U, enabled, angle);
const uint16_t angle[] = {0,120,240,0,0,0,0,0};
assert_fuel_schedules(360U, reqFuel * 100U, enabled, angle);
#endif
}