Initial complete closed loop boost control. NOT TESTED!

Only works with kpa in TunerStudio.
This commit is contained in:
Josh Stewart 2016-05-22 20:12:44 +10:00
parent aeee880f6a
commit 6c5722c595
6 changed files with 30 additions and 11 deletions

View File

@ -3,7 +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
integerPID boostPID(&currentStatus.MAP, &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
@ -36,18 +36,22 @@ void initialiseAuxPWM()
boost_pwm_max_count = 1000000L / (16 * configPage3.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte)
vvt_pwm_max_count = 1000000L / (16 * configPage3.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle
TIMSK1 |= (1 << OCIE1A); //Turn on the A compare unit (ie turn on the interrupt)
//TIMSK1 |= (1 << OCIE1A); //Turn on the A compare unit (ie turn on the interrupt) //Shouldn't be needed with closed loop as its turned on below
TIMSK1 |= (1 << OCIE1B); //Turn on the B compare unit (ie turn on the interrupt)
boostPID.SetOutputLimits(0, boost_pwm_max_count);
boostPID.SetMode(AUTOMATIC); //Turn PID on
}
void boostControl()
{
if(configPage3.boostEnabled)
{
byte boostDuty = get3DTableValue(&boostTable, currentStatus.TPS, currentStatus.RPM);
if( boostDuty == 0 ) { TIMSK1 &= ~(1 << OCIE1A); digitalWrite(pinBoost, LOW); return; }
if(currentStatus.MAP < 100) { TIMSK1 &= ~(1 << OCIE1A); digitalWrite(pinBoost, LOW); return; } //Set duty to 0 and turn off timer compare
boost_cl_target_boost = get3DTableValue(&boostTable, currentStatus.TPS, currentStatus.RPM) * 2; //Boost target table is in kpa and divided by 2
boostPID.SetTunings(configPage3.boostKP, configPage3.boostKI, configPage3.boostKD);
boostPID.Compute();
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__)
else { TIMSK1 &= ~(1 << OCIE1A); } // Disable timer channel

View File

@ -88,7 +88,7 @@ struct statuses {
unsigned int RPM;
long longRPM;
int mapADC;
int MAP;
unsigned int MAP;
byte TPS; //The current TPS reading (0% - 100%)
byte TPSlast; //The previous TPS reading
unsigned long TPS_time; //The time the TPS sample was taken

View File

@ -12,7 +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
*/
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
integerPID idlePID(&currentStatus.RPM, &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()
{

View File

@ -203,12 +203,12 @@ int PID::GetDirection(){ return controllerDirection;}
* The parameters specified here are those for for which we can't set up
* reliable defaults, so we need to have the user set them.
***************************************************************************/
integerPID::integerPID(long* Input, long* Output, long* Setpoint,
integerPID::integerPID(unsigned int* Input, long* Output, long* Setpoint,
byte Kp, byte Ki, byte Kd, byte ControllerDirection)
{
myOutput = Output;
myInput = Input;
myInput = (long*)Input;
mySetpoint = Setpoint;
inAuto = false;

View File

@ -90,7 +90,7 @@ class integerPID
#define REVERSE 1
//commonly used functions **************************************************************************
integerPID(long*, long*, long*, // * constructor. links the PID to the Input, Output, and
integerPID(unsigned int*, long*, long*, // * constructor. links the PID to the Input, Output, and
byte, byte, byte, byte); // Setpoint. Initial tuning parameters are also set here
void SetMode(int Mode); // * sets PID to either Manual (0) or Auto (non-0)

View File

@ -9,6 +9,17 @@
;-------------------------------------------------------------------------------
[SettingGroups]
; the referenceName will over-ride previous, so if you are creating a
; settingGroup with a reference name of lambdaSensor, it will replace the
; setting group defined in the settingGroups.xml of the TunerStudio config
; folder. If is is an undefined referenceName, it will be added.
; keyword = referenceName, DisplayName
settingGroup = boostUnits, "Boost table units"
settingOption = BOOSTKPA, "kPa"
settingOption = BOOSTPSI, "PSI"
[Constants]
;----------------------------------------------------------------------------
@ -408,7 +419,11 @@ page = 7
;Boost and vvt maps (Page 8)
;--------------------------------------------------
page = 8
boostTable = array, U08, 0,[8x8], "%", 1.0, 0.0, 0, 100, 0
#if BOOSTKPA
boostTable = array, U08, 0,[8x8], "kPa", 2.0, 0.0, 0, 511, 0
#else
boostTable = array, U08, 0,[8x8], "PSI", 0.29062745098039, 0.0, 0, 74, 1 #0.043511 0.02900754754 0.05801509508
#endif
rpmBinsBoost = array, U08, 64,[ 8], "RPM", 100.0, 0.0, 100, 25500, 0
tpsBinsBoost = array, U08, 72,[ 8], "TPS", 1.0, 0.0, 0.0, 255.0, 0
vvtTable = array, U08, 80,[8x8], "%", 1.0, 0.0, 0, 100, 0