From 33720f77f8f5f5cc452a36469c8cbe766226c7e3 Mon Sep 17 00:00:00 2001 From: Richard Metcalfe Date: Tue, 26 Feb 2019 22:52:37 +0000 Subject: [PATCH 1/2] Changes to idle stepper control to prevent idleControl() and disableIdle() from competing against each other. Also target the cranking stepper position when the engine stops and after initial homing when on open loop. Do not disable the stepper when engine stops on stepper closed loop. --- speeduino/idle.ino | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/speeduino/idle.ino b/speeduino/idle.ino index 23be3837..bb355e06 100644 --- a/speeduino/idle.ino +++ b/speeduino/idle.ino @@ -250,7 +250,8 @@ void idleControl() else if( (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) < iacStepTable.axisX[IDLE_TABLE_SIZE-1]) { //Standard running - if ((mainLoopCount & 255) == 1) + //We must also have more than zero RPM for the running state + if (((mainLoopCount & 255) == 1) && (currentStatus.RPM > 0)) { //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 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 @@ -389,13 +390,17 @@ static inline void disableIdle() IDLE_TIMER_DISABLE(); digitalWrite(pinIdle1, LOW); } - else if ( (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OL) ) + else if ((configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OL) ) { //Only disable the stepper motor if homing is completed if( (checkForStepping() == false) && (isStepperHomed() == true) ) { - digitalWrite(pinStepperEnable, HIGH); //Disable the DRV8825 - idleStepper.targetIdleStep = idleStepper.curIdleStep; //Don't try to move anymore + /* for open loop stepper we should just move to the cranking position when + disabling idle, since the only time this function is called in this scenario + is if the engine stops. + */ + 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 + if(currentStatus.idleUpActive == true) { idleStepper.targetIdleStep += configPage2.idleUpAdder; } //Add Idle Up amount if active? } } BIT_CLEAR(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag off From 3b29179621430dd085a9f6c8465ccf0bc8edfd3c Mon Sep 17 00:00:00 2001 From: Richard Metcalfe Date: Tue, 26 Feb 2019 22:53:43 +0000 Subject: [PATCH 2/2] Changes to separate out stepper cooling step time from stepper step time. --- reference/speeduino.ini | 4 ++++ speeduino/globals.h | 2 +- speeduino/idle.h | 1 + speeduino/idle.ino | 29 +++++++++++++++++++++++++++-- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index a158777b..0c680ff9 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -857,6 +857,7 @@ page = 9 ;unused10_152 = scalar, U08, 152, "", 1, 0, 0, 255, 0 ;unused10_153 = scalar, U08, 153, "", 1, 0, 0, 255, 0 iacStepperInv = bits, U08, 153, [0:0], "No", "Yes" + iacCoolTime = bits , U08, 153, [1:3], "0", "1", "2", "3", "4", "5", "6","INVALID" unused10_154 = scalar, U08, 154, "", 1, 0, 0, 255, 0 unused10_155 = scalar, U08, 155, "", 1, 0, 0, 255, 0 @@ -1348,6 +1349,8 @@ menuDialog = main iacChannels = "The number of output channels used for PWM valves. Select 1 for 2-wire valves or 2 for 3-wire valves." iacStepTime = "Pause time between each step. Values that are too low can cause the motor to behave erratically or not at all" + iacCoolTime = "Cool time between each step. Set to zero if you don't want any cooling at all" + iacStepHome = "Homing steps to perform on startup. Must be greater than the fully open steps value" iacStepHyster = "The minimum number of steps to move in any one go." iacAlgorithm = "Selects method of idle control.\nNone = no idle control valve.\nOn/Off valve.\nPWM valve (2,3 wire).\nStepper Valve (4,6,8 wire)." @@ -1719,6 +1722,7 @@ menuDialog = main dialog = stepper_idle, "Stepper Idle" field = "Step time (ms)", iacStepTime, { iacAlgorithm == 4 || iacAlgorithm == 5 } + field = "Cool time (ms)", iacCoolTime, { iacAlgorithm == 4 || iacAlgorithm == 5 } field = "Home steps", iacStepHome, { iacAlgorithm == 4 || iacAlgorithm == 5 } field = "Minimum Steps", iacStepHyster, { iacAlgorithm == 4 || iacAlgorithm == 5 } field = "Stepper Inverted", iacStepperInv, { iacAlgorithm == 4 || iacAlgorithm == 5 } diff --git a/speeduino/globals.h b/speeduino/globals.h index 5efd9316..d267635d 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -746,8 +746,8 @@ struct config9 { uint8_t Auxinpinb[16]; // digital pin number when internal aux in use byte iacStepperInv : 1; //stepper direction of travel to allow reversing. 0=normal, 1=inverted. + byte iacCoolTime : 3; // how long to wait for the stepper to cool between steps - byte unused10_153; byte unused10_154; byte unused10_155; byte unused10_156; diff --git a/speeduino/idle.h b/speeduino/idle.h index 243d6b0c..07b1000c 100644 --- a/speeduino/idle.h +++ b/speeduino/idle.h @@ -39,6 +39,7 @@ struct StepperIdle idleStepper; bool idleOn; //Simply tracks whether idle was on last time around byte idleInitComplete = 99; //TRacks which idle method was initialised. 99 is a method that will never exist unsigned int iacStepTime; +unsigned int iacCoolTime; unsigned int completedHomeSteps; volatile PORT_TYPE *idle_pin_port; diff --git a/speeduino/idle.ino b/speeduino/idle.ino index bb355e06..87f0d365 100644 --- a/speeduino/idle.ino +++ b/speeduino/idle.ino @@ -104,6 +104,7 @@ void initialiseIdle() iacCrankStepsTable.values = configPage6.iacCrankSteps; iacCrankStepsTable.axisX = configPage6.iacCrankBins; iacStepTime = configPage6.iacStepTime * 1000; + iacCoolTime = configPage9.iacCoolTime * 1000; completedHomeSteps = 0; idleStepper.curIdleStep = 0; @@ -133,6 +134,7 @@ void initialiseIdle() iacCrankStepsTable.values = configPage6.iacCrankSteps; iacCrankStepsTable.axisX = configPage6.iacCrankBins; iacStepTime = configPage6.iacStepTime * 1000; + iacCoolTime = configPage9.iacCoolTime * 1000; completedHomeSteps = 0; idleCounter = 0; @@ -257,6 +259,7 @@ void idleControl() 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 iacStepTime = configPage6.iacStepTime * 1000; + iacCoolTime = configPage9.iacCoolTime * 1000; } doStep(); } @@ -273,6 +276,7 @@ void idleControl() //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 = configPage6.iacStepTime * 1000; + iacCoolTime = configPage9.iacCoolTime * 1000; } idle_cl_target_rpm = table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) * 10; //All temps are offset by 40 degrees @@ -324,16 +328,37 @@ False: If the motor is ready for another step static inline byte checkForStepping() { bool isStepping = false; + unsigned int timeCheck; + if( (idleStepper.stepperStatus == STEPPING) || (idleStepper.stepperStatus == COOLING) ) { - if(micros_safe() > (idleStepper.stepStartTime + iacStepTime) ) + if (idleStepper.stepperStatus == STEPPING) { + timeCheck = iacStepTime; + } + else + { + timeCheck = iacCoolTime; + } + + if(micros_safe() > (idleStepper.stepStartTime + timeCheck) ) + { if(idleStepper.stepperStatus == STEPPING) { //Means we're currently in a step, but it needs to be turned off digitalWrite(pinStepperStep, LOW); //Turn off the step idleStepper.stepStartTime = micros_safe(); - idleStepper.stepperStatus = COOLING; //'Cooling' is the time the stepper needs to sit in LOW state before the next step can be made + + // if there is no cool time we can miss that step out completely. + if (iacCoolTime > 0) + { + idleStepper.stepperStatus = COOLING; //'Cooling' is the time the stepper needs to sit in LOW state before the next step can be made + } + else + { + idleStepper.stepperStatus = SOFF; + } + isStepping = true; } else