diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 38e005eb..b84438f4 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -576,9 +576,9 @@ page = 6 lnchHardLim = scalar, U08, 51, "rpm", 100, 0.0, 100, 25500, 0 lnchFuelAdd = scalar, U08, 52, "%", 1.0, 0.0, 0.0, 80, 0 - idleKP = scalar, U08, 53, "%", 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) + idleKP = scalar, U08, 53, "%", 0.03125, 0.0, 0.0, 7.96, 2 ; * ( 1 byte) + idleKI = scalar, U08, 54, "%", 0.03125, 0.0, 0.0, 7.96, 2 ; * ( 1 byte) + idleKD = scalar, U08, 55, "%", 0.00781, 0.0, 0.0, 1.99, 3 ; * ( 1 byte) boostLimit = scalar, U08, 56, "kPa", 2.0, 0.0, 0.0, 511.0, 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) @@ -1019,9 +1019,9 @@ page = 10 ;All related to the closed loop VVT control vvtCLholdDuty = scalar, U08, 126, "%", 1.0, 0.0, 0.0, 100.0, 0 - vvtCLKP = scalar, U08, 127, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte) - vvtCLKI = scalar, U08, 128, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte) - vvtCLKD = scalar, U08, 129, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte) + vvtCLKP = scalar, U08, 127, "%", 0.03125, 0.0, 0.0, 7.96, 2 ; * ( 1 byte) + vvtCLKI = scalar, U08, 128, "%", 0.03125, 0.0, 0.0, 7.96, 2 ; * ( 1 byte) + vvtCLKD = scalar, U08, 129, "%", 0.00781, 0.0, 0.0, 1.99, 3 ; * ( 1 byte) vvtCLMinAng = scalar, U16, 130, "deg", 1.0, 0.0, 0.0, 360.0, 0 ; * ( 1 bytes) vvtCLMaxAng = scalar, U16, 132, "deg", 1.0, 0.0, 0.0, 360.0, 0 ; * ( 1 bytes) @@ -1367,7 +1367,7 @@ menuDialog = main subMenu = idleSettings, "Idle Control" subMenu = iacClosedLoop_curve, "Idle - RPM targets", 7, { iacAlgorithm == 3 || iacAlgorithm == 5 || idleAdvEnabled >= 1 } subMenu = iacPwm_curve, "Idle - PWM Duty Cycle", 7, { iacAlgorithm == 2 } - subMenu = iacPwmCrank_curve, "Idle - PWM Cranking Duty Cycle", 7, { iacAlgorithm == 2 } + subMenu = iacPwmCrank_curve, "Idle - PWM Cranking Duty Cycle", 7, { iacAlgorithm == 2 || iacAlgorithm == 3 } subMenu = iacStep_curve, "Idle - Stepper Motor", 7, { iacAlgorithm == 4 } subMenu = iacStepCrank_curve, "Idle - Stepper Motor Cranking", 7, { iacAlgorithm == 4 || iacAlgorithm == 5 } subMenu = std_separator diff --git a/speeduino/TS_CommandButtonHandler.ino b/speeduino/TS_CommandButtonHandler.ino index 191cfae6..48db7455 100644 --- a/speeduino/TS_CommandButtonHandler.ino +++ b/speeduino/TS_CommandButtonHandler.ino @@ -110,79 +110,55 @@ uint16_t TS_CommandButtonsHandler(int buttonCommand) break; case TS_CMD_INJ5_ON: // cmd group is for injector5 on actions - #if INJ_CHANNELS >= 5 - if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector5(); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector5(); } break; case TS_CMD_INJ5_OFF: // cmd group is for injector5 off actions - #if INJ_CHANNELS >= 5 - if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector5(); BIT_CLEAR(HWTest_INJ_50pc, 5); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector5(); BIT_CLEAR(HWTest_INJ_50pc, 5); } break; case TS_CMD_INJ5_50PC: // cmd group is for injector5 50%dc actions - #if INJ_CHANNELS >= 5 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 5); } - if(!BIT_CHECK(HWTest_INJ_50pc, 5)) { closeInjector5(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 5); } + if(!BIT_CHECK(HWTest_INJ_50pc, 5)) { closeInjector5(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) break; case TS_CMD_INJ6_ON: // cmd group is for injector6 on actions - #if INJ_CHANNELS >= 6 - if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector6(); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector6(); } break; case TS_CMD_INJ6_OFF: // cmd group is for injector6 off actions - #if INJ_CHANNELS >= 6 - if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector6(); BIT_CLEAR(HWTest_INJ_50pc, 6); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector6(); BIT_CLEAR(HWTest_INJ_50pc, 6); } break; case TS_CMD_INJ6_50PC: // cmd group is for injector6 50% dc actions - #if INJ_CHANNELS >= 6 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 6); } - if(!BIT_CHECK(HWTest_INJ_50pc, 6)) { closeInjector6(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 6); } + if(!BIT_CHECK(HWTest_INJ_50pc, 6)) { closeInjector6(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) break; case TS_CMD_INJ7_ON: // cmd group is for injector7 on actions - #if INJ_CHANNELS >= 7 - if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector7(); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector7(); } break; case TS_CMD_INJ7_OFF: // cmd group is for injector7 off actions - #if INJ_CHANNELS >= 7 - if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector7(); BIT_CLEAR(HWTest_INJ_50pc, 7); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector7(); BIT_CLEAR(HWTest_INJ_50pc, 7); } break; case TS_CMD_INJ7_50PC: // cmd group is for injector7 50%dc actions - #if INJ_CHANNELS >= 7 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 7); } - if(!BIT_CHECK(HWTest_INJ_50pc, 7)) { closeInjector7(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 7); } + if(!BIT_CHECK(HWTest_INJ_50pc, 7)) { closeInjector7(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) break; case TS_CMD_INJ8_ON: // cmd group is for injector8 on actions - #if INJ_CHANNELS >= 8 - if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector8(); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector8(); } break; case TS_CMD_INJ8_OFF: // cmd group is for injector8 off actions - #if INJ_CHANNELS >= 8 - if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector8(); BIT_CLEAR(HWTest_INJ_50pc, 8); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector8(); BIT_CLEAR(HWTest_INJ_50pc, 8); } break; case TS_CMD_INJ8_50PC: // cmd group is for injector8 50% dc actions - #if INJ_CHANNELS >= 8 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 8); } - if(!BIT_CHECK(HWTest_INJ_50pc, 8)) { closeInjector8(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 8); } + if(!BIT_CHECK(HWTest_INJ_50pc, 8)) { closeInjector8(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) break; case TS_CMD_IGN1_ON: // cmd group is for spark1 on actions @@ -238,79 +214,55 @@ uint16_t TS_CommandButtonsHandler(int buttonCommand) break; case TS_CMD_IGN5_ON: // cmd group is for spark5 on actions - #if IGN_CHANNELS >= 5 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil5Charge(); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil5Charge(); } break; case TS_CMD_IGN5_OFF: // cmd group is for spark5 off actions - #if IGN_CHANNELS >= 5 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil5Charge(); BIT_CLEAR(HWTest_IGN_50pc, 5); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil5Charge(); BIT_CLEAR(HWTest_IGN_50pc, 5); } break; case TS_CMD_IGN5_50PC: // cmd group is for spark4 50%dc actions - #if IGN_CHANNELS >= 5 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 5); } - if(!BIT_CHECK(HWTest_IGN_50pc, 5)) { coil5Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 5); } + if(!BIT_CHECK(HWTest_IGN_50pc, 5)) { coil5Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) break; case TS_CMD_IGN6_ON: // cmd group is for spark6 on actions - #if IGN_CHANNELS >= 6 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil6Charge(); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil6Charge(); } break; case TS_CMD_IGN6_OFF: // cmd group is for spark6 off actions - #if IGN_CHANNELS >= 6 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil6Charge(); BIT_CLEAR(HWTest_IGN_50pc, 6); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil6Charge(); BIT_CLEAR(HWTest_IGN_50pc, 6); } break; case TS_CMD_IGN6_50PC: // cmd group is for spark6 50%dc actions - #if IGN_CHANNELS >= 6 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 6); } - if(!BIT_CHECK(HWTest_IGN_50pc, 6)) { coil6Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 6); } + if(!BIT_CHECK(HWTest_IGN_50pc, 6)) { coil6Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) break; case TS_CMD_IGN7_ON: // cmd group is for spark7 on actions - #if IGN_CHANNELS >= 7 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil7Charge(); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil7Charge(); } break; case TS_CMD_IGN7_OFF: // cmd group is for spark7 off actions - #if IGN_CHANNELS >= 7 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil7Charge(); BIT_CLEAR(HWTest_IGN_50pc, 7); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil7Charge(); BIT_CLEAR(HWTest_IGN_50pc, 7); } break; case TS_CMD_IGN7_50PC: // cmd group is for spark7 50%dc actions - #if IGN_CHANNELS >= 7 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 7); } - if(!BIT_CHECK(HWTest_IGN_50pc, 7)) { coil7Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 7); } + if(!BIT_CHECK(HWTest_IGN_50pc, 7)) { coil7Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) break; case TS_CMD_IGN8_ON: // cmd group is for spark8 on actions - #if IGN_CHANNELS >= 8 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil8Charge(); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil8Charge(); } break; case TS_CMD_IGN8_OFF: // cmd group is for spark8 off actions - #if IGN_CHANNELS >= 8 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil8Charge(); BIT_CLEAR(HWTest_IGN_50pc, 8); } - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil8Charge(); BIT_CLEAR(HWTest_IGN_50pc, 8); } break; case TS_CMD_IGN8_50PC: // cmd group is for spark8 50%dc actions - #if IGN_CHANNELS >= 8 - if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 8); } - if(!BIT_CHECK(HWTest_IGN_50pc, 8)) { coil8Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) - #endif + if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 8); } + if(!BIT_CHECK(HWTest_IGN_50pc, 8)) { coil8Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently) break; //VSS Calibration routines diff --git a/speeduino/idle.ino b/speeduino/idle.ino index f29e0b68..a0ea2e22 100644 --- a/speeduino/idle.ino +++ b/speeduino/idle.ino @@ -87,7 +87,7 @@ void initialiseIdle() #elif defined(CORE_TEENSY) idle_pwm_max_count = 1000000L / (32 * configPage6.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz #endif - idlePID.SetOutputLimits(percentage(configPage2.iacCLminDuty, idle_pwm_max_count), percentage(configPage2.iacCLmaxDuty, idle_pwm_max_count)); + idlePID.SetOutputLimits(percentage(configPage2.iacCLminDuty, idle_pwm_max_count<<2), percentage(configPage2.iacCLmaxDuty, idle_pwm_max_count<<2)); idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD); idlePID.SetMode(AUTOMATIC); //Turn PID on @@ -159,7 +159,7 @@ void initialiseIdle() } idlePID.SetSampleTime(100); - idlePID.SetOutputLimits(0, (configPage9.iacMaxSteps * 3)); //Maximum number of steps; always less than home steps count. + idlePID.SetOutputLimits(0, (configPage9.iacMaxSteps * 3)<<2); //Maximum number of steps; always less than home steps count. idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD); idlePID.SetMode(AUTOMATIC); //Turn PID on break; @@ -247,6 +247,17 @@ void idleControl() case IAC_ALGORITHM_PWM_CL: //Case 3 is PWM closed loop //No cranking specific value for closed loop (yet?) + if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) ) + { + //Currently cranking. Use the cranking table + currentStatus.idleDuty = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees + currentStatus.idleLoad = currentStatus.idleDuty; + idle_pwm_target_value = percentage(currentStatus.idleDuty, idle_pwm_max_count); + idle_pid_target_value = idle_pwm_target_value<<2; //Resolution increased + idlePID.Initialize(); //Update output to smooth transition + } + else + { currentStatus.CLIdleTarget = (byte)table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees idle_cl_target_rpm = (uint16_t)currentStatus.CLIdleTarget * 10; //Multiply the byte target value back out by 10 if( (idleCounter & 31) == 1) { idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD); } //This only needs to be run very infrequently, once every 32 calls to idleControl(). This is approx. once per second @@ -254,7 +265,7 @@ void idleControl() PID_computed = idlePID.Compute(true); if(PID_computed == true) { - idle_pwm_target_value = idle_pid_target_value; + idle_pwm_target_value = idle_pid_target_value>>2; //increased resolution if( idle_pwm_target_value == 0 ) { disableIdle(); @@ -267,6 +278,7 @@ void idleControl() } idleCounter++; + } break; case IAC_ALGORITHM_STEP_OL: //Case 4 is open loop stepper control @@ -291,9 +303,9 @@ void idleControl() else { //Standard running - //Only do a lookup of the required value around 4 times per second (Once every 255 mainloops). Any more than this can create too much jitter and require a hyster value that is too high + //Only do a lookup of the required value around 4 times per second. Any more than this can create too much jitter and require a hyster value that is too high //We must also have more than zero RPM for the running state - if (((mainLoopCount & 255) == 1) && (currentStatus.RPM > 0)) + if (BIT_CHECK(LOOP_TIMER, BIT_TIMER_4HZ) && (currentStatus.RPM > 0)) { idleStepper.targetIdleStep = table2D_getValue(&iacStepTable, (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET)) * 3; //All temps are offset by 40 degrees. Step counts are divided by 3 in TS. Multiply back out here if(currentStatus.idleUpActive == true) { idleStepper.targetIdleStep += configPage2.idleUpAdder; } //Add Idle Up amount if active @@ -319,7 +331,7 @@ void idleControl() //First thing to check is whether there is currently a step going on and if so, whether it needs to be turned off if( (checkForStepping() == false) && (isStepperHomed() == true) ) //Check that homing is complete and that there's not currently a step already taking place. MUST BE IN THIS ORDER! { - if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK )/* ||currentStatus.rpmDOT>=500||currentStatus.rpmDOT<=-500*/) + if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) ) { //Currently cranking. Use the cranking table idleStepper.targetIdleStep = table2D_getValue(&iacCrankStepsTable, (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET)) * 3; //All temps are offset by 40 degrees. Step counts are divided by 3 in TS. Multiply back out here @@ -332,36 +344,35 @@ void idleControl() } doStep(); - + idle_pid_target_value = idleStepper.targetIdleStep<<2; //Resolution increased + idlePID.Initialize(); //Update output to smooth transition } - else { - if( (idleCounter & 31) == 1) - { - //This only needs to be run very infrequently, once every 32 calls to idleControl(). This is approx. once per second - idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD); - iacStepTime_uS = configPage6.iacStepTime * 1000; - iacCoolTime_uS = configPage9.iacCoolTime * 1000; + if( (idleCounter & 31) == 1) + { + //This only needs to be run very infrequently, once every 32 calls to idleControl(). This is approx. once per second + idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD); + iacStepTime_uS = configPage6.iacStepTime * 1000; + iacCoolTime_uS = configPage9.iacCoolTime * 1000; + } + + currentStatus.CLIdleTarget = (byte)table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees + idle_cl_target_rpm = (uint16_t)currentStatus.CLIdleTarget * 10; //All temps are offset by 40 degrees + PID_computed = idlePID.Compute(true); + idleStepper.targetIdleStep = idle_pid_target_value>>2; //Increase resolution + if(currentStatus.idleUpActive == true) { idleStepper.targetIdleStep += configPage2.idleUpAdder; } //Add Idle Up amount if active + + //limit to the configured max steps. This must include any idle up adder, to prevent over-opening. + if (idleStepper.targetIdleStep > (configPage9.iacMaxSteps * 3) ) + { + idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3; + } + + doStep(); + idleCounter++; } - - currentStatus.CLIdleTarget = (byte)table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees - idle_cl_target_rpm = (uint16_t)currentStatus.CLIdleTarget * 10; //All temps are offset by 40 degrees - if(currentStatus.idleUpActive == true) { idle_pid_target_value += configPage2.idleUpAdder; } //Add Idle Up amount if active - PID_computed = idlePID.Compute(true); - idleStepper.targetIdleStep = idle_pid_target_value; - - //limit to the configured max steps. This must include any idle up adder, to prevent over-opening. - if (idleStepper.targetIdleStep > (configPage9.iacMaxSteps * 3) ) - { - idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3; - } - - doStep(); - - idleCounter++; - } - currentStatus.idleLoad = idleStepper.curIdleStep / 2; //Current step count (Divided by 2 for byte) + currentStatus.idleLoad = idleStepper.curIdleStep / 2; //Current step count (Divided by 2 for byte) } //Set or clear the idle active flag if(idleStepper.targetIdleStep != idleStepper.curIdleStep) { BIT_SET(currentStatus.spark, BIT_SPARK_IDLE); } diff --git a/speeduino/src/PID_v1/PID_v1.cpp b/speeduino/src/PID_v1/PID_v1.cpp index 4e08164d..591ef9fd 100755 --- a/speeduino/src/PID_v1/PID_v1.cpp +++ b/speeduino/src/PID_v1/PID_v1.cpp @@ -213,13 +213,12 @@ integerPID::integerPID(long* Input, long* Output, long* Setpoint, byte Kp, byte Ki, byte Kd, byte ControllerDirection) { - myOutput = Output; + myOutput = Output; myInput = Input; - mySetpoint = Setpoint; + mySetpoint = Setpoint; inAuto = false; - integerPID::SetOutputLimits(0, 255); //default output limit corresponds to - //the arduino pwm limits + integerPID::SetOutputLimits(0, 255); //default output limit corresponds to the arduino pwm limits SampleTime = 250; //default Controller Sample Time is 0.25 seconds. This is the 4Hz control time for Idle and VVT @@ -240,45 +239,57 @@ bool integerPID::Compute(bool pOnE) { if(!inAuto) return false; unsigned long now = millis(); - //SampleTime = (now - lastTime); unsigned long timeChange = (now - lastTime); if(timeChange >= SampleTime) { /*Compute all the working error variables*/ - long input = *myInput; - long error = *mySetpoint - input; - long dInput = (input - lastInput); - - outputSum += (ki * error)/1024; //Note that ki is multiplied by 1024 so it must be divided by 1024 here - if(outputSum > outMax) { outputSum = outMax; } - else if(outputSum < outMin) { outputSum = outMin; } - - /*Compute PID Output*/ - long output; - - if(pOnE) + long input = *myInput; + if(input > 0) //Fail safe, should never be 0 { - output = (kp * error) + outputSum - ((kd * dInput)/128); + long error = *mySetpoint - input; + long dInput = (input - lastInput); + long outMinResized = outMin< outMaxResized) { outputSum = outMaxResized; } + else if(outputSum < outMinResized) { outputSum = outMinResized; } + } + + /*Compute PID Output*/ + long output; + + if(pOnE) + { + output = (kp * error); + if (ki != 0) { output += outputSum; } + if (kd != 0) { output -= (kd * dInput)>>2; } + output >>= PID_SHIFTS; + } + else + { + outputSum -= (kp * dInput); + if(outputSum > outMaxResized) { outputSum = outMaxResized; } + else if(outputSum < outMinResized) { outputSum = outMinResized; } + + output = outputSum; + if (kd != 0) { output -= (kd * dInput)>>2; } + output >>= PID_SHIFTS; + } + + + if(output > outMax) output = outMax; + else if(output < outMin) output = outMin; + *myOutput = output; + + /*Remember some variables for next time*/ + lastInput = input; + lastTime = now; + + return true; } - else - { - outputSum -= kp * dInput; - if(outputSum > outMax) { outputSum = outMax; } - else if(outputSum < outMin) { outputSum = outMin; } - - output = outputSum - ((kd * dInput)/128); - } - - - if(output > outMax) output = outMax; - else if(output < outMin) output = outMin; - *myOutput = output; - - /*Remember some variables for next time*/ - lastInput = input; - lastTime = now; - - return true; } else return false; } @@ -364,9 +375,10 @@ void integerPID::SetTunings(byte Kp, byte Ki, byte Kd) kd = Kd / SampleTimeInSec; */ long InverseSampleTimeInSec = 1000 / SampleTime; - kp = Kp; - ki = (long)((long)Ki * 1024) / InverseSampleTimeInSec; - kd = ((long)Kd * InverseSampleTimeInSec); + //New resolution, 2 shifts to improve ki here | kp 1.563% | ki 1.563% | kd 0.195% + kp = (uint16_t)Kp<<2; + ki = (long)(Ki<<2) / InverseSampleTimeInSec; + kd = (long)(Kd<<2) * InverseSampleTimeInSec; if(controllerDirection == REVERSE) { @@ -409,8 +421,8 @@ void integerPID::SetOutputLimits(long Min, long Max) if(*myOutput > outMax) *myOutput = outMax; else if(*myOutput < outMin) *myOutput = outMin; - if(outputSum > outMax) { outputSum = outMax; } - else if(outputSum < outMin) { outputSum = outMin; } + if((outputSum>>PID_SHIFTS) > outMax) { outputSum = outMax<>PID_SHIFTS) < outMin) { outputSum = outMin< outMax) { outputSum = outMax; } - else if(outputSum < outMin) { outputSum = outMin; } + if((outputSum>>PID_SHIFTS) > outMax) { outputSum = outMax<>PID_SHIFTS) < outMin) { outputSum = outMin<