Add duty cycle limit option

This commit is contained in:
Josh Stewart 2015-06-12 13:18:36 +10:00
parent c8a7684d5a
commit dd08d52db2
5 changed files with 107 additions and 74 deletions

View File

@ -13,3 +13,4 @@ volatile int toothHistoryIndex = 0;
volatile int triggerActualTeeth;
unsigned int triggerFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering)
unsigned int triggerToothAngle; //The number of crank degrees that elapse per tooth
unsigned long revolutionTime; //The time in uS that one revolution would take at current speed (The time tooth 1 was last seen, minus the time it was seen prior to that)

View File

@ -148,7 +148,7 @@ struct config1 {
byte injTiming : 2;
byte primePulse;
byte unused40;
byte dutyLim;
byte unused41;
byte egoSwitch;
byte taeColdM;

19
math.h
View File

@ -60,4 +60,23 @@ int divs100(int n) {
// return q + (r > 99);
}
//Unsigned divide by 100
unsigned int divu100(unsigned n) {
unsigned q, r;
q = (n >> 1) + (n >> 3) + (n >> 6) - (n >> 10) +
(n >> 12) + (n >> 13) - (n >> 16);
q = q + (q >> 20);
q = q >> 6;
r = n - q*100;
return q + ((r + 28) >> 7);
// return q + (r > 99);
}
//Return x percent of y
//This is a relatively fast approximation of a percentage value.
unsigned int percentage(byte x, unsigned int y)
{
return divu100(y) * x;
}
#endif // MATH_H

View File

@ -148,7 +148,7 @@ page = 2
injTiming = bits, U08, 38, [4:5], "Bank", "Semi-Sequential", "INVALID", "INVALID"
primePulse = scalar, U08, 39, "ms", 0.1, 0.0, 0.0, 25.5, 1
unused40 = scalar, U08, 40, "RPM", 100.0, 0.0, 100, 25500, 0
dutyLim = scalar, U08, 40, "%", 1.0, 0.0, 0.0, 100.0, 0
unused41 = scalar, U08, 41, "RPM", 100.0, 0.0, 100, 25500, 0
egoSwitch = scalar, U08, 42, "v", 0.0196, 0.0, 0.0, 5.0, 3
taeColdM = scalar, U08, 43, "%", 1.0, 0.0, 0.0, 250.0, 0
@ -366,6 +366,7 @@ page = 7
defaultValue = inj2Ang, 355
defaultValue = inj3Ang, 355
defaultValue = inj4Ang, 355
defaultValue = dutyLim, 100
[Menu]
@ -503,6 +504,7 @@ page = 7
field = "Channel 2", inj2Ang, { nCylinders > 1 }
field = "Channel 3", inj3Ang, { nCylinders > 4 || nCylinders == 3 }
field = "Channel 4", inj4Ang, { nCylinders > 6 }
field = "Injector Duty Limit", dutyLim
panel = injector_voltage_curve
dialog = egoControl, ""

View File

@ -53,7 +53,8 @@ int req_fuel_uS, inj_opentime_uS;
#define MAX_RPM 10000 //This is the maximum rpm that the ECU will attempt to run at. It is NOT related to the rev limiter, but is instead dictates how fast certain operations will be allowed to run. Lower number gives better performance
volatile byte startRevolutions = 0; //A counter for how many revolutions have been completed since sync was achieved.
volatile bool ignitionOn = true; //The current state of the ignition system
bool ignitionOn = false; //The current state of the ignition system
bool fuelOn = false; //The current state of the ignition system
void (*trigger)(); //Pointer for the trigger function (Gets pointed to the relevant decoder)
void (*triggerSecondary)(); //Pointer for the secondary trigger function (Gets pointed to the relevant decoder)
@ -320,6 +321,9 @@ void loop()
currentStatus.hasSync = false;
currentStatus.runSecs = 0; //Reset the counter for number of seconds running.
secCounter = 0; //Reset our seconds counter.
startRevolutions = 0;
ignitionOn = false;
fuelOn = false;
digitalWrite(pinFuelPump, LOW); //Turn off the fuel pump
}
@ -369,6 +373,7 @@ void loop()
{ //Sets the engine running bit, clears the engine cranking bit
BIT_SET(currentStatus.engine, BIT_ENGINE_RUN);
BIT_CLEAR(currentStatus.engine, BIT_ENGINE_CRANK);
if(startRevolutions > configPage2.StgCycles) { ignitionOn = true; fuelOn = true;}
}
else
{ //Sets the engine cranking bit, clears the engine running bit
@ -376,8 +381,7 @@ void loop()
BIT_CLEAR(currentStatus.engine, BIT_ENGINE_RUN);
currentStatus.runSecs = 0; //We're cranking (hopefully), so reset the engine run time to prompt ASE.
//Check whether enough cranking revolutions have been performed to turn the ignition on
if(startRevolutions > configPage2.StgCycles)
{ignitionOn = true;}
if(startRevolutions > configPage2.StgCycles) { ignitionOn = true; fuelOn = true;}
}
//END SETTING STATUSES
@ -424,6 +428,10 @@ void loop()
//How fast are we going? Need to know how long (uS) it will take to get from one tooth to the next. We then use that to estimate how far we are between the last tooth and the next one
timePerDegree = ldiv( 166666L, currentStatus.RPM ).quot; //There is a small amount of rounding in this calculation, however it is less than 0.001 of a uS (Faster as ldiv than / )
//Check that the duty cycle of the chosen pulsewidth isn't too high
unsigned int pwLimit = percentage(configPage1.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
if (currentStatus.PW > pwLimit) { currentStatus.PW = pwLimit; }
//***********************************************************************************************
//BEGIN INJECTION TIMING
//Determine next firing angles
@ -542,86 +550,89 @@ void loop()
//Determine the current crank angle
int crankAngle = getCrankAngle(timePerDegree);
if (injector1StartAngle > crankAngle)
{
if (configPage1.injTiming == 1)
{
setFuelSchedule1(openInjector1and4,
((unsigned long)(injector1StartAngle - crankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector1and4
);
if (fuelOn)
{
if (injector1StartAngle > crankAngle)
{
if (configPage1.injTiming == 1)
{
setFuelSchedule1(openInjector1and4,
((unsigned long)(injector1StartAngle - crankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector1and4
);
}
else
{
setFuelSchedule1(openInjector1,
((unsigned long)(injector1StartAngle - crankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector1
);
}
}
else
{
setFuelSchedule1(openInjector1,
((unsigned long)(injector1StartAngle - crankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector1
);
/*-----------------------------------------------------------------------------------------
| A Note on tempCrankAngle and tempStartAngle:
| The use of tempCrankAngle/tempStartAngle is described below. It is then used in the same way for channels 2, 3 and 4 on both injectors and ignition
| Essentially, these 2 variables are used to realign the current crank and and the desired start angle around 0 degrees for the given cylinder/output
| Eg: If cylinder 2 TDC is 180 degrees after cylinder 1 (Eg a standard 4 cylidner engine), then tempCrankAngle is 180* less than the current crank angle and
| tempStartAngle is the desired open time less 180*. Thus the cylinder is being treated relative to its own TDC, regardless of its offset
|
| This is done to avoid problems with very short of very long times until tempStartAngle.
| This will very likely need to be rewritten when sequential is enabled
|------------------------------------------------------------------------------------------
*/
tempCrankAngle = crankAngle - channel2Degrees;
if( tempCrankAngle < 0) { tempCrankAngle += 360; }
tempStartAngle = injector2StartAngle - channel2Degrees;
if ( tempStartAngle < 0) { tempStartAngle += 360; }
if (tempStartAngle > tempCrankAngle)
{
if (configPage1.injTiming == 1)
{
setFuelSchedule2(openInjector2and3,
((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector2and3
);
}
else
{
setFuelSchedule2(openInjector2,
((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector2
);
}
}
}
/*-----------------------------------------------------------------------------------------
| A Note on tempCrankAngle and tempStartAngle:
| The use of tempCrankAngle/tempStartAngle is described below. It is then used in the same way for channels 2, 3 and 4 on both injectors and ignition
| Essentially, these 2 variables are used to realign the current crank and and the desired start angle around 0 degrees for the given cylinder/output
| Eg: If cylinder 2 TDC is 180 degrees after cylinder 1 (Eg a standard 4 cylidner engine), then tempCrankAngle is 180* less than the current crank angle and
| tempStartAngle is the desired open time less 180*. Thus the cylinder is being treated relative to its own TDC, regardless of its offset
|
| This is done to avoid problems with very short of very long times until tempStartAngle.
| This will very likely need to be rewritten when sequential is enabled
|------------------------------------------------------------------------------------------
*/
tempCrankAngle = crankAngle - channel2Degrees;
if( tempCrankAngle < 0) { tempCrankAngle += 360; }
tempStartAngle = injector2StartAngle - channel2Degrees;
if ( tempStartAngle < 0) { tempStartAngle += 360; }
if (tempStartAngle > tempCrankAngle)
{
if (configPage1.injTiming == 1)
{
setFuelSchedule2(openInjector2and3,
tempCrankAngle = crankAngle - channel3Degrees;
if( tempCrankAngle < 0) { tempCrankAngle += 360; }
tempStartAngle = injector3StartAngle - channel3Degrees;
if ( tempStartAngle < 0) { tempStartAngle += 360; }
if (tempStartAngle > tempCrankAngle)
{
setFuelSchedule3(openInjector3,
((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector2and3
closeInjector3
);
}
else
{
setFuelSchedule2(openInjector2,
tempCrankAngle = crankAngle - channel4Degrees;
if( tempCrankAngle < 0) { tempCrankAngle += 360; }
tempStartAngle = injector4StartAngle - channel4Degrees;
if ( tempStartAngle < 0) { tempStartAngle += 360; }
if (tempStartAngle > tempCrankAngle)
{
setFuelSchedule4(openInjector4,
((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector2
closeInjector4
);
}
}
tempCrankAngle = crankAngle - channel3Degrees;
if( tempCrankAngle < 0) { tempCrankAngle += 360; }
tempStartAngle = injector3StartAngle - channel3Degrees;
if ( tempStartAngle < 0) { tempStartAngle += 360; }
if (tempStartAngle > tempCrankAngle)
{
setFuelSchedule3(openInjector3,
((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector3
);
}
tempCrankAngle = crankAngle - channel4Degrees;
if( tempCrankAngle < 0) { tempCrankAngle += 360; }
tempStartAngle = injector4StartAngle - channel4Degrees;
if ( tempStartAngle < 0) { tempStartAngle += 360; }
if (tempStartAngle > tempCrankAngle)
{
setFuelSchedule4(openInjector4,
((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree),
(unsigned long)currentStatus.PW,
closeInjector4
);
}
//***********************************************************************************************
//| BEGIN IGNITION SCHEDULES
//Likewise for the ignition