diff --git a/reference/speeduino.ini b/reference/speeduino.ini index a43234bb..534dcf26 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -558,11 +558,11 @@ page = 4 FILTER_FLEX = scalar, U08, 125, "%", 1.0, 0.0, 0, 240, 0 #if CELSIUS - vvtMinClt = array, U08, 126, "C", 1.0, -40, -40, 215, 0 + vvtMinClt = scalar, U08, 126, "C", 1.0, -40, -40, 215, 0 #else - vvtMinClt = scalar, U08, 126, "F", 1.8, -22.23, -40, 215, 0 + vvtMinClt = scalar, U08, 126, "F", 1.8, -22.23, -40, 215, 0 #endif - vvtDelay = scalar, U08, 127, "S", 5.0, 0.0, 0, 1275, 0 + vvtDelay = scalar, U08, 127, "S", 5.0, 0.0, 0, 1275, 0 ;-------------------------------------------------- @@ -2096,21 +2096,21 @@ menuDialog = main vvtCLMinAng = "Safety limit for minimum expected cam angle value. If cam angle gets smaller or equal to this, it triggers VVT error state, closed loop adjustment is disabled and VVT output duty drops to 0%" vvtCLMaxAng = "Safety limit for maximum expected cam angle value. If cam angle gets bigger than this, it triggers VVT error state, closed loop adjustment is disabled and VVT output duty drops to 0%" ANGLEFILTER_VVT = "Can be used to smooth out cam angle readings if needed. Only supported on specific decoders that have cam angle reading capability" - vvtMinClt = "Minimum coolant temp to activate VVT" - vvtDelay = "Time to wait after reaching minimum coolant temp (additional time for oil warmup)" + vvtMinClt = "Minimum coolant temp to activate VVT" + vvtDelay = "Time to wait after reaching minimum coolant temp (additional time for oil warmup)" stagedInjSizePri= "Size of the primary injectors. The sum of the Pri and Sec injectors values MUST match the value used in the req_fuel calculation" stagedInjSizeSec= "Size of the secondary injectors. The sum of the Pri and Sec injectors values MUST match the value used in the req_fuel calculation" #if resetcontrol_adv - resetControl = "How to control the Arduino's automatic reset feature. NOTE: Some of these settings require modifying your hardware and replacing the Arduino bootloader. See the Wiki for more details.\n\nDisabled: Allow the Arduino to reset when a new serial connection is made.\n\nPrevent When Running: Hold the control pin high while the engine is running.\n\nPrevent Always: Always hold the control pin high.\n\nSerial Command: Normally hold the control pin high, but pull it low when the 'U' serial command is issued and reset upon receiving more data." + resetControl = "How to control the Arduino's automatic reset feature. NOTE: Some of these settings require modifying your hardware and replacing the Arduino bootloader. See the Wiki for more details.\n\nDisabled: Allow the Arduino to reset when a new serial connection is made.\n\nPrevent When Running: Hold the control pin high while the engine is running.\n\nPrevent Always: Always hold the control pin high.\n\nSerial Command: Normally hold the control pin high, but pull it low when the 'U' serial command is issued and reset upon receiving more data." #else - resetControl = "If set to Serial Command, normally hold the control pin high but pull it low when the 'U' serial command is issued and reset upon receiving more data. The control pin should be connected to the Arduino's reset pin." + resetControl = "If set to Serial Command, normally hold the control pin high but pull it low when the 'U' serial command is issued and reset upon receiving more data. The control pin should be connected to the Arduino's reset pin." #endif - resetControlPin = "The Arduino pin used to control resets." + resetControlPin = "The Arduino pin used to control resets." - battVCorMode = "The Battery Voltage Correction value from the table below can either be applied on the whole injection Pulse Width value, or only on the Open Time value." - dwellTable = "Sets the dwell time in milliseconds based on RPM/load. This can be used to reduce stress/wear on ignition system where long dwell is not needed. And other areas can use longer dwell value if needed for stronger spark. Battery voltage correction is applied for these dwell values." - useDwellMap = "In normal operation mode this is set to No and speeduino will use fixed running dwell value. But if different dwell values are required across engine RPM/load range, this can be set to Yes and separate Dwell table defines running dwell value." + battVCorMode = "The Battery Voltage Correction value from the table below can either be applied on the whole injection Pulse Width value, or only on the Open Time value." + dwellTable = "Sets the dwell time in milliseconds based on RPM/load. This can be used to reduce stress/wear on ignition system where long dwell is not needed. And other areas can use longer dwell value if needed for stronger spark. Battery voltage correction is applied for these dwell values." + useDwellMap = "In normal operation mode this is set to No and speeduino will use fixed running dwell value. But if different dwell values are required across engine RPM/load range, this can be set to Yes and separate Dwell table defines running dwell value." [UserDefined] diff --git a/speeduino/auxiliaries.h b/speeduino/auxiliaries.h index ab5ff7b6..88870ea4 100644 --- a/speeduino/auxiliaries.h +++ b/speeduino/auxiliaries.h @@ -35,6 +35,8 @@ void wmiControl(); #define N2O_STAGE2_PIN_HIGH() *n2o_stage2_pin_port |= (n2o_stage2_pin_mask) #define READ_N2O_ARM_PIN() ((*n2o_arming_pin_port & n2o_arming_pin_mask) ? true : false) +#define VVT_TIME_DELAY_MULTIPLIER 50 + #define FAN_ON() ((configPage6.fanInv) ? FAN_PIN_LOW() : FAN_PIN_HIGH()) #define FAN_OFF() ((configPage6.fanInv) ? FAN_PIN_HIGH() : FAN_PIN_LOW()) @@ -62,6 +64,9 @@ long boost_pwm_target_value; long boost_cl_target_boost; byte boostCounter; byte vvtCounter; +uint32_t vvtWarmTime; +bool vvtIsHot; +bool vvtTimeHold; byte fanHIGH = HIGH; // Used to invert the cooling fan output byte fanLOW = LOW; // Used to invert the cooling fan output diff --git a/speeduino/auxiliaries.ino b/speeduino/auxiliaries.ino index 96306864..d10ecac3 100644 --- a/speeduino/auxiliaries.ino +++ b/speeduino/auxiliaries.ino @@ -9,16 +9,12 @@ A full copy of the license may be found in the projects root directory #include "src/PID_v1/PID_v1.h" #include "decoders.h" -uint32_t vvtTime; -bool vvtHot; -bool vvtTimeHold; //Old PID method. Retained incase the new one has issues //integerPID boostPID(&MAPx100, &boost_pwm_target_value, &boostTargetx100, configPage6.boostKP, configPage6.boostKI, configPage6.boostKD, DIRECT); integerPID_ideal boostPID(¤tStatus.MAP, ¤tStatus.boostDuty , ¤tStatus.boostTarget, &configPage10.boostSens, &configPage10.boostIntv, configPage6.boostKP, configPage6.boostKI, configPage6.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 vvtPID(&vvt_pid_current_angle, ¤tStatus.vvt1Duty, &vvt_pid_target_angle, configPage10.vvtCLKP, configPage10.vvtCLKI, configPage10.vvtCLKD, configPage6.vvtPWMdir); //This is the PID object if that algorithm is used. Needs to be global as it maintains state outside of each function call integerPID vvt2PID(&vvt2_pid_current_angle, ¤tStatus.vvt2Duty, &vvt2_pid_target_angle, configPage10.vvtCLKP, configPage10.vvtCLKI, configPage10.vvtCLKD, configPage4.vvt2PWMdir); //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 */ @@ -130,8 +126,8 @@ void initialiseAuxPWM() ENABLE_VVT_TIMER(); //Turn on the B compare unit (ie turn on the interrupt) BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT1_ERROR); BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT2_ERROR); - vvtTimeHold=false; - if (currentStatus.coolant >= (int)(configPage4.vvtMinClt - CALIBRATION_TEMPERATURE_OFFSET)) {vvtHot=true;} //Checks to see if coolant's already at operating temperature + vvtTimeHold = false; + if (currentStatus.coolant >= (int)(configPage4.vvtMinClt - CALIBRATION_TEMPERATURE_OFFSET)) { vvtIsHot = true; } //Checks to see if coolant's already at operating temperature } if( (configPage6.vvtEnabled == 0) && (configPage10.wmiEnabled >= 1) ) { @@ -306,150 +302,151 @@ void vvtControl() { if( (configPage6.vvtEnabled == 1) && (currentStatus.coolant >= (int)(configPage4.vvtMinClt - CALIBRATION_TEMPERATURE_OFFSET)) && (BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN))) { - if (vvtTimeHold==false) - { - vvtTime = runSecsX10; - vvtTimeHold=true; - } - if (((runSecsX10 - vvtTime) >= (configPage4.vvtDelay * 50)) || (vvtHot==true)) { - vvtHot=true; - //currentStatus.vvt1Duty = 0; - //Calculate the current cam angle - if( configPage4.TrigPattern == 9 ) { currentStatus.vvt1Angle = getCamAngle_Miata9905(); } - - if( (configPage6.vvtMode == VVT_MODE_OPEN_LOOP) || (configPage6.vvtMode == VVT_MODE_ONOFF) ) + if(vvtTimeHold == false) { - //Lookup VVT duty based on either MAP or TPS - if(configPage6.vvtLoadSource == VVT_LOAD_TPS) { currentStatus.vvt1Duty = get3DTableValue(&vvtTable, currentStatus.TPS, currentStatus.RPM); } - else { currentStatus.vvt1Duty = get3DTableValue(&vvtTable, currentStatus.MAP, currentStatus.RPM); } + vvtWarmTime = runSecsX10; + vvtTimeHold = true; + } + if( (vvtIsHot == true) || ((runSecsX10 - vvtWarmTime) >= (configPage4.vvtDelay * VVT_TIME_DELAY_MULTIPLIER)) ) + { + vvtIsHot = true; - //VVT table can be used for controlling on/off switching. If this is turned on, then disregard any interpolation or non-binary values - if( (configPage6.vvtMode == VVT_MODE_ONOFF) && (currentStatus.vvt1Duty < 200) ) { currentStatus.vvt1Duty = 0; } + //Calculate the current cam angle + if( configPage4.TrigPattern == 9 ) { currentStatus.vvt1Angle = getCamAngle_Miata9905(); } - vvt1_pwm_value = halfPercentage(currentStatus.vvt1Duty, vvt_pwm_max_count); - - if (configPage10.vvt2Enabled == 1) // same for VVT2 if it's enabled + if( (configPage6.vvtMode == VVT_MODE_OPEN_LOOP) || (configPage6.vvtMode == VVT_MODE_ONOFF) ) { //Lookup VVT duty based on either MAP or TPS - if(configPage6.vvtLoadSource == VVT_LOAD_TPS) { currentStatus.vvt2Duty = get3DTableValue(&vvt2Table, currentStatus.TPS, currentStatus.RPM); } - else { currentStatus.vvt2Duty = get3DTableValue(&vvt2Table, currentStatus.MAP, currentStatus.RPM); } + if(configPage6.vvtLoadSource == VVT_LOAD_TPS) { currentStatus.vvt1Duty = get3DTableValue(&vvtTable, currentStatus.TPS, currentStatus.RPM); } + else { currentStatus.vvt1Duty = get3DTableValue(&vvtTable, currentStatus.MAP, currentStatus.RPM); } //VVT table can be used for controlling on/off switching. If this is turned on, then disregard any interpolation or non-binary values - if( (configPage6.vvtMode == VVT_MODE_ONOFF) && (currentStatus.vvt2Duty < 200) ) { currentStatus.vvt2Duty = 0; } + if( (configPage6.vvtMode == VVT_MODE_ONOFF) && (currentStatus.vvt1Duty < 200) ) { currentStatus.vvt1Duty = 0; } - vvt2_pwm_value = halfPercentage(currentStatus.vvt2Duty, vvt_pwm_max_count); - } - - } //Open loop - else if( (configPage6.vvtMode == VVT_MODE_CLOSED_LOOP) ) - { - //Lookup VVT duty based on either MAP or TPS - if(configPage6.vvtLoadSource == VVT_LOAD_TPS) { currentStatus.vvt1TargetAngle = get3DTableValue(&vvtTable, currentStatus.TPS, currentStatus.RPM); } - else { currentStatus.vvt1TargetAngle = get3DTableValue(&vvtTable, currentStatus.MAP, currentStatus.RPM); } - - if( (vvtCounter & 31) == 1) { vvtPID.SetTunings(configPage10.vvtCLKP, configPage10.vvtCLKI, configPage10.vvtCLKD); //This only needs to be run very infrequently, once every 32 calls to vvtControl(). This is approx. once per second - vvtPID.SetControllerDirection(configPage6.vvtPWMdir); } - - // safety check that the cam angles are ok. The engine will be totally undriveable if the cam sensor is faulty and giving wrong cam angles, so if that happens, default to 0 duty. - // This also prevents using zero or negative current angle values for PID adjustment, because those don't work in integer PID. - if ( currentStatus.vvt1Angle <= configPage10.vvtCLMinAng || currentStatus.vvt1Angle > configPage10.vvtCLMaxAng ) - { - currentStatus.vvt1Duty = 0; vvt1_pwm_value = halfPercentage(currentStatus.vvt1Duty, vvt_pwm_max_count); - BIT_SET(currentStatus.status4, BIT_STATUS4_VVT1_ERROR); - } - //Check that we're not already at the angle we want to be - else if((configPage6.vvtCLUseHold > 0) && (currentStatus.vvt1TargetAngle == currentStatus.vvt1Angle) ) - { - currentStatus.vvt1Duty = configPage10.vvtCLholdDuty; - vvt1_pwm_value = halfPercentage(currentStatus.vvt1Duty, vvt_pwm_max_count); - vvtPID.Initialize(); - BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT1_ERROR); - } - else - { - //This is dumb, but need to convert the current angle into a long pointer. - vvt_pid_target_angle = (unsigned long)currentStatus.vvt1TargetAngle; - vvt_pid_current_angle = (long)currentStatus.vvt1Angle; - //If not already at target angle, calculate new value from PID - bool PID_compute = vvtPID.Compute(true); - //vvtPID.Compute2(currentStatus.vvt1TargetAngle, currentStatus.vvt1Angle, false); - //vvt_pwm_target_value = percentage(40, vvt_pwm_max_count); - //if (currentStatus.vvt1Angle > currentStatus.vvt1TargetAngle) { vvt_pwm_target_value = 0; } - if(PID_compute == true) { vvt1_pwm_value = halfPercentage(currentStatus.vvt1Duty, vvt_pwm_max_count); } - BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT1_ERROR); - } + if (configPage10.vvt2Enabled == 1) // same for VVT2 if it's enabled + { + //Lookup VVT duty based on either MAP or TPS + if(configPage6.vvtLoadSource == VVT_LOAD_TPS) { currentStatus.vvt2Duty = get3DTableValue(&vvt2Table, currentStatus.TPS, currentStatus.RPM); } + else { currentStatus.vvt2Duty = get3DTableValue(&vvt2Table, currentStatus.MAP, currentStatus.RPM); } - if (configPage10.vvt2Enabled == 1) // same for VVT2 if it's enabled + //VVT table can be used for controlling on/off switching. If this is turned on, then disregard any interpolation or non-binary values + if( (configPage6.vvtMode == VVT_MODE_ONOFF) && (currentStatus.vvt2Duty < 200) ) { currentStatus.vvt2Duty = 0; } + + vvt2_pwm_value = halfPercentage(currentStatus.vvt2Duty, vvt_pwm_max_count); + } + + } //Open loop + else if( (configPage6.vvtMode == VVT_MODE_CLOSED_LOOP) ) { - if(configPage6.vvtLoadSource == VVT_LOAD_TPS) { currentStatus.vvt2TargetAngle = get3DTableValue(&vvt2Table, currentStatus.TPS, currentStatus.RPM); } - else { currentStatus.vvt2TargetAngle = get3DTableValue(&vvt2Table, currentStatus.MAP, currentStatus.RPM); } + //Lookup VVT duty based on either MAP or TPS + if(configPage6.vvtLoadSource == VVT_LOAD_TPS) { currentStatus.vvt1TargetAngle = get3DTableValue(&vvtTable, currentStatus.TPS, currentStatus.RPM); } + else { currentStatus.vvt1TargetAngle = get3DTableValue(&vvtTable, currentStatus.MAP, currentStatus.RPM); } - if( vvtCounter == 30) { vvt2PID.SetTunings(configPage10.vvtCLKP, configPage10.vvtCLKI, configPage10.vvtCLKD); //This only needs to be run very infrequently, once every 32 calls to vvtControl(). This is approx. once per second - vvt2PID.SetControllerDirection(configPage4.vvt2PWMdir); } + if( (vvtCounter & 31) == 1) { vvtPID.SetTunings(configPage10.vvtCLKP, configPage10.vvtCLKI, configPage10.vvtCLKD); //This only needs to be run very infrequently, once every 32 calls to vvtControl(). This is approx. once per second + vvtPID.SetControllerDirection(configPage6.vvtPWMdir); } // safety check that the cam angles are ok. The engine will be totally undriveable if the cam sensor is faulty and giving wrong cam angles, so if that happens, default to 0 duty. // This also prevents using zero or negative current angle values for PID adjustment, because those don't work in integer PID. - if ( currentStatus.vvt2Angle <= configPage10.vvtCLMinAng || currentStatus.vvt2Angle > configPage10.vvtCLMaxAng ) + if ( currentStatus.vvt1Angle <= configPage10.vvtCLMinAng || currentStatus.vvt1Angle > configPage10.vvtCLMaxAng ) { - currentStatus.vvt2Duty = 0; - vvt2_pwm_value = halfPercentage(currentStatus.vvt2Duty, vvt_pwm_max_count); - BIT_SET(currentStatus.status4, BIT_STATUS4_VVT2_ERROR); + currentStatus.vvt1Duty = 0; + vvt1_pwm_value = halfPercentage(currentStatus.vvt1Duty, vvt_pwm_max_count); + BIT_SET(currentStatus.status4, BIT_STATUS4_VVT1_ERROR); } //Check that we're not already at the angle we want to be - else if((configPage6.vvtCLUseHold > 0) && (currentStatus.vvt2TargetAngle == currentStatus.vvt2Angle) ) + else if((configPage6.vvtCLUseHold > 0) && (currentStatus.vvt1TargetAngle == currentStatus.vvt1Angle) ) { - currentStatus.vvt2Duty = configPage10.vvtCLholdDuty; - vvt2_pwm_value = halfPercentage(currentStatus.vvt2Duty, vvt_pwm_max_count); - vvt2PID.Initialize(); - BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT2_ERROR); + currentStatus.vvt1Duty = configPage10.vvtCLholdDuty; + vvt1_pwm_value = halfPercentage(currentStatus.vvt1Duty, vvt_pwm_max_count); + vvtPID.Initialize(); + BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT1_ERROR); } else { //This is dumb, but need to convert the current angle into a long pointer. - vvt2_pid_target_angle = (unsigned long)currentStatus.vvt2TargetAngle; - vvt2_pid_current_angle = (long)currentStatus.vvt2Angle; - //If not already at target angle, calculate new value from PID - bool PID_compute = vvt2PID.Compute(true); - if(PID_compute == true) { vvt2_pwm_value = halfPercentage(currentStatus.vvt2Duty, vvt_pwm_max_count); } - BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT2_ERROR); - } - } - //currentStatus.vvt1Duty = 0; - vvtCounter++; - } + vvt_pid_target_angle = (unsigned long)currentStatus.vvt1TargetAngle; + vvt_pid_current_angle = (long)currentStatus.vvt1Angle; - //Set the PWM state based on the above lookups - if( (currentStatus.vvt1Duty == 0) && (currentStatus.vvt2Duty == 0) ) - { - //Make sure solenoid is off (0% duty) - VVT1_PIN_OFF(); - VVT2_PIN_OFF(); - vvt1_pwm_state = false; - vvt1_max_pwm = false; - vvt2_pwm_state = false; - vvt2_max_pwm = false; - DISABLE_VVT_TIMER(); - } - else if( (currentStatus.vvt1Duty >= 200) && (currentStatus.vvt2Duty >= 200) ) - { - //Make sure solenoid is on (100% duty) - VVT1_PIN_ON(); - VVT2_PIN_ON(); - vvt1_pwm_state = true; - vvt1_max_pwm = true; - vvt2_pwm_state = true; - vvt2_max_pwm = true; - DISABLE_VVT_TIMER(); - } - else - { - //Duty cycle is between 0 and 100. Make sure the timer is enabled - ENABLE_VVT_TIMER(); - if(currentStatus.vvt1Duty < 200) { vvt1_max_pwm = false; } - if(currentStatus.vvt2Duty < 200) { vvt2_max_pwm = false; } - } + //If not already at target angle, calculate new value from PID + bool PID_compute = vvtPID.Compute(true); + //vvtPID.Compute2(currentStatus.vvt1TargetAngle, currentStatus.vvt1Angle, false); + //vvt_pwm_target_value = percentage(40, vvt_pwm_max_count); + //if (currentStatus.vvt1Angle > currentStatus.vvt1TargetAngle) { vvt_pwm_target_value = 0; } + if(PID_compute == true) { vvt1_pwm_value = halfPercentage(currentStatus.vvt1Duty, vvt_pwm_max_count); } + BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT1_ERROR); + } + + if (configPage10.vvt2Enabled == 1) // same for VVT2 if it's enabled + { + if(configPage6.vvtLoadSource == VVT_LOAD_TPS) { currentStatus.vvt2TargetAngle = get3DTableValue(&vvt2Table, currentStatus.TPS, currentStatus.RPM); } + else { currentStatus.vvt2TargetAngle = get3DTableValue(&vvt2Table, currentStatus.MAP, currentStatus.RPM); } + + if( vvtCounter == 30) { vvt2PID.SetTunings(configPage10.vvtCLKP, configPage10.vvtCLKI, configPage10.vvtCLKD); //This only needs to be run very infrequently, once every 32 calls to vvtControl(). This is approx. once per second + vvt2PID.SetControllerDirection(configPage4.vvt2PWMdir); } + + // safety check that the cam angles are ok. The engine will be totally undriveable if the cam sensor is faulty and giving wrong cam angles, so if that happens, default to 0 duty. + // This also prevents using zero or negative current angle values for PID adjustment, because those don't work in integer PID. + if ( currentStatus.vvt2Angle <= configPage10.vvtCLMinAng || currentStatus.vvt2Angle > configPage10.vvtCLMaxAng ) + { + currentStatus.vvt2Duty = 0; + vvt2_pwm_value = halfPercentage(currentStatus.vvt2Duty, vvt_pwm_max_count); + BIT_SET(currentStatus.status4, BIT_STATUS4_VVT2_ERROR); + } + //Check that we're not already at the angle we want to be + else if((configPage6.vvtCLUseHold > 0) && (currentStatus.vvt2TargetAngle == currentStatus.vvt2Angle) ) + { + currentStatus.vvt2Duty = configPage10.vvtCLholdDuty; + vvt2_pwm_value = halfPercentage(currentStatus.vvt2Duty, vvt_pwm_max_count); + vvt2PID.Initialize(); + BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT2_ERROR); + } + else + { + //This is dumb, but need to convert the current angle into a long pointer. + vvt2_pid_target_angle = (unsigned long)currentStatus.vvt2TargetAngle; + vvt2_pid_current_angle = (long)currentStatus.vvt2Angle; + //If not already at target angle, calculate new value from PID + bool PID_compute = vvt2PID.Compute(true); + if(PID_compute == true) { vvt2_pwm_value = halfPercentage(currentStatus.vvt2Duty, vvt_pwm_max_count); } + BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT2_ERROR); + } + } + //currentStatus.vvt1Duty = 0; + vvtCounter++; + } + + //Set the PWM state based on the above lookups + if( (currentStatus.vvt1Duty == 0) && (currentStatus.vvt2Duty == 0) ) + { + //Make sure solenoid is off (0% duty) + VVT1_PIN_OFF(); + VVT2_PIN_OFF(); + vvt1_pwm_state = false; + vvt1_max_pwm = false; + vvt2_pwm_state = false; + vvt2_max_pwm = false; + DISABLE_VVT_TIMER(); + } + else if( (currentStatus.vvt1Duty >= 200) && (currentStatus.vvt2Duty >= 200) ) + { + //Make sure solenoid is on (100% duty) + VVT1_PIN_ON(); + VVT2_PIN_ON(); + vvt1_pwm_state = true; + vvt1_max_pwm = true; + vvt2_pwm_state = true; + vvt2_max_pwm = true; + DISABLE_VVT_TIMER(); + } + else + { + //Duty cycle is between 0 and 100. Make sure the timer is enabled + ENABLE_VVT_TIMER(); + if(currentStatus.vvt1Duty < 200) { vvt1_max_pwm = false; } + if(currentStatus.vvt2Duty < 200) { vvt2_max_pwm = false; } + } } }