Example unit tests for corrections
This commit is contained in:
parent
e7dbbb2a75
commit
a5d3a311b6
|
@ -7,19 +7,19 @@ All functions in the gamma file return
|
|||
|
||||
void initialiseCorrections();
|
||||
|
||||
static inline uint16_t correctionsFuel() __attribute__((always_inline));
|
||||
static inline byte correctionWUE() __attribute__((always_inline)); //Warmup enrichment
|
||||
static inline byte correctionCranking() __attribute__((always_inline)); //Cranking enrichment
|
||||
static inline byte correctionASE() __attribute__((always_inline)); //After Start Enrichment
|
||||
static inline uint16_t correctionAccel() __attribute__((always_inline)); //Acceleration Enrichment
|
||||
static inline byte correctionFloodClear() __attribute__((always_inline)); //Check for flood clear on cranking
|
||||
static inline byte correctionAFRClosedLoop() __attribute__((always_inline)); //Closed loop AFR adjustment
|
||||
static inline byte correctionFlex() __attribute__((always_inline)); //Flex fuel adjustment
|
||||
static inline byte correctionBatVoltage() __attribute__((always_inline)); //Battery voltage correction
|
||||
static inline byte correctionIATDensity() __attribute__((always_inline)); //Inlet temp density correction
|
||||
static inline byte correctionBaro() __attribute__((always_inline)); //Barometric pressure correction
|
||||
static inline byte correctionLaunch() __attribute__((always_inline)); //Launch control correction
|
||||
static inline bool correctionDFCO() __attribute__((always_inline)); //Decelleration fuel cutoff
|
||||
uint16_t correctionsFuel();
|
||||
byte correctionWUE(); //Warmup enrichment
|
||||
byte correctionCranking(); //Cranking enrichment
|
||||
byte correctionASE(); //After Start Enrichment
|
||||
uint16_t correctionAccel(); //Acceleration Enrichment
|
||||
byte correctionFloodClear(); //Check for flood clear on cranking
|
||||
byte correctionAFRClosedLoop(); //Closed loop AFR adjustment
|
||||
byte correctionFlex(); //Flex fuel adjustment
|
||||
byte correctionBatVoltage(); //Battery voltage correction
|
||||
byte correctionIATDensity(); //Inlet temp density correction
|
||||
byte correctionBaro(); //Barometric pressure correction
|
||||
byte correctionLaunch(); //Launch control correction
|
||||
bool correctionDFCO(); //Decelleration fuel cutoff
|
||||
|
||||
int8_t correctionsIgn(int8_t advance);
|
||||
static inline int8_t correctionFixedTiming(int8_t);
|
||||
|
@ -36,10 +36,10 @@ static inline int8_t correctionKnock(int8_t);
|
|||
|
||||
uint16_t correctionsDwell(uint16_t dwell);
|
||||
|
||||
uint16_t AFRnextCycle;
|
||||
unsigned long knockStartTime;
|
||||
byte lastKnockCount;
|
||||
int16_t knockWindowMin; //The current minimum crank angle for a knock pulse to be valid
|
||||
int16_t knockWindowMax;//The current maximum crank angle for a knock pulse to be valid
|
||||
extern uint16_t AFRnextCycle;
|
||||
extern unsigned long knockStartTime;
|
||||
extern byte lastKnockCount;
|
||||
extern int16_t knockWindowMin; //The current minimum crank angle for a knock pulse to be valid
|
||||
extern int16_t knockWindowMax;//The current maximum crank angle for a knock pulse to be valid
|
||||
|
||||
#endif // CORRECTIONS_H
|
||||
|
|
|
@ -23,6 +23,12 @@ Flood clear mode etc.
|
|||
long PID_O2, PID_output, PID_AFRTarget;
|
||||
PID egoPID(&PID_O2, &PID_output, &PID_AFRTarget, configPage6.egoKP, configPage6.egoKI, configPage6.egoKD, REVERSE); //This is the PID object if that algorithm is used. Needs to be global as it maintains state outside of each function call
|
||||
|
||||
uint16_t AFRnextCycle;
|
||||
unsigned long knockStartTime;
|
||||
byte lastKnockCount;
|
||||
int16_t knockWindowMin; //The current minimum crank angle for a knock pulse to be valid
|
||||
int16_t knockWindowMax;//The current maximum crank angle for a knock pulse to be valid
|
||||
|
||||
void initialiseCorrections()
|
||||
{
|
||||
egoPID.SetMode(AUTOMATIC); //Turn O2 PID on
|
||||
|
@ -36,7 +42,7 @@ void initialiseCorrections()
|
|||
correctionsTotal() calls all the other corrections functions and combines their results.
|
||||
This is the only function that should be called from anywhere outside the file
|
||||
*/
|
||||
static inline uint16_t correctionsFuel()
|
||||
uint16_t correctionsFuel()
|
||||
{
|
||||
#define MAX_CORRECTIONS 3 //The maximum number of corrections allowed before the sum is reprocessed
|
||||
uint32_t sumCorrections = 100;
|
||||
|
@ -102,14 +108,13 @@ static inline byte correctionsFuel_new()
|
|||
{
|
||||
uint32_t sumCorrections = 100;
|
||||
byte numCorrections = 0;
|
||||
byte result; //temporary variable to store the result of each corrections function
|
||||
|
||||
//The values returned by each of the correction functions are multipled together and then divided back to give a single 0-255 value.
|
||||
currentStatus.wueCorrection = correctionWUE(); numCorrections++;
|
||||
uint16_t correctionASEvalue = correctionASE(); numCorrections++;
|
||||
uint16_t correctionCrankingValue = correctionCranking(); numCorrections++;
|
||||
currentStatus.AEamount = correctionAccel(); numCorrections++;
|
||||
result = correctionFloodClear(); numCorrections++;
|
||||
uint8_t correctionFloodClearValue = correctionFloodClear(); numCorrections++;
|
||||
currentStatus.egoCorrection = correctionAFRClosedLoop(); numCorrections++;
|
||||
|
||||
currentStatus.batCorrection = correctionBatVoltage(); numCorrections++;
|
||||
|
@ -121,7 +126,17 @@ static inline byte correctionsFuel_new()
|
|||
bitWrite(currentStatus.status1, BIT_STATUS1_DFCO, correctionDFCO());
|
||||
if ( bitRead(currentStatus.status1, BIT_STATUS1_DFCO) == 1 ) { sumCorrections = 0; }
|
||||
|
||||
return ( currentStatus.wueCorrection + correctionASEvalue + correctionCrankingValue);
|
||||
sumCorrections = currentStatus.wueCorrection \
|
||||
+ correctionASEvalue \
|
||||
+ correctionCrankingValue \
|
||||
+ currentStatus.AEamount \
|
||||
+ correctionFloodClearValue \
|
||||
+ currentStatus.batCorrection \
|
||||
+ currentStatus.iatCorrection \
|
||||
+ currentStatus.baroCorrection \
|
||||
+ currentStatus.flexCorrection \
|
||||
+ currentStatus.launchCorrection;
|
||||
return (sumCorrections);
|
||||
|
||||
}
|
||||
|
||||
|
@ -129,7 +144,7 @@ static inline byte correctionsFuel_new()
|
|||
Warm Up Enrichment (WUE)
|
||||
Uses a 2D enrichment table (WUETable) where the X axis is engine temp and the Y axis is the amount of extra fuel to add
|
||||
*/
|
||||
static inline byte correctionWUE()
|
||||
byte correctionWUE()
|
||||
{
|
||||
byte WUEValue;
|
||||
//Possibly reduce the frequency this runs at (Costs about 50 loops per second)
|
||||
|
@ -153,7 +168,7 @@ static inline byte correctionWUE()
|
|||
Cranking Enrichment
|
||||
Additional fuel % to be added when the engine is cranking
|
||||
*/
|
||||
static inline byte correctionCranking()
|
||||
byte correctionCranking()
|
||||
{
|
||||
byte crankingValue = 100;
|
||||
//if ( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) ) { crankingValue = 100 + configPage2.crankingPct; }
|
||||
|
@ -164,12 +179,15 @@ static inline byte correctionCranking()
|
|||
return crankingValue;
|
||||
}
|
||||
|
||||
/*
|
||||
After Start Enrichment
|
||||
This is a short period (Usually <20 seconds) immediately after the engine first fires (But not when cranking)
|
||||
where an additional amount of fuel is added (Over and above the WUE amount)
|
||||
/**
|
||||
* @brief Afer Start Enrichment calculation
|
||||
*
|
||||
* This is a short period (Usually <20 seconds) immediately after the engine first fires (But not when cranking)
|
||||
* where an additional amount of fuel is added (Over and above the WUE amount)
|
||||
*
|
||||
* @return uint8_t The After Start Enrichment modifier as a %. 100% = No modification.
|
||||
*/
|
||||
static inline byte correctionASE()
|
||||
byte correctionASE()
|
||||
{
|
||||
int16_t ASEValue;
|
||||
//Two checks are requiredL:
|
||||
|
@ -202,7 +220,7 @@ static inline byte correctionASE()
|
|||
* @return uint16_t The Acceleration enrichment modifier as a %. 100% = No modification.
|
||||
* As the maximum enrichment amount is +255%, the overall return value from this function can be 100+255=355. Hence this function returns a uint16_t rather than byte
|
||||
*/
|
||||
static inline uint16_t correctionAccel()
|
||||
uint16_t correctionAccel()
|
||||
{
|
||||
int16_t accelValue = 100;
|
||||
//First, check whether the accel. enrichment is already running
|
||||
|
@ -317,8 +335,7 @@ static inline uint16_t correctionAccel()
|
|||
Simple check to see whether we are cranking with the TPS above the flood clear threshold
|
||||
This function always returns either 100 or 0
|
||||
*/
|
||||
|
||||
static inline byte correctionFloodClear()
|
||||
byte correctionFloodClear()
|
||||
{
|
||||
byte floodValue = 100;
|
||||
if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
|
||||
|
@ -337,7 +354,7 @@ static inline byte correctionFloodClear()
|
|||
Battery Voltage correction
|
||||
Uses a 2D enrichment table (WUETable) where the X axis is engine temp and the Y axis is the amount of extra fuel to add
|
||||
*/
|
||||
static inline byte correctionBatVoltage()
|
||||
byte correctionBatVoltage()
|
||||
{
|
||||
byte batValue = 100;
|
||||
if (configPage2.battVCorMode == BATTV_COR_MODE_WHOLE)
|
||||
|
@ -352,7 +369,7 @@ static inline byte correctionBatVoltage()
|
|||
Simple temperature based corrections lookup based on the inlet air temperature.
|
||||
This corrects for changes in air density from movement of the temperature
|
||||
*/
|
||||
static inline byte correctionIATDensity()
|
||||
byte correctionIATDensity()
|
||||
{
|
||||
byte IATValue = 100;
|
||||
IATValue = table2D_getValue(&IATDensityCorrectionTable, currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); //currentStatus.IAT is the actual temperature, values in IATDensityCorrectionTable.axisX are temp+offset
|
||||
|
@ -364,7 +381,7 @@ static inline byte correctionIATDensity()
|
|||
* @brief
|
||||
* @returns A percentage value indicating the amount the fueling should be changed based on the barometric reading. 100 = No change. 110 = 10% increase. 90 = 10% decrease
|
||||
*/
|
||||
static inline byte correctionBaro()
|
||||
byte correctionBaro()
|
||||
{
|
||||
byte baroValue = 100;
|
||||
baroValue = table2D_getValue(&baroFuelTable, currentStatus.baro);
|
||||
|
@ -376,7 +393,7 @@ static inline byte correctionBaro()
|
|||
Launch control has a setting to increase the fuel load to assist in bringing up boost
|
||||
This simple check applies the extra fuel if we're currently launching
|
||||
*/
|
||||
static inline byte correctionLaunch()
|
||||
byte correctionLaunch()
|
||||
{
|
||||
byte launchValue = 100;
|
||||
if(currentStatus.launchingHard || currentStatus.launchingSoft) { launchValue = (100 + configPage6.lnchFuelAdd); }
|
||||
|
@ -387,7 +404,7 @@ static inline byte correctionLaunch()
|
|||
/*
|
||||
* Returns true if decelleration fuel cutoff should be on, false if its off
|
||||
*/
|
||||
static inline bool correctionDFCO()
|
||||
bool correctionDFCO()
|
||||
{
|
||||
bool DFCOValue = false;
|
||||
if ( configPage2.dfcoEnabled == 1 )
|
||||
|
@ -402,7 +419,7 @@ static inline bool correctionDFCO()
|
|||
* Flex fuel adjustment to vary fuel based on ethanol content
|
||||
* The amount of extra fuel required is a linear relationship based on the % of ethanol.
|
||||
*/
|
||||
static inline byte correctionFlex()
|
||||
byte correctionFlex()
|
||||
{
|
||||
byte flexValue = 100;
|
||||
|
||||
|
@ -426,8 +443,7 @@ This continues until either:
|
|||
PID (Best suited to wideband sensors):
|
||||
|
||||
*/
|
||||
|
||||
static inline byte correctionAFRClosedLoop()
|
||||
byte correctionAFRClosedLoop()
|
||||
{
|
||||
byte AFRValue = 100;
|
||||
if( configPage6.egoType > 0 ) //egoType of 0 means no O2 sensor
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
#include <globals.h>
|
||||
#include <corrections.h>
|
||||
#include <unity.h>
|
||||
#include "tests_corrections.h"
|
||||
|
||||
|
||||
void testCorrections()
|
||||
{
|
||||
test_corrections_WUE();
|
||||
/*
|
||||
RUN_TEST(test_corrections_cranking); //Not written yet
|
||||
RUN_TEST(test_corrections_ASE); //Not written yet
|
||||
RUN_TEST(test_corrections_floodclear); //Not written yet
|
||||
RUN_TEST(test_corrections_closedloop); //Not written yet
|
||||
RUN_TEST(test_corrections_flex); //Not written yet
|
||||
RUN_TEST(test_corrections_bat); //Not written yet
|
||||
RUN_TEST(test_corrections_iatdensity); //Not written yet
|
||||
RUN_TEST(test_corrections_baro); //Not written yet
|
||||
RUN_TEST(test_corrections_launch); //Not written yet
|
||||
RUN_TEST(test_corrections_dfco); //Not written yet
|
||||
*/
|
||||
}
|
||||
|
||||
void test_corrections_WUE_active(void)
|
||||
{
|
||||
//Check for WUE being active
|
||||
currentStatus.coolant = 0;
|
||||
correctionWUE();
|
||||
TEST_ASSERT_BIT_HIGH(BIT_ENGINE_WARMUP, currentStatus.engine);
|
||||
}
|
||||
|
||||
void test_corrections_WUE_inactive(void)
|
||||
{
|
||||
//Check for WUE being inactive due to the temp being too high
|
||||
currentStatus.coolant = 200;
|
||||
correctionWUE();
|
||||
TEST_ASSERT_BIT_LOW(BIT_ENGINE_WARMUP, currentStatus.engine);
|
||||
}
|
||||
|
||||
void test_corrections_WUE_inactive_value(void)
|
||||
{
|
||||
//Check for WUE being set to the final row of the WUE curve if the coolant is above the max WUE temp
|
||||
currentStatus.coolant = 200;
|
||||
((uint8_t*)WUETable.axisX)[9] = 100;
|
||||
((uint8_t*)WUETable.values)[9] = 123; //Use a value other than 100 here to ensure we are using the non-default value
|
||||
|
||||
//Force invalidate the cache
|
||||
WUETable.cacheTime = currentStatus.secl - 1;
|
||||
|
||||
TEST_ASSERT_EQUAL(123, correctionWUE() );
|
||||
}
|
||||
|
||||
void test_corrections_WUE_active_value(void)
|
||||
{
|
||||
//Check for WUE being made active and returning a correct interpolated value
|
||||
currentStatus.coolant = 80;
|
||||
//Set some fake values in the table axis. Target value will fall between points 6 and 7
|
||||
((uint8_t*)WUETable.axisX)[0] = 0;
|
||||
((uint8_t*)WUETable.axisX)[1] = 0;
|
||||
((uint8_t*)WUETable.axisX)[2] = 0;
|
||||
((uint8_t*)WUETable.axisX)[3] = 0;
|
||||
((uint8_t*)WUETable.axisX)[4] = 0;
|
||||
((uint8_t*)WUETable.axisX)[5] = 0;
|
||||
((uint8_t*)WUETable.axisX)[6] = 70 + CALIBRATION_TEMPERATURE_OFFSET;
|
||||
((uint8_t*)WUETable.axisX)[7] = 90 + CALIBRATION_TEMPERATURE_OFFSET;
|
||||
((uint8_t*)WUETable.axisX)[8] = 100 + CALIBRATION_TEMPERATURE_OFFSET;
|
||||
((uint8_t*)WUETable.axisX)[9] = 120 + CALIBRATION_TEMPERATURE_OFFSET;
|
||||
|
||||
((uint8_t*)WUETable.values)[6] = 120;
|
||||
((uint8_t*)WUETable.values)[7] = 130;
|
||||
|
||||
//Force invalidate the cache
|
||||
WUETable.cacheTime = currentStatus.secl - 1;
|
||||
|
||||
//Value should be midway between 120 and 130 = 125
|
||||
TEST_ASSERT_EQUAL(125, correctionWUE() );
|
||||
}
|
||||
|
||||
void test_corrections_WUE(void)
|
||||
{
|
||||
RUN_TEST(test_corrections_WUE_active);
|
||||
RUN_TEST(test_corrections_WUE_inactive);
|
||||
RUN_TEST(test_corrections_WUE_active_value);
|
||||
RUN_TEST(test_corrections_WUE_inactive_value);
|
||||
}
|
||||
void test_corrections_cranking(void)
|
||||
{
|
||||
|
||||
}
|
||||
void test_corrections_ASE(void)
|
||||
{
|
||||
|
||||
}
|
||||
void test_corrections_floodclear(void)
|
||||
{
|
||||
|
||||
}
|
||||
void test_corrections_closedloop(void)
|
||||
{
|
||||
|
||||
}
|
||||
void test_corrections_flex(void)
|
||||
{
|
||||
|
||||
}
|
||||
void test_corrections_bat(void)
|
||||
{
|
||||
|
||||
}
|
||||
void test_corrections_iatdensity(void)
|
||||
{
|
||||
|
||||
}
|
||||
void test_corrections_baro(void)
|
||||
{
|
||||
|
||||
}
|
||||
void test_corrections_launch(void)
|
||||
{
|
||||
|
||||
}
|
||||
void test_corrections_dfco(void)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
void testCorrections();
|
||||
void test_corrections_WUE(void);
|
||||
void test_corrections_cranking(void);
|
||||
void test_corrections_ASE(void);
|
||||
void test_corrections_floodclear(void);
|
||||
void test_corrections_closedloop(void);
|
||||
void test_corrections_flex(void);
|
||||
void test_corrections_bat(void);
|
||||
void test_corrections_iatdensity(void);
|
||||
void test_corrections_baro(void);
|
||||
void test_corrections_launch(void);
|
||||
void test_corrections_dfco(void);
|
|
@ -18,7 +18,7 @@ void test_initialisation_complete(void)
|
|||
|
||||
void test_initialisation_ports(void)
|
||||
{
|
||||
initialiseAll(); //Run the main initialise function
|
||||
//initialiseAll(); //Run the main initialise function
|
||||
TEST_ASSERT_NOT_EQUAL(0, inj1_pin_port);
|
||||
TEST_ASSERT_NOT_EQUAL(0, inj2_pin_port);
|
||||
TEST_ASSERT_NOT_EQUAL(0, inj3_pin_port);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
|
||||
#include "tests_corrections.h"
|
||||
#include "tests_init.h"
|
||||
#include <unity.h>
|
||||
|
||||
|
@ -21,6 +21,7 @@ uint8_t max_blinks = 5;
|
|||
void loop()
|
||||
{
|
||||
testInitialisation();
|
||||
testCorrections();
|
||||
|
||||
UNITY_END(); // stop unit testing
|
||||
}
|
Loading…
Reference in New Issue