Initial work on closed loop boost
This commit is contained in:
parent
366f75c38b
commit
c10da12683
|
@ -8,10 +8,12 @@ volatile byte vvt_pin_mask;
|
||||||
volatile bool boost_pwm_state;
|
volatile bool boost_pwm_state;
|
||||||
unsigned int boost_pwm_max_count; //Used for variable PWM frequency
|
unsigned int boost_pwm_max_count; //Used for variable PWM frequency
|
||||||
volatile unsigned int boost_pwm_cur_value;
|
volatile unsigned int boost_pwm_cur_value;
|
||||||
unsigned int boost_pwm_target_value;
|
long boost_pwm_target_value;
|
||||||
|
long boost_cl_target_boost;
|
||||||
|
|
||||||
volatile bool vvt_pwm_state;
|
volatile bool vvt_pwm_state;
|
||||||
unsigned int vvt_pwm_max_count; //Used for variable PWM frequency
|
unsigned int vvt_pwm_max_count; //Used for variable PWM frequency
|
||||||
volatile unsigned int vvt_pwm_cur_value;
|
volatile unsigned int vvt_pwm_cur_value;
|
||||||
unsigned int vvt_pwm_target_value;
|
long vvt_pwm_target_value;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ Speeduino - Simple engine management for the Arduino Mega 2560 platform
|
||||||
Copyright (C) Josh Stewart
|
Copyright (C) Josh Stewart
|
||||||
A full copy of the license may be found in the projects root directory
|
A full copy of the license may be found in the projects root directory
|
||||||
*/
|
*/
|
||||||
|
integerPID boostPID(¤tStatus.longRPM, &boost_pwm_target_value, &boost_cl_target_boost, configPage3.boostKP, configPage3.boostKI, configPage3.boostKD, DIRECT); //This is the PID object if that algorithm is used. Needs to be global as it maintains state outside of each function call
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Fan control
|
Fan control
|
||||||
|
@ -44,6 +45,8 @@ void boostControl()
|
||||||
if(configPage3.boostEnabled)
|
if(configPage3.boostEnabled)
|
||||||
{
|
{
|
||||||
byte boostDuty = get3DTableValue(&boostTable, currentStatus.TPS, currentStatus.RPM);
|
byte boostDuty = get3DTableValue(&boostTable, currentStatus.TPS, currentStatus.RPM);
|
||||||
|
if( boostDuty == 0 ) { TIMSK1 &= ~(1 << OCIE1A); digitalWrite(pinBoost, LOW); return; }
|
||||||
|
TIMSK1 |= (1 << OCIE1A); //Turn on the compare unit (ie turn on the interrupt)
|
||||||
boost_pwm_target_value = percentage(boostDuty, boost_pwm_max_count);
|
boost_pwm_target_value = percentage(boostDuty, boost_pwm_max_count);
|
||||||
}
|
}
|
||||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
|
|
@ -86,6 +86,7 @@ volatile byte ign4_pin_mask;
|
||||||
struct statuses {
|
struct statuses {
|
||||||
volatile boolean hasSync;
|
volatile boolean hasSync;
|
||||||
unsigned int RPM;
|
unsigned int RPM;
|
||||||
|
long longRPM;
|
||||||
int mapADC;
|
int mapADC;
|
||||||
int MAP;
|
int MAP;
|
||||||
byte TPS; //The current TPS reading (0% - 100%)
|
byte TPS; //The current TPS reading (0% - 100%)
|
||||||
|
@ -328,9 +329,9 @@ struct config3 {
|
||||||
byte idleKD;
|
byte idleKD;
|
||||||
|
|
||||||
byte boostLimit; //Is divided by 2, allowing kPa values up to 511
|
byte boostLimit; //Is divided by 2, allowing kPa values up to 511
|
||||||
byte unused57;
|
byte boostKP;
|
||||||
byte unused58;
|
byte boostKI;
|
||||||
byte unused59;
|
byte boostKD;
|
||||||
byte unused60;
|
byte unused60;
|
||||||
byte unused61;
|
byte unused61;
|
||||||
byte unused62;
|
byte unused62;
|
||||||
|
|
4
idle.ino
4
idle.ino
|
@ -12,8 +12,7 @@ These functions cover the PWM and stepper idle control
|
||||||
Idle Control
|
Idle Control
|
||||||
Currently limited to on/off control and open loop PWM and stepper drive
|
Currently limited to on/off control and open loop PWM and stepper drive
|
||||||
*/
|
*/
|
||||||
long longRPM;
|
integerPID idlePID(¤tStatus.longRPM, &idle_pwm_target_value, &idle_cl_target_rpm, configPage3.idleKP, configPage3.idleKI, configPage3.idleKD, DIRECT); //This is the PID object if that algorithm is used. Needs to be global as it maintains state outside of each function call
|
||||||
integerPID idlePID(&longRPM, &idle_pwm_target_value, &idle_cl_target_rpm, configPage3.idleKP, configPage3.idleKI, configPage3.idleKD, DIRECT); //This is the PID object if that algorithm is used. Needs to be global as it maintains state outside of each function call
|
|
||||||
|
|
||||||
void initialiseIdle()
|
void initialiseIdle()
|
||||||
{
|
{
|
||||||
|
@ -151,7 +150,6 @@ void idleControl()
|
||||||
case 3: //Case 3 is PWM closed loop
|
case 3: //Case 3 is PWM closed loop
|
||||||
//No cranking specific value for closed loop (yet?)
|
//No cranking specific value for closed loop (yet?)
|
||||||
idle_cl_target_rpm = table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) * 10; //All temps are offset by 40 degrees
|
idle_cl_target_rpm = table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) * 10; //All temps are offset by 40 degrees
|
||||||
longRPM = currentStatus.RPM; //The PID object needs a long as the RPM input. A separate variable is used for this
|
|
||||||
idlePID.SetTunings(configPage3.idleKP, configPage3.idleKI, configPage3.idleKD);
|
idlePID.SetTunings(configPage3.idleKP, configPage3.idleKI, configPage3.idleKD);
|
||||||
|
|
||||||
idlePID.Compute();
|
idlePID.Compute();
|
||||||
|
|
|
@ -340,9 +340,9 @@ page = 6
|
||||||
idleKI = scalar, U08, 54, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
|
idleKI = scalar, U08, 54, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
|
||||||
idleKD = scalar, U08, 55, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
|
idleKD = scalar, U08, 55, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
|
||||||
boostLimit = scalar, U08, 56, "kPa", 2.0, 0.0, 0, 511, 0
|
boostLimit = scalar, U08, 56, "kPa", 2.0, 0.0, 0, 511, 0
|
||||||
unused6-57 = scalar, U08, 57, "RPM", 100.0, 0.0, 100, 25500, 0
|
boostKP = scalar, U08, 57, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
|
||||||
unused6-58 = scalar, U08, 58, "RPM", 100.0, 0.0, 100, 25500, 0
|
boostKI = scalar, U08, 58, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
|
||||||
unused6-59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0
|
boostKD = scalar, U08, 59, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
|
||||||
unused6-60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0
|
unused6-60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0
|
||||||
unused6-61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0
|
unused6-61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0
|
||||||
unused6-62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0
|
unused6-62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0
|
||||||
|
@ -815,6 +815,10 @@ page = 8
|
||||||
field = "Boost solenoid freq.", boostFreq
|
field = "Boost solenoid freq.", boostFreq
|
||||||
field = "Boost Cut", boostCutType
|
field = "Boost Cut", boostCutType
|
||||||
field = "Boost Limit", boostLimit, { boostCutType }
|
field = "Boost Limit", boostLimit, { boostCutType }
|
||||||
|
field = "Closed Loop settings"
|
||||||
|
field = "P", boostKP
|
||||||
|
field = "I", boostKI
|
||||||
|
field = "D", boostKD
|
||||||
|
|
||||||
dialog = vvtSettings, "VVT Control"
|
dialog = vvtSettings, "VVT Control"
|
||||||
field = "VVT Control Enabled", vvtEnabled
|
field = "VVT Control Enabled", vvtEnabled
|
||||||
|
|
|
@ -635,7 +635,7 @@ void loop()
|
||||||
if ( (timeToLastTooth < MAX_STALL_TIME) || (toothLastToothTime > currentLoopTime) ) //Check how long ago the last tooth was seen compared to now. If it was more than half a second ago then the engine is probably stopped. toothLastToothTime can be greater than currentLoopTime if a pulse occurs between getting the lastest time and doing the comparison
|
if ( (timeToLastTooth < MAX_STALL_TIME) || (toothLastToothTime > currentLoopTime) ) //Check how long ago the last tooth was seen compared to now. If it was more than half a second ago then the engine is probably stopped. toothLastToothTime can be greater than currentLoopTime if a pulse occurs between getting the lastest time and doing the comparison
|
||||||
{
|
{
|
||||||
int lastRPM = currentStatus.RPM; //Need to record this for rpmDOT calculation
|
int lastRPM = currentStatus.RPM; //Need to record this for rpmDOT calculation
|
||||||
currentStatus.RPM = getRPM();
|
currentStatus.RPM = currentStatus.longRPM = getRPM(); //Long RPM is included here
|
||||||
if(fuelPumpOn == false) { digitalWrite(pinFuelPump, HIGH); fuelPumpOn = true; } //Check if the fuel pump is on and turn it on if it isn't.
|
if(fuelPumpOn == false) { digitalWrite(pinFuelPump, HIGH); fuelPumpOn = true; } //Check if the fuel pump is on and turn it on if it isn't.
|
||||||
currentStatus.rpmDOT = ldiv(1000000, (currentLoopTime - previousLoopTime)).quot * (currentStatus.RPM - lastRPM); //This is the RPM per second that the engine has accelerated/decelleratedin the last loop
|
currentStatus.rpmDOT = ldiv(1000000, (currentLoopTime - previousLoopTime)).quot * (currentStatus.RPM - lastRPM); //This is the RPM per second that the engine has accelerated/decelleratedin the last loop
|
||||||
}
|
}
|
||||||
|
@ -656,6 +656,7 @@ void loop()
|
||||||
fuelOn = false;
|
fuelOn = false;
|
||||||
if (fpPrimed) { digitalWrite(pinFuelPump, LOW); } //Turn off the fuel pump, but only if the priming is complete
|
if (fpPrimed) { digitalWrite(pinFuelPump, LOW); } //Turn off the fuel pump, but only if the priming is complete
|
||||||
fuelPumpOn = false;
|
fuelPumpOn = false;
|
||||||
|
TIMSK4 &= ~(1 << OCIE4C); digitalWrite(pinIdle1, LOW); //Turns off the idle control PWM. This REALLY needs to be cleaned up into a general PWM controller class
|
||||||
}
|
}
|
||||||
|
|
||||||
//Uncomment the following for testing
|
//Uncomment the following for testing
|
||||||
|
|
Loading…
Reference in New Issue