Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r7e522d0cc0ee30e2576c8ce9d1d0cadad0414664 -r3f7d30b23906496854054949d4491f3bae6ef3c4 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 7e522d0cc0ee30e2576c8ce9d1d0cadad0414664) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 3f7d30b23906496854054949d4491f3bae6ef3c4) @@ -49,7 +49,12 @@ #define TRIMMER_HEATER_MAX_DUTY_CYCLE 0.50 ///< Trimmer heater max duty cycle (50%). #endif #define HEATERS_MIN_DUTY_CYCLE 0.00 ///< Primary and trimmer heaters minimum duty cycle (0.00%). +#define PRIMARY_HEATERS_CUMULATIVE_DUTY_CYCLE ( MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE + \ + SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE ) ///< Primary heaters cumulative duty cycle. +#define PRIMARY_HEATER_INITIAL_DUTY_CYCLE_ESTIMATE_DIVISOR 2.0 ///< Primary heaters initial duty cycle estimation divisor. +#define MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR 2.0 ///< Main and small primary heater duty cycle divisor + #define PRIMARY_HEATERS_P_COEFFICIENT 0.02 ///< Primary heaters proportional coefficient. #define PRIMARY_HEATERS_I_COEFFICIENT 0.001 ///< Primary heaters integral coefficient. @@ -70,7 +75,7 @@ #define MAXIMUM_TARGET_TEMPERATURE 90U ///< Maximum allowed target temperature for the heaters. #define HEATERS_ON_WITH_NO_FLOW_TIMEOUT_COUNT ( ( 3 * MS_PER_SECOND ) / TASK_PRIORITY_INTERVAL ) ///< Heaters are on but there is no sufficient flow timeout in counts. -#define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_C 120.0 ///< Heaters max allowed internal temperature in degrees C. TODO figure out the max temperature value +#define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_C 190.0 ///< Heaters max allowed internal temperature in degrees C. TODO figure out the max temperature value #define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heaters max allowed internal temperature timeout in milliseconds. #define HEATERS_ON_NO_FLOW_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heaters on with no flow time out in milliseconds. @@ -191,7 +196,7 @@ // Initialize the PI controller for the primary heaters initializePIController( PI_CONTROLLER_ID_PRIMARY_HEATER, HEATERS_MIN_DUTY_CYCLE, PRIMARY_HEATERS_P_COEFFICIENT, PRIMARY_HEATERS_I_COEFFICIENT, - HEATERS_MIN_DUTY_CYCLE, MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE + SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE ); + HEATERS_MIN_DUTY_CYCLE, PRIMARY_HEATERS_CUMULATIVE_DUTY_CYCLE ); // Initialize the PI controller for the trimmer heater initializePIController( PI_CONTROLLER_ID_TRIMMER_HEATER, HEATERS_MIN_DUTY_CYCLE, TRIMMER_HEATER_P_COEFFICIENT, @@ -639,10 +644,13 @@ { PRIMARY_HEATERS_EXEC_STATES_T state = PRIMARY_HEATERS_EXEC_STATE_OFF; - if ( hasStartPrimaryHeaterRequested ) + if ( TRUE == hasStartPrimaryHeaterRequested ) { resetHeaterState( PRIMARY_HEATER ); + // Once the primary heaters duty cycle is set, it is divided into 2 + // so both heaters will start and both elements are heated up setMainPrimaryHeaterPWM( mainPrimaryHeaterDutyCycle ); + setSmallPrimaryHeaterPWM( smallPrimaryHeaterDutyCycle ); isPrimaryHeaterOn = TRUE; hasStartPrimaryHeaterRequested = FALSE; @@ -681,25 +689,25 @@ // If the flow is within range, run the PI controller to control the heaters normally if ( FALSE == isFlowBelowMin ) { - F32 outletTemp = getTemperatureValue( primaryHeatersFeedbackTempSensor ); - mainPrimaryHeaterDutyCycle = runPIController( PI_CONTROLLER_ID_PRIMARY_HEATER, primaryHeaterTargetTemperature, outletTemp ); - - if ( mainPrimaryHeaterDutyCycle >= MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE ) + // If the primary heater is running and another start primary heater request + // is set, reset the primary heater again + if ( TRUE == hasStartPrimaryHeaterRequested ) { - // The duty cycle from the PI controller was greater than max duty cycle of the main primary - // heater. So subtract the remaining from the max main primary heater duty cycle and set - // the rest to the small primary heater - smallPrimaryHeaterDutyCycle = mainPrimaryHeaterDutyCycle - MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE; - mainPrimaryHeaterDutyCycle = MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE; - setMainPrimaryHeaterPWM( mainPrimaryHeaterDutyCycle ); - setSmallPrimaryHeaterPWM( smallPrimaryHeaterDutyCycle ); + resetHeaterState( PRIMARY_HEATER ); + hasStartPrimaryHeaterRequested = FALSE; } else { - setMainPrimaryHeaterPWM( mainPrimaryHeaterDutyCycle ); - smallPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; - setSmallPrimaryHeaterPWM( smallPrimaryHeaterDutyCycle ); + F32 outletTemp = getTemperatureValue( primaryHeatersFeedbackTempSensor ); + mainPrimaryHeaterDutyCycle = runPIController( PI_CONTROLLER_ID_PRIMARY_HEATER, primaryHeaterTargetTemperature, outletTemp ); + + // Once the primary heaters duty cycle is set, it is divided into 2 so both heaters will start and both elements are heated up + smallPrimaryHeaterDutyCycle = mainPrimaryHeaterDutyCycle / MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR; + mainPrimaryHeaterDutyCycle = mainPrimaryHeaterDutyCycle / MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR; } + + setMainPrimaryHeaterPWM( mainPrimaryHeaterDutyCycle ); + setSmallPrimaryHeaterPWM( smallPrimaryHeaterDutyCycle ); } // Flow is below the minimum required flow to run the primary heaters else @@ -848,8 +856,29 @@ { if ( PRIMARY_HEATER == heater ) { - mainPrimaryHeaterDutyCycle = MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE; - resetPIController( PI_CONTROLLER_ID_PRIMARY_HEATER, MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE ); + // Calculate the delta temperature from the inlet primary heater to target temperature + F32 inletPrimaryHeaterTemp = getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ); + F32 deltaTemp = primaryHeaterTargetTemperature - inletPrimaryHeaterTemp; + + // If the delta temperature (target temperature - inlet primary heater temperature) + // Is 0 or negative, the duty cycle is 0.0 + if ( deltaTemp <= 0.0 ) + { + mainPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; + } + else + { + // The formula for the initial guess is: (delta temperature * target flow) / 2.0 + F32 targetFlow = getTargetROPumpFlowRate(); + F32 duty = ( targetFlow * deltaTemp ) / PRIMARY_HEATER_INITIAL_DUTY_CYCLE_ESTIMATE_DIVISOR; + // If the duty cycle is greater 200% on the primary and small primary heaters, set it to 200%, otherwise set it to the + // estimated duty cycles + duty = ( duty > PRIMARY_HEATERS_CUMULATIVE_DUTY_CYCLE ? PRIMARY_HEATERS_CUMULATIVE_DUTY_CYCLE : duty ); + mainPrimaryHeaterDutyCycle = duty / MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR; + smallPrimaryHeaterDutyCycle = duty / MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR; + } + + resetPIController( PI_CONTROLLER_ID_PRIMARY_HEATER, mainPrimaryHeaterDutyCycle ); } else if ( TRIMMER_HEATER == heater ) {