Initial work on closed loop boost

This commit is contained in:
Josh Stewart 2016-05-15 21:05:49 +10:00
parent 366f75c38b
commit c10da12683
6 changed files with 21 additions and 12 deletions

View File

@ -8,10 +8,12 @@ volatile byte vvt_pin_mask;
volatile bool boost_pwm_state;
unsigned int boost_pwm_max_count; //Used for variable PWM frequency
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;
unsigned int vvt_pwm_max_count; //Used for variable PWM frequency
volatile unsigned int vvt_pwm_cur_value;
unsigned int vvt_pwm_target_value;
long vvt_pwm_target_value;

View File

@ -3,6 +3,7 @@ Speeduino - Simple engine management for the Arduino Mega 2560 platform
Copyright (C) Josh Stewart
A full copy of the license may be found in the projects root directory
*/
integerPID boostPID(&currentStatus.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
@ -44,6 +45,8 @@ void boostControl()
if(configPage3.boostEnabled)
{
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);
}
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

View File

@ -86,6 +86,7 @@ volatile byte ign4_pin_mask;
struct statuses {
volatile boolean hasSync;
unsigned int RPM;
long longRPM;
int mapADC;
int MAP;
byte TPS; //The current TPS reading (0% - 100%)
@ -328,9 +329,9 @@ struct config3 {
byte idleKD;
byte boostLimit; //Is divided by 2, allowing kPa values up to 511
byte unused57;
byte unused58;
byte unused59;
byte boostKP;
byte boostKI;
byte boostKD;
byte unused60;
byte unused61;
byte unused62;

View File

@ -12,8 +12,7 @@ These functions cover the PWM and stepper idle control
Idle Control
Currently limited to on/off control and open loop PWM and stepper drive
*/
long longRPM;
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
integerPID idlePID(&currentStatus.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()
{
@ -151,7 +150,6 @@ void idleControl()
case 3: //Case 3 is PWM closed loop
//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
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.Compute();

View File

@ -340,9 +340,9 @@ page = 6
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)
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
unused6-58 = scalar, U08, 58, "RPM", 100.0, 0.0, 100, 25500, 0
unused6-59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0
boostKP = scalar, U08, 57, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
boostKI = scalar, U08, 58, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
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-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
@ -815,6 +815,10 @@ page = 8
field = "Boost solenoid freq.", boostFreq
field = "Boost Cut", boostCutType
field = "Boost Limit", boostLimit, { boostCutType }
field = "Closed Loop settings"
field = "P", boostKP
field = "I", boostKI
field = "D", boostKD
dialog = vvtSettings, "VVT Control"
field = "VVT Control Enabled", vvtEnabled

View File

@ -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
{
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.
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;
if (fpPrimed) { digitalWrite(pinFuelPump, LOW); } //Turn off the fuel pump, but only if the priming is complete
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