Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -raf83481e7313ed6b624e1a8ed8996a906177ad6d -r2c4dfa08ac8ead07939b4f6aba3b0073e0997706 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision af83481e7313ed6b624e1a8ed8996a906177ad6d) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 2c4dfa08ac8ead07939b4f6aba3b0073e0997706) @@ -69,13 +69,16 @@ #define HEATERS_MIN_RAMP_TIME_MS ( 6 * MS_PER_SECOND ) ///< Heaters minimum time that they have to stay in the ramp state in milliseconds. #define TEMPERATURES_MOVING_AVG_SIZE 3U ///< Heaters ramp state temperatures moving average size. -#define PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_SLOPE 0.395 ///< Primary heaters thermal power to voltage slope. -#define PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_INTERCEPT 0.21 ///< Primary heaters thermal power to voltage intercept. +#define PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_SLOPE 0.395 // TODO remove ///< Primary heaters thermal power to voltage slope. +#define PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_INTERCEPT 0.21 // TODO remove ///< Primary heaters thermal power to voltage intercept. #define DELTA_DUTY_CYCLE_GAIN 0.1 ///< Delta duty cycle gain. #define DELTA_TEMPERATURE_GAIN 1.27 ///< Delta temperature gain. #define HEATERS_CONTROL_TO_TARGET_DUTY_CYCLE_CAP 0.09 ///< Heaters control to target duty cycle cap. +static const F32 WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES = 4184 / SEC_PER_MIN; ///< Water specific heat in J/KgC / 60. +static const F32 PRIMARY_HEATERS_MAXIMUM_POWER_WATTS = 475 + 237.5; ///< Primary heaters maximum power (main primary = 475W and small primary = 237.5W). + typedef enum Heaters_Exec_States { HEATER_EXEC_STATE_NOT_RUNNING = 0, ///< Heater exec state not running. @@ -99,6 +102,7 @@ U32 heaterOnWithNoFlowTimer; // TODO remove ///< Heater on with no flow timer. BOOL isFlowBelowMin; ///< Heater flow below minimum flag indicator. BOOL hasTargetTempChanged; ///< Heater target temperature change flag indicator. + BOOL isThisFirstFill; ///< Heater the first fill flag indicator. PI_CONTROLLER_ID_T controllerID; ///< Heater PI controller ID TODO remove this? @@ -119,7 +123,7 @@ static HEATERS_STATE_T handleHeaterStateControlToTarget( DG_HEATERS_T heater ); static void setHeaterDutyCycle( DG_HEATERS_T heater, F32 pwm ); -static F32 calculateHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow ); +static F32 calculatePrimaryHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow ); static BOOL haveHeaterControlConditionsChanged( DG_HEATERS_T heater ); static void setMainPrimaryHeaterPWM( F32 pwm ); @@ -162,6 +166,7 @@ heatersStatus[ heater ].targetROFlow = 0.0; heatersStatus[ heater ].controllerID = ( DG_PRIMARY_HEATER == heater ? 4 : PI_CONTROLLER_ID_TRIMMER_HEATER ); // TODO remove or refactor? heatersStatus[ heater ].hasTargetTempChanged = FALSE; + heatersStatus[ heater ].isThisFirstFill = TRUE; } // Initialize the PI controller for the trimmer heater @@ -422,12 +427,6 @@ heatersStatus[ heater ].startHeaterSignal = FALSE; heatersStatus[ heater ].targetROFlow = getTargetROPumpFlowRate(); - // TODO for testing remove - heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; - F32 dutyCycle = calculateHeaterDutyCycle( 39.0, getTemperatureValue( (U32)TEMPSENSORS_HEAT_DISINFECT ), 0.8 ); - setHeaterDutyCycle( heater, dutyCycle ); - // TODo for testing remove - /*f ( ( DG_MODE_DRAI == getCurrentOperationMode() ) || ( DG_MODE_GENE == getCurrentOperationMode() ) ) { heatersStatus[ heater ].targetTemp = MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE; @@ -470,27 +469,34 @@ *************************************************************************/ static HEATERS_STATE_T handleHeaterStateRampToTarget( DG_HEATERS_T heater ) { + F32 dutyCycle; + HEATERS_STATE_T state = HEATER_EXEC_STATE_RAMP_TO_TARGET; - TEMPERATURE_SENSORS_T sensor = heatersStatus[ heater ].feedbackSensor; - F32 inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_HEAT_DISINFECT ); - F32 feedbackTemperature = getTemperatureValue( (U32)sensor ); - F32 targetFlow = getTargetROPumpFlowRate(); - // Continuously get the target temperature in case it was changed dynamically - F32 targetTemperature = heatersStatus[ heater ].originalTargetTemp; - BOOL hasFlowChanged = ( fabs( targetFlow - heatersStatus[ heater ].targetROFlow ) > NEARLY_ZERO ? TRUE : FALSE ); - F32 dutyCycle = heatersStatus[ heater ].dutycycle; - // Set the hand off flag to false - BOOL isItHandOffTime = FALSE; + F32 inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_HEAT_DISINFECT ); + F32 feedbackTemperature = getTemperatureValue( (U32)heatersStatus[ heater ].feedbackSensor ); + F32 targetFlow = getTargetROPumpFlowRate(); + BOOL isItHandOffTime = FALSE; - // TODO remve this code if ( DG_MODE_FILL == getCurrentOperationMode() ) { - dutyCycle = calculateHeaterDutyCycle( 39.0, inletTemperature, 0.8 ); - heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; + F32 flow; + F32 targetTemperature = heatersStatus[ heater ].originalTargetTemp; + + if ( TRUE == heatersStatus[ heater ].isThisFirstFill ) + { + flow = targetFlow; + heatersStatus[ heater ].isThisFirstFill = FALSE; + } + + //dutyCycle = calculatePrimaryHeaterDutyCycle( 39.0, inletTemperature, 0.8 ); + //heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; } + // TODO For testing only remove + dutyCycle = calculatePrimaryHeaterDutyCycle( 39.0, inletTemperature, 0.8 ); + heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; + // TODO for testing only remove isItHandOffTime = TRUE; - // TODO remove this code /*if ( heatersStatus[ heater ].initialDutyCycle - 0.0 < NEARLY_ZERO ) @@ -586,7 +592,7 @@ if ( TRUE == isItHandOffTime ) { - //setHeaterDutyCycle( heater, dutyCycle ); + setHeaterDutyCycle( heater, dutyCycle ); //heatersStatus[ heater ].initialDutyCycle = dutyCycle; //TODO do we need this? @@ -688,23 +694,21 @@ /*********************************************************************//** * @brief - * The calculateHeaterDutyCycle function calculates a heater's duty cycle - * by providing the + * The calculatePrimaryHeaterDutyCycle function calculates the primary + * heater's duty cycle. * @details Inputs: none * @details Outputs: none * @param targetTemperature target temperature of the heater * @oaram currentTemperature current inlet temperature of the heater * @param flow current flow * @return calculated duty cycle *************************************************************************/ -static F32 calculateHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow ) +static F32 calculatePrimaryHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow ) { - // The power is proportional to square root of deltaT x flow - F32 power = sqrt( fabs( targetTemperature - currentTemperature ) * flow ); + // Duty cycle = ( 69.73 * flow rate * deltaT / primary heater maximum power ) ^ 1/2 + F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * + fabs( targetTemperature - currentTemperature ) * flow ) / PRIMARY_HEATERS_MAXIMUM_POWER_WATTS ); - // PWM = ( power * A - B ) - F32 dutyCycle = ( ( power * PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_SLOPE ) - PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_INTERCEPT ); - // Check the boundaries of the calculated duty cycle dutyCycle = ( dutyCycle > HEATERS_MAX_DUTY_CYCLE ? HEATERS_MAX_DUTY_CYCLE : dutyCycle ); dutyCycle = ( dutyCycle < HEATERS_MIN_DUTY_CYCLE ? HEATERS_MIN_DUTY_CYCLE : dutyCycle ); Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -rd3819286869611f9c02add72a0f8e321598fdf42 -r2c4dfa08ac8ead07939b4f6aba3b0073e0997706 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision d3819286869611f9c02add72a0f8e321598fdf42) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 2c4dfa08ac8ead07939b4f6aba3b0073e0997706) @@ -748,6 +748,8 @@ roPumpPWMDutyCyclePct = roPumpOpenLoopTargetDutyCycle; roPumpDutyCyclePctSet = roPumpPWMDutyCyclePct; roPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; + + setROPumpControlSignalDutyCycle( roPumpOpenLoopTargetDutyCycle ); // TODO remove } /*********************************************************************//** @@ -1008,7 +1010,7 @@ { BOOL result = FALSE; - if ( TRUE == isTestingActivated() ) + //if ( TRUE == isTestingActivated() ) TODO uncomment { // Check if duty cycle is within range if ( value >= MIN_RO_PUMP_DUTY_CYCLE && value <= MAX_RO_PUMP_DUTY_CYCLE ) Index: firmware/App/Modes/ModeDrain.c =================================================================== diff -u -r54e58f64179ea382d2e2c403c8c3b9a15a612636 -r2c4dfa08ac8ead07939b4f6aba3b0073e0997706 --- firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 54e58f64179ea382d2e2c403c8c3b9a15a612636) +++ firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 2c4dfa08ac8ead07939b4f6aba3b0073e0997706) @@ -98,7 +98,7 @@ // NOTE: The target flow rate should be set prior to setting the start primary heater // because the initial guess in the heaters driver needs the target flow to calculate // the new PWMs for the main and small primary heaters - setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + //setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); startHeater( DG_PRIMARY_HEATER ); } Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -rd74b98a3b101ec827cc7da59dd617df9435d79e3 -r2c4dfa08ac8ead07939b4f6aba3b0073e0997706 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision d74b98a3b101ec827cc7da59dd617df9435d79e3) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 2c4dfa08ac8ead07939b4f6aba3b0073e0997706) @@ -146,7 +146,7 @@ // NOTE: The target flow rate should be set prior to setting the start primary heater // because the initial guess in the heaters driver needs the target flow to calculate // the new PWMs for the main and small primary heaters - setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + //setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); startHeater( DG_PRIMARY_HEATER ); } Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -raf83481e7313ed6b624e1a8ed8996a906177ad6d -r2c4dfa08ac8ead07939b4f6aba3b0073e0997706 --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision af83481e7313ed6b624e1a8ed8996a906177ad6d) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 2c4dfa08ac8ead07939b4f6aba3b0073e0997706) @@ -402,6 +402,10 @@ setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setROPumpTargetFlowRate( FINAL_DRAIN_RO_PUMP_FLOW_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + // Turn on the UV reactors + turnOnUVReactor( INLET_UV_REACTOR ); + turnOnUVReactor( OUTLET_UV_REACTOR ); + flushUIState = FLUSH_UI_STATE_FLUSH_RECIRCULATION_PATH; state = DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE; } @@ -643,8 +647,14 @@ { signalROPumpHardStop(); setValveState( VRD1, VALVE_STATE_OPEN ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + // Turn off the UV reactors prior to transitioning to drain states. + // In the drain states, there is not fluid flowing in the RO section so the reactors are turned off + turnOffUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); + stateTimerStart = getMSTimerCount(); isThisInitialDrain = FALSE; rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; Index: firmware/App/Modes/ModeGenIdle.c =================================================================== diff -u -rd74b98a3b101ec827cc7da59dd617df9435d79e3 -r2c4dfa08ac8ead07939b4f6aba3b0073e0997706 --- firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision d74b98a3b101ec827cc7da59dd617df9435d79e3) +++ firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 2c4dfa08ac8ead07939b4f6aba3b0073e0997706) @@ -108,8 +108,10 @@ // NOTE: The target flow rate should be set prior to setting the start primary heater // because the initial guess in the heaters driver needs the target flow to calculate // the new PWMs for the main and small primary heaters - setROPumpTargetFlowRate( TARGET_FLUSH_LINES_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + //setROPumpTargetFlowRate( TARGET_FLUSH_LINES_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + testSetTargetDutyCycle( 0.55 ); + setHeaterTargetTemperature( DG_PRIMARY_HEATER, 39.0 ); // TODO remove this line. It comes form HD startHeater( DG_PRIMARY_HEATER ); } @@ -216,7 +218,7 @@ if ( flushLinesVolumeL >= getFlushLineVolume() ) { //setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); TODO remove - setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + //setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); result = DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; } Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r54e58f64179ea382d2e2c403c8c3b9a15a612636 -r2c4dfa08ac8ead07939b4f6aba3b0073e0997706 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 54e58f64179ea382d2e2c403c8c3b9a15a612636) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 2c4dfa08ac8ead07939b4f6aba3b0073e0997706) @@ -1117,23 +1117,23 @@ break; case MSG_ID_TEMPERATURE_SENSORS_VALUE_OVERRIDE: - handleTestTemperatureSensorsOverrideRequest ( message ); + handleTestTemperatureSensorsOverrideRequest( message ); break; case MSG_ID_TEMPERATURE_SENSORS_PUBLISH_INTERVAL_OVERRIDE: - handleTestTemperatureSensorsDataPublishOverrideRequest ( message ); + handleTestTemperatureSensorsDataPublishOverrideRequest( message ); break; case MSG_ID_HEATERS_PUBLISH_INTERVAL_ORVERRIDE: - handleTestHeatersDataPublishOverrideRequest ( message ); + handleTestHeatersDataPublishOverrideRequest( message ); break; case MSG_ID_CONDUCTIVITY_OVERRIDE: - handleTestSetConductivityOverrideRequest ( message ); + handleTestSetConductivityOverrideRequest( message ); break; case MSG_ID_CONDUCTIVITY_PUBLISH_INTERVAL_OVERRIDE: - handleTestSetConductivityDataPublishIntervalOverrideRequest ( message ); + handleTestSetConductivityDataPublishIntervalOverrideRequest( message ); break; case MSG_ID_DG_ACCEL_OVERRIDE: