PWM and on/off idle fixes/cleanup (#806)

* Idle fixes #1

* Idle fixes #2

Co-authored-by: Josh Stewart <josh@noisymime.org>
This commit is contained in:
Pasi Kemppainen 2022-04-12 03:23:18 +03:00 committed by GitHub
parent 2cda68277b
commit 5dee6135b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 59 deletions

View File

@ -4832,6 +4832,7 @@ cmdVSSratio6 = "E\x99\x06"
indicator = { vvt1Error }, "VVT1 Ok", "VVT1 Error", white, black, red, black
indicator = { vvt2Error }, "VVT2 Ok", "VVT2 Error", white, black, red, black
indicator = { fanStatus }, "Fan OFF", "Fan ON", white, black, red, black
indicator = { idleControlOn }, "Idle OFF", "Idle ON", white, black, green, black
indicator = { (batteryVoltage < batlow) || (batteryVoltage > bathigh) }, "Battery Voltage OK", "Battery Voltage Warning", white, black, red, black
indicator = { outputsStatus0 }, "Programmable out 1 Off", "Programmable out 1 ON", white, black, green, black
indicator = { outputsStatus1 }, "Programmable out 2 Off", "Programmable out 2 ON", white, black, green, black

View File

@ -311,7 +311,7 @@ void sendcanValues(uint16_t offset, uint16_t packetLength, byte cmd, byte portTy
fullStatus[87] = highByte(currentStatus.ignLoad);
fullStatus[88] = lowByte(currentStatus.injAngle);
fullStatus[89] = highByte(currentStatus.injAngle);
fullStatus[90] = currentStatus.idleDuty;
fullStatus[90] = currentStatus.idleLoad;
fullStatus[91] = currentStatus.CLIdleTarget; //closed loop idle target
fullStatus[92] = currentStatus.mapDOT; //rate of change of the map
fullStatus[93] = (int8_t)currentStatus.vvt1Angle;

View File

@ -669,7 +669,6 @@ struct statuses {
byte fuelTempCorrection; /**< Amount of correction being applied to compensate for fuel temperature */
int8_t flexIgnCorrection;/**< Amount of additional advance being applied based on flex. Note the type as this allows for negative values */
byte afrTarget; /**< Current AFR Target looked up from AFR target table (x10 ? See @ref afrTable)*/
byte idleDuty; /**< The current idle duty cycle amount if PWM idle is selected and active */
byte CLIdleTarget; /**< The target idle RPM (when closed loop idle control is active) */
bool idleUpActive; /**< Whether the externally controlled idle up is currently active */
bool CTPSActive; /**< Whether the externally controlled closed throttle position sensor is currently active */

View File

@ -16,6 +16,8 @@
#define IDLE_PIN_LOW() *idle_pin_port &= ~(idle_pin_mask)
#define IDLE_PIN_HIGH() *idle_pin_port |= (idle_pin_mask)
#define IDLE2_PIN_LOW() *idle2_pin_port &= ~(idle2_pin_mask)
#define IDLE2_PIN_HIGH() *idle2_pin_port |= (idle2_pin_mask)
#define STEPPER_FORWARD 0
#define STEPPER_BACKWARD 1

View File

@ -54,7 +54,7 @@ void initialiseIdle()
//Case 1 is on/off idle control
if ((currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) < configPage6.iacFastTemp)
{
digitalWrite(pinIdle1, HIGH);
IDLE_PIN_HIGH();
idleOn = true;
}
break;
@ -451,15 +451,17 @@ void idleControl()
case IAC_ALGORITHM_ONOFF: //Case 1 is on/off idle control
if ( (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) < configPage6.iacFastTemp) //All temps are offset by 40 degrees
{
digitalWrite(pinIdle1, HIGH);
IDLE_PIN_HIGH();
idleOn = true;
BIT_SET(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag on
currentStatus.idleLoad = 100;
}
else if (idleOn)
{
digitalWrite(pinIdle1, LOW);
IDLE_PIN_LOW();
idleOn = false;
BIT_CLEAR(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag on
currentStatus.idleLoad = 0;
}
break;
@ -468,7 +470,7 @@ void idleControl()
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 = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
idleTaper = 0;
}
else if ( !BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN))
@ -476,7 +478,7 @@ void idleControl()
if( configPage6.iacPWMrun == true)
{
//Engine is not running or cranking, but the run before crank flag is set. Use the cranking table
currentStatus.idleDuty = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
currentStatus.idleLoad = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
idleTaper = 0;
}
}
@ -485,7 +487,7 @@ void idleControl()
if ( idleTaper < configPage2.idleTaperTime )
{
//Tapering between cranking IAC value and running
currentStatus.idleDuty = map(idleTaper, 0, configPage2.idleTaperTime,\
currentStatus.idleLoad = map(idleTaper, 0, configPage2.idleTaperTime,\
table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET),\
table2D_getValue(&iacPWMTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET));
if( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) ) { idleTaper++; }
@ -493,22 +495,13 @@ void idleControl()
else
{
//Standard running
currentStatus.idleDuty = table2D_getValue(&iacPWMTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
currentStatus.idleLoad = table2D_getValue(&iacPWMTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
}
}
if(currentStatus.idleUpActive == true) { currentStatus.idleDuty += configPage2.idleUpAdder; } //Add Idle Up amount if active
if( currentStatus.idleDuty > 100 ) { currentStatus.idleDuty = 100; } //Safety Check
if( currentStatus.idleDuty == 0 )
{
disableIdle();
BIT_CLEAR(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag off
break;
}
BIT_SET(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag on
idle_pwm_target_value = percentage(currentStatus.idleDuty, idle_pwm_max_count);
currentStatus.idleLoad = currentStatus.idleDuty;
idleOn = true;
if(currentStatus.idleUpActive == true) { currentStatus.idleLoad += configPage2.idleUpAdder; } //Add Idle Up amount if active
if( currentStatus.idleLoad > 100 ) { currentStatus.idleLoad = 100; } //Safety Check
idle_pwm_target_value = percentage(currentStatus.idleLoad, idle_pwm_max_count);
break;
@ -517,9 +510,8 @@ void idleControl()
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);
currentStatus.idleLoad = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
idle_pwm_target_value = percentage(currentStatus.idleLoad, idle_pwm_max_count);
idle_pid_target_value = idle_pwm_target_value << 2; //Resolution increased
idlePID.Initialize(); //Update output to smooth transition
}
@ -528,9 +520,8 @@ void idleControl()
if( configPage6.iacPWMrun == true)
{
//Engine is not running or cranking, but the run before crank flag is set. 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);
currentStatus.idleLoad = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
idle_pwm_target_value = percentage(currentStatus.idleLoad, idle_pwm_max_count);
}
}
else
@ -543,15 +534,8 @@ void idleControl()
if(PID_computed == true)
{
idle_pwm_target_value = idle_pid_target_value>>2; //increased resolution
if( idle_pwm_target_value == 0 )
{
disableIdle();
BIT_CLEAR(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag off
break;
}
BIT_SET(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag on
currentStatus.idleLoad = ((unsigned long)(idle_pwm_target_value * 100UL) / idle_pwm_max_count);
if(currentStatus.idleUpActive == true) { currentStatus.idleDuty += configPage2.idleUpAdder; } //Add Idle Up amount if active
if(currentStatus.idleUpActive == true) { currentStatus.idleLoad += configPage2.idleUpAdder; } //Add Idle Up amount if active
}
idleCounter++;
@ -564,12 +548,20 @@ void idleControl()
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);
currentStatus.idleLoad = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
idle_pwm_target_value = percentage(currentStatus.idleLoad, idle_pwm_max_count);
idle_pid_target_value = idle_pwm_target_value << 2; //Resolution increased
idlePID.Initialize(); //Update output to smooth transition
}
else if ( !BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN))
{
if( configPage6.iacPWMrun == true)
{
//Engine is not running or cranking, but the run before crank flag is set. Use the cranking table
currentStatus.idleLoad = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
idle_pwm_target_value = percentage(currentStatus.idleLoad, idle_pwm_max_count);
}
}
else
{
//Read the OL table as feedforward term
@ -586,15 +578,8 @@ void idleControl()
if(PID_computed == true)
{
idle_pwm_target_value = idle_pid_target_value>>2; //increased resolution
if( idle_pwm_target_value == 0 )
{
disableIdle();
BIT_CLEAR(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag off
break;
}
BIT_SET(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag on
currentStatus.idleLoad = ((unsigned long)(idle_pwm_target_value * 100UL) / idle_pwm_max_count);
if(currentStatus.idleUpActive == true) { currentStatus.idleDuty += configPage2.idleUpAdder; } //Add Idle Up amount if active
if(currentStatus.idleUpActive == true) { currentStatus.idleLoad += configPage2.idleUpAdder; } //Add Idle Up amount if active
}
idleCounter++;
@ -753,15 +738,35 @@ void idleControl()
}
lastDFCOValue = BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO);
//Check for 100% DC on PWM idle
//Check for 100% and 0% DC on PWM idle
if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL) )
{
if(currentStatus.idleLoad == 100)
if(currentStatus.idleLoad >= 100)
{
BIT_SET(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag on
IDLE_TIMER_DISABLE();
IDLE_PIN_HIGH();
if (configPage6.iacPWMdir == 0)
{
//Normal direction
IDLE_PIN_HIGH(); // Switch pin high
if(configPage6.iacChannels == 1) { IDLE2_PIN_LOW(); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
}
else
{
//Reversed direction
IDLE_PIN_LOW(); // Switch pin to low
if(configPage6.iacChannels == 1) { IDLE2_PIN_HIGH(); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
}
}
else if (currentStatus.idleLoad == 0)
{
disableIdle();
}
else
{
BIT_SET(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag on
IDLE_TIMER_ENABLE();
}
else if(currentStatus.idleLoad > 0) { IDLE_TIMER_ENABLE(); }
}
}
@ -772,7 +777,18 @@ void disableIdle()
if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) )
{
IDLE_TIMER_DISABLE();
digitalWrite(pinIdle1, LOW);
if (configPage6.iacPWMdir == 0)
{
//Normal direction
IDLE_PIN_LOW(); // Switch pin to low
if(configPage6.iacChannels == 1) { IDLE2_PIN_HIGH(); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
}
else
{
//Reversed direction
IDLE_PIN_HIGH(); // Switch pin high
if(configPage6.iacChannels == 1) { IDLE2_PIN_LOW(); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
}
}
else if( (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OLCL) )
{
@ -809,14 +825,14 @@ void idleInterrupt() //Most ARM chips can simply call a function
if (configPage6.iacPWMdir == 0)
{
//Normal direction
*idle_pin_port &= ~(idle_pin_mask); // Switch pin to low (1 pin mode)
if(configPage6.iacChannels == 1) { *idle2_pin_port |= (idle2_pin_mask); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
IDLE_PIN_LOW(); // Switch pin to low (1 pin mode)
if(configPage6.iacChannels == 1) { IDLE2_PIN_HIGH(); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
}
else
{
//Reversed direction
*idle_pin_port |= (idle_pin_mask); // Switch pin high
if(configPage6.iacChannels == 1) { *idle2_pin_port &= ~(idle2_pin_mask); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
IDLE_PIN_HIGH(); // Switch pin high
if(configPage6.iacChannels == 1) { IDLE2_PIN_LOW(); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
}
SET_COMPARE(IDLE_COMPARE, IDLE_COUNTER + (idle_pwm_max_count - idle_pwm_cur_value) );
idle_pwm_state = false;
@ -826,14 +842,14 @@ void idleInterrupt() //Most ARM chips can simply call a function
if (configPage6.iacPWMdir == 0)
{
//Normal direction
*idle_pin_port |= (idle_pin_mask); // Switch pin high
if(configPage6.iacChannels == 1) { *idle2_pin_port &= ~(idle2_pin_mask); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
IDLE_PIN_HIGH(); // Switch pin high
if(configPage6.iacChannels == 1) { IDLE2_PIN_LOW(); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
}
else
{
//Reversed direction
*idle_pin_port &= ~(idle_pin_mask); // Switch pin to low (1 pin mode)
if(configPage6.iacChannels == 1) { *idle2_pin_port |= (idle2_pin_mask); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
IDLE_PIN_LOW(); // Switch pin to low (1 pin mode)
if(configPage6.iacChannels == 1) { IDLE2_PIN_HIGH(); } //If 2 idle channels are in use, flip idle2 to be the opposite of idle1
}
SET_COMPARE(IDLE_COMPARE, IDLE_COUNTER + idle_pwm_target_value);
idle_pwm_cur_value = idle_pwm_target_value;