Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -ra43996d4383527a14cffe8bc676cccc6bd93c174 -r740929e7f04220e1a74e1a6f8ce71129f40a7be1 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision a43996d4383527a14cffe8bc676cccc6bd93c174) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 740929e7f04220e1a74e1a6f8ce71129f40a7be1) @@ -7,8 +7,8 @@ * * @file Heaters.c * -* @author (last) Bill Bracken -* @date (last) 22-Aug-2022 +* @author (last) Dara Navaei +* @date (last) 21-Sep-2022 * * @author (original) Dara Navaei * @date (original) 23-Apr-2020 @@ -23,6 +23,7 @@ #include "AlarmMgmt.h" #include "DGDefs.h" #include "FlowSensors.h" +#include "FPGA.h" #include "Heaters.h" #include "MessageSupport.h" #include "ModeFill.h" @@ -48,7 +49,8 @@ #define HEATERS_MAX_DUTY_CYCLE 1.00F ///< Heaters max duty cycle (100%). #define HEATERS_MIN_DUTY_CYCLE 0.00F ///< Heaters minimum duty cycle (0.00%). -#define HEATERS_MIN_HEAT_DISINFECT_DUTY_CYCLE 0.6F ///< Heaters minimum duty cycle during heat disinfect. +#define HEATERS_DISINFECT_DUTY_CYCLE 0.70F ///< Heaters disinfect cycle. +#define HEATERS_DISINFECT_TEMPERATURE_DRIFT_C 3.0F ///< Heaters disinfect temperature drift in C. #define HEATERS_MIN_EST_GAIN 0.2F ///< Heaters minimum estimation gain. #define HEATERS_MAX_EST_GAIN 5.0F ///< Heaters maximum estimation gain. #define HEATERS_NEUTRAL_EST_GAIN 1.0F ///< Heaters neutral estimation gain. @@ -63,29 +65,20 @@ #define HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Heaters voltage out of range time out in milliseconds. #define HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL 0.2F ///< Heaters max voltage out of range tolerance. #define TRIMMER_HEATER_MAX_POWER_W 66.5F ///< Trimmer heater maximum power in Watts. -#define TRIMMER_HEATER_CONTROL_CHECK_INTERVAL_COUNT ( ( 30 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Trimmer heater control interval count. +#define HEATER_CONTROL_CHECK_INTERVAL_COUNT ( ( 30 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Heater control interval count. #define DELTA_TEMPERATURE_TIME_COSNTANT_C 8.6F ///< Delta temperature calculated from time constant. #define PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C 0.015F ///< Primary heaters duty cycle per temperature in C. #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. #define MIN_RO_HEATER_FLOWRATE_LPM 0.2F ///< Minimum target RO heater flow rate in L/min. +#define PRIMARY_HEATER_POWER_TOL 0.1F ///< Primary heater power tolerance. +#define MAIN_PIMARY_HEATER_VOLTAGE_ADC_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Main primary heater voltage ADC FPGA error. 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.5F; ///< Primary heaters maximum power (main primary = 475W and small primary = 237.5W). static const F32 HEATERS_VOLTAGE_TOLERANCE_V = HEATERS_MAX_OPERATING_VOLTAGE_V * HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL; ///< Heaters voltage tolerance in volts. +static const F32 PRIMARY_HEATER_VOLTAGE_TOLERANCE_V = HEATERS_MAX_OPERATING_VOLTAGE_V * PRIMARY_HEATER_POWER_TOL; ///< Primary heater power voltage tolerance in volts. -/// Heaters exec states -typedef enum Heaters_Exec_States -{ - HEATER_EXEC_STATE_OFF = 0, ///< Heater exec state off. - HEATER_EXEC_STATE_PRIMARY_RAMP_TO_TARGET, ///< Heater exec state primary ramp to target. - HEATER_EXEC_STATE_PRIMARY_CONTROL_TO_TARGET, ///< Heater exec state primary control to target. - HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET, ///< Heater exec state control to disinfect (heat or chemical) target. - HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET, ///< Heater exec state trimmer ramp to target. - HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET, ///< Heater exec state trimmer control to target. - NUM_OF_HEATERS_STATE, ///< Number of heaters state. -} HEATERS_STATE_T; - /// Heaters data structure typedef struct { @@ -104,7 +97,7 @@ static HEATER_STATUS_T heatersStatus[ NUM_OF_DG_HEATERS ]; ///< Heaters status. static U32 dataPublicationTimerCounter; ///< Data publication timer counter. -static U32 trimmerHeaterControlCounter; ///< Trimmer heater control counter. +static U32 heaterControlCounter; ///< Heater control counter. static OVERRIDE_U32_T heatersDataPublishInterval = { HEATERS_DATA_PUBLISH_INTERVAL, HEATERS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Heaters data publish time interval. // ********** private function prototypes ********** @@ -140,16 +133,16 @@ { DG_HEATERS_T heater; dataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - trimmerHeaterControlCounter = 0; + heaterControlCounter = 0; for ( heater = DG_PRIMARY_HEATER; heater < NUM_OF_DG_HEATERS; heater++ ) { - heatersStatus[ heater ].targetTemp = 0.0; + heatersStatus[ heater ].targetTemp = 0.0F; heatersStatus[ heater ].state = HEATER_EXEC_STATE_OFF; heatersStatus[ heater ].startHeaterSignal = FALSE; heatersStatus[ heater ].isHeaterOn = FALSE; - heatersStatus[ heater ].dutyCycle = 0.0; - heatersStatus[ heater ].targetFlow = 0.0; + heatersStatus[ heater ].dutyCycle = 0.0F; + heatersStatus[ heater ].targetFlow = 0.0F; heatersStatus[ heater ].hasTargetTempChanged = FALSE; heatersStatus[ heater ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; heatersStatus[ heater ].hasTargetBeenReached = FALSE; @@ -159,8 +152,13 @@ initPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_PRIMARY_HEATER_POWER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_RO_FLOW_TOO_LOW_WHILE_PRIMARY_HEATER_IS_ON, HEATERS_ON_NO_FLOW_TIMEOUT_MS, HEATERS_ON_NO_FLOW_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_TOO_LOW_WHILE_TRIMMER_HEATER_IS_ON, HEATERS_ON_NO_FLOW_TIMEOUT_MS, HEATERS_ON_NO_FLOW_TIMEOUT_MS ); + + // Initialize the FPGA persistent alarm + initFPGAPersistentAlarm( FPGA_PERS_ERROR_MAIN_PRIMARY_HEATER_VOLTAGE_ADC, ALARM_ID_DG_MAIN_PRIMARY_HEATER_FPGA_FAULT, + MAIN_PIMARY_HEATER_VOLTAGE_ADC_FPGA_ERROR_TIMEOUT_MS, MAIN_PIMARY_HEATER_VOLTAGE_ADC_FPGA_ERROR_TIMEOUT_MS ); } /*********************************************************************//** @@ -226,9 +224,17 @@ { if ( HEATER_EXEC_STATE_OFF == heatersStatus[ heater ].state ) { - status = TRUE; heatersStatus[ heater ].startHeaterSignal = TRUE; + status = TRUE; } + +#ifndef _RELEASE_ + if ( ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_TRIMMER_HEATER ) ) && ( DG_TRIMMER_HEATER == heater ) ) + { + heatersStatus[ heater ].startHeaterSignal = FALSE; + status = FALSE; + } +#endif } else { @@ -330,15 +336,15 @@ if ( TRUE == heatersStatus[ heater ].isHeaterOn ) { ALARM_ID_T alarm; - F32 measFlow; - F32 minFlow; - BOOL isFlowLow; + F32 measFlow = 0.0F; + F32 minFlow = 0.0F; + BOOL isFlowLow = FALSE; if ( DG_PRIMARY_HEATER == heater ) { alarm = ALARM_ID_RO_FLOW_TOO_LOW_WHILE_PRIMARY_HEATER_IS_ON; measFlow = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); - minFlow = MIN_RO_FLOWRATE_LPM; + minFlow = MIN_RO_HEATER_FLOWRATE_LPM; } else { @@ -353,8 +359,14 @@ } else { - checkPersistentAlarm( ALARM_ID_RO_FLOW_TOO_LOW_WHILE_PRIMARY_HEATER_IS_ON, FALSE, 0.0, 0.0 ); - checkPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_TOO_LOW_WHILE_TRIMMER_HEATER_IS_ON, FALSE, 0.0, 0.0 ); + if ( DG_PRIMARY_HEATER == heater ) + { + checkPersistentAlarm( ALARM_ID_RO_FLOW_TOO_LOW_WHILE_PRIMARY_HEATER_IS_ON, FALSE, 0.0F, 0.0F ); + } + else + { + checkPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_TOO_LOW_WHILE_TRIMMER_HEATER_IS_ON, FALSE, 0.0F, 0.0F ); + } } } @@ -442,7 +454,7 @@ heatersStatus[ heater ].startHeaterSignal = FALSE; // Depending on which heater is called, go to different states - state = ( heater == DG_PRIMARY_HEATER ? HEATER_EXEC_STATE_PRIMARY_RAMP_TO_TARGET : HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET ); + state = ( DG_PRIMARY_HEATER == heater ? HEATER_EXEC_STATE_PRIMARY_RAMP_TO_TARGET : HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET ); } return state; @@ -461,15 +473,15 @@ HEATERS_STATE_T state = HEATER_EXEC_STATE_PRIMARY_RAMP_TO_TARGET; DG_HEATERS_T heater = DG_PRIMARY_HEATER; F32 inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_HEAT_DISINFECT ); - F32 targetFlow = 0.0; - F32 dutyCycle = 0.0; + F32 targetFlow = 0.0F; + F32 dutyCycle = 0.0F; F32 targetTemperature = heatersStatus[ heater ].targetTemp; DG_OP_MODE_T opMode = getCurrentOperationMode(); if ( DG_MODE_FILL == opMode ) { // If the previous average fill flow rate is 0, use the nominal target RO flow from the RO pump - targetFlow = ( getAvgFillFlowRateLPM() - 0.0 > NEARLY_ZERO ? getAvgFillFlowRateLPM() : getTargetROPumpFlowRateLPM() ); + targetFlow = ( getAvgFillFlowRateLPM() - 0.0F > NEARLY_ZERO ? getAvgFillFlowRateLPM() : getTargetROPumpFlowRateLPM() ); dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow, TRUE ); state = HEATER_EXEC_STATE_PRIMARY_CONTROL_TO_TARGET; } @@ -490,12 +502,16 @@ } else { - // No other modes are using the heaters - // TODO software fault + // Calculate the energy equation and set the duty cycle + // This is for other modes (i.e. standby or service) + targetFlow = getTargetROPumpFlowRateLPM(); + dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow, FALSE ); + state = HEATER_EXEC_STATE_PRIMARY_CONTROL_TO_TARGET; } - // Update the calculated target temperature + // Update the calculated target temperature and flow heatersStatus[ DG_PRIMARY_HEATER ].calculatedTemperature = targetTemperature; + heatersStatus[ DG_PRIMARY_HEATER ].targetFlow = targetFlow; setHeaterDutyCycle( heater, dutyCycle ); return state; @@ -534,32 +550,24 @@ *************************************************************************/ static HEATERS_STATE_T handleHeaterStateControlToDisinfectTarget( DG_HEATERS_T heater ) { - HEATERS_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; + HEATERS_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; + F32 currentTemperature = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); + F32 targetTemperature = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; - F32 heatDisinfectSensorTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); - - // Check if the heaters control conditions have changed, if yes, switch back to ramp to target - if ( TRUE == haveHeaterControlConditionsChanged( heater ) ) + if ( currentTemperature < targetTemperature ) { - state = HEATER_EXEC_STATE_PRIMARY_RAMP_TO_TARGET; + setHeaterDutyCycle( DG_TRIMMER_HEATER, HEATERS_MAX_DUTY_CYCLE ); + setHeaterDutyCycle( DG_PRIMARY_HEATER, HEATERS_MAX_DUTY_CYCLE ); } - - // If the heat disinfect sensor indicates that the temperature is below target temperature but the target temperature had been reached - // before turn on the heaters with 100% power - if ( ( heatDisinfectSensorTemp <= heatersStatus[ heater ].targetTemp ) && ( TRUE == heatersStatus[ heater ].hasTargetBeenReached ) ) + else if ( currentTemperature - targetTemperature < HEATERS_DISINFECT_TEMPERATURE_DRIFT_C ) { - heatersStatus[ heater ].hasTargetBeenReached = FALSE; - setHeaterDutyCycle( heater, HEATERS_MAX_DUTY_CYCLE ); + setHeaterDutyCycle( DG_TRIMMER_HEATER, HEATERS_DISINFECT_DUTY_CYCLE ); + setHeaterDutyCycle( DG_PRIMARY_HEATER, HEATERS_DISINFECT_DUTY_CYCLE ); } - - // If we have reached to target temperature, turn off the heaters - if ( heatDisinfectSensorTemp > heatersStatus[ heater ].targetTemp ) + else { - // Set the flag to true for the next run - heatersStatus[ heater ].hasTargetBeenReached = TRUE; - // The primary heater are not turned off but it is set to a minimum duty cycle so the temperature is kept - // above the target - setHeaterDutyCycle( heater, HEATERS_MIN_HEAT_DISINFECT_DUTY_CYCLE ); + setHeaterDutyCycle( DG_TRIMMER_HEATER, HEATERS_MIN_DUTY_CYCLE ); + setHeaterDutyCycle( DG_PRIMARY_HEATER, HEATERS_MIN_DUTY_CYCLE ); } return state; @@ -577,9 +585,9 @@ { HEATERS_STATE_T state = HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET; DG_HEATERS_T heater = DG_TRIMMER_HEATER; - F32 currentTemperature = 0.0; + F32 currentTemperature = 0.0F; F32 targetFlowLPM = getTargetDialysateFlowLPM(); - F32 dutyCycle = 0.0; + F32 dutyCycle = 0.0F; F32 targetTemperature = heatersStatus[ heater ].targetTemp; DG_OP_MODE_T opMode = getCurrentOperationMode(); @@ -599,14 +607,20 @@ dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, currentTemperature, targetFlowLPM, FALSE ); state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; } + else + { + // If not any of the above modes, just calculate the energy equation based on TRo + currentTemperature = getTemperatureValue( (U32)TEMPSENSORS_OUTLET_REDUNDANT ); + dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, currentTemperature, targetFlowLPM, TRUE ); + state = HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET; + } // Update the calculated target temperature // Reset the duty cycle since the reservoir has been switched heatersStatus[ heater ].calculatedTemperature = currentTemperature; heatersStatus[ heater ].inactiveRsrvr = getInactiveReservoir(); heatersStatus[ heater ].targetFlow = targetFlowLPM; - heatersStatus[ heater ].dutyCycle = 0.0F; - trimmerHeaterControlCounter = 0; + heaterControlCounter = 0; // Cap the minimum duty cycle. So if it is calculated to negative, set it to 0 dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); @@ -626,23 +640,23 @@ static HEATERS_STATE_T handleHeaterStateTrimmerControlToTarget( void ) { HEATERS_STATE_T state = HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET; - F32 tempDutyCycle = 0.0; + F32 tempDutyCycle = 0.0F; // If the inactive reservoir has changed from the last run transition to ramp state to recalculate the // duty cycle for the next delivery if ( heatersStatus[ DG_TRIMMER_HEATER ].inactiveRsrvr != getInactiveReservoir() ) { state = HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET; } - else if ( ++trimmerHeaterControlCounter > TRIMMER_HEATER_CONTROL_CHECK_INTERVAL_COUNT ) + else if ( ++heaterControlCounter > HEATER_CONTROL_CHECK_INTERVAL_COUNT ) { // When the trimmer heater is on, its duty cycle is adjusted at the control interval. For this control check, // dialysate inlet temperature sensor is used rather than the theoretical calculations. F32 outletRedundantTemperature = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); F32 targetTemperature = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; F32 targetFlowLPM = heatersStatus[ DG_TRIMMER_HEATER ].targetFlow; F32 dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, outletRedundantTemperature, targetFlowLPM, TRUE ); - trimmerHeaterControlCounter = 0; + heaterControlCounter = 0; tempDutyCycle = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle + dutyCycle; tempDutyCycle = MIN( tempDutyCycle, HEATERS_MAX_DUTY_CYCLE ); @@ -665,10 +679,7 @@ *************************************************************************/ static void setHeaterDutyCycle( DG_HEATERS_T heater, F32 pwm ) { - // Check if the requested duty cycle is different from what the heater's duty cycle is. - // If the same duty cycle is requested, then it is not needed to send it again. This is to make sure - // the same duty cycle is not sent to the hardware all the time. - if ( fabs( heatersStatus[ heater ].dutyCycle - pwm ) > NEARLY_ZERO ) + if ( heater < NUM_OF_DG_HEATERS ) { if ( DG_PRIMARY_HEATER == heater ) { @@ -680,9 +691,12 @@ setTrimmerHeaterPWM( pwm ); } - // Updated the heater's information heatersStatus[ heater ].dutyCycle = pwm; } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_INVALID_HEATER_ID_SELECTED, heater ); + } } /*********************************************************************//** @@ -725,15 +739,15 @@ { // Get the primary heater's efficiency and the last fill temperature from the ModeFill F32 heaterEstGain = heatersStatus[ DG_TRIMMER_HEATER ].heaterEstGain; - F32 dutyCycle = 0.0; + F32 dutyCycle = 0.0F; #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_HEATERS_EFFICIENCY ) != SW_CONFIG_ENABLE_VALUE ) #endif { if ( TRUE == checkEfficiency ) { - // TODO Do we need efficiency for the trimmer heater? + // Do nothing right now. Efficiency will be implemented later if needed } } @@ -782,7 +796,15 @@ *************************************************************************/ static void setMainPrimaryHeaterPWM( F32 pwm ) { - etpwmSetCmpA( etpwmREG1, (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); + etpwm_config_reg_t mainPriConfig; + U32 pwmValue = (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ); + + etpwm1GetConfigValue( &mainPriConfig, CurrentValue ); + + if ( mainPriConfig.CONFIG_CMPA != pwmValue ) + { + etpwmSetCmpA( etpwmREG1, pwmValue ); + } } /*********************************************************************//** @@ -795,7 +817,15 @@ *************************************************************************/ static void setSmallPrimaryHeaterPWM( F32 pwm ) { - etpwmSetCmpB( etpwmREG1, (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); + etpwm_config_reg_t smallPriConfig; + U32 pwmValue = (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ); + + etpwm1GetConfigValue( &smallPriConfig, CurrentValue ); + + if ( smallPriConfig.CONFIG_CMPB != pwmValue ) + { + etpwmSetCmpB( etpwmREG1, pwmValue ); + } } /*********************************************************************//** @@ -808,7 +838,15 @@ *************************************************************************/ static void setTrimmerHeaterPWM( F32 pwm ) { - etpwmSetCmpA( etpwmREG3, (U32)( (S32)( ( pwm * (F32)(etpwmREG3->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); + etpwm_config_reg_t trimmerConfig; + U32 pwmValue = (U32)( (S32)( ( pwm * (F32)(etpwmREG3->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ); + + etpwm3GetConfigValue( &trimmerConfig, CurrentValue ); + + if ( trimmerConfig.CONFIG_CMPA != pwmValue ) + { + etpwmSetCmpA( etpwmREG3, pwmValue ); + } } /*********************************************************************//** @@ -825,16 +863,16 @@ { HEATERS_DATA_T data; - data.mainPrimayHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle * 100.0; // The duty cycle of the primary heater is divided into 2 parts and is applied to main // and small primary heaters. So they are always the same. - data.smallPrimaryHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle * 100.0; - data.trimmerHeaterDC = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle * 100.0; + data.mainPrimayHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle * FRACTION_TO_PERCENT_FACTOR; + data.smallPrimaryHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle * FRACTION_TO_PERCENT_FACTOR; + data.trimmerHeaterDC = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle * FRACTION_TO_PERCENT_FACTOR; data.primaryTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; data.trimmerTargetTemp = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; data.primaryHeaterState = heatersStatus[ DG_PRIMARY_HEATER ].state; data.trimmerHeaterState = heatersStatus[ DG_TRIMMER_HEATER ].state; - data.primaryEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain * 100; + data.primaryEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain * FRACTION_TO_PERCENT_FACTOR; data.primaryCalcTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].calculatedTemperature; data.trimmerCalcCurrentTemp = heatersStatus[ DG_TRIMMER_HEATER ].calculatedTemperature; dataPublicationTimerCounter = 0; @@ -852,36 +890,58 @@ *************************************************************************/ static void monitorHeatersVoltage( void ) { - // NOTE: Default to using Primary heater voltage from FPGA - F32 mainPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_PRIM_HTR_GND_V ); -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) - { - // V3 use CPU based value for Primary, same as Secondary - mainPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_SEC_HTR_V ); - } -#endif - F32 smallPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_SEC_HTR_V ); - F32 trimmerVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_TRIM_HTR_V ); + F32 mainPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_MAIN_PRIM_HTR_V ); + F32 smallPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_SMALL_PRIM_HTR_V ); + F32 trimmerVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_TRIM_HTR_V ); // Voltage to PWM is reverse. If PWM = 0 -> V = 24V F32 mainPriDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle; F32 smallPriDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle; F32 trimmerDC = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle; + // The expected voltage is the inverse of the duty cycle F32 mainPriExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0F - mainPriDC ); F32 smallPriExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0F - smallPriDC ); F32 trimmerExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0F - trimmerDC ); - BOOL isMainPriOut = ( fabs( mainPriExpectedVoltage - mainPriVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); - BOOL isSmallPriOut = ( fabs( smallPriExpectedVoltage - smallPriVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); - BOOL isTrimmerOut = ( fabs( trimmerExpectedVoltage - trimmerVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + BOOL isMainPriOut = FALSE; + BOOL isSmallPriOut = FALSE; + BOOL isTrimmerOut = FALSE; +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) + { + // V3 use CPU based value for Primary, same as Secondary + mainPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_SMALL_PRIM_HTR_V ); + } + else +#endif + { + // TODO this is not working on DVT-002 + // If the system is DVT, check the FPGA persistent alarm of the main primary heater's voltage ADC + //checkFPGAPersistentAlarms( FPGA_PERS_ERROR_MAIN_PRIMARY_HEATER_VOLTAGE_ADC, getFPGAHeaterGateADCErrorCount(), getFPGAHeaterGateADCReadCount() ); + } + + isMainPriOut = ( fabs( mainPriExpectedVoltage - mainPriVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + isSmallPriOut = ( fabs( smallPriExpectedVoltage - smallPriVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + isTrimmerOut = ( fabs( trimmerExpectedVoltage - trimmerVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + if ( getCurrentOperationMode() != DG_MODE_INIT ) { checkPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isMainPriOut, mainPriDC, HEATERS_VOLTAGE_TOLERANCE_V ); checkPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isSmallPriOut, smallPriDC, HEATERS_VOLTAGE_TOLERANCE_V ); checkPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, isTrimmerOut, trimmerDC, HEATERS_VOLTAGE_TOLERANCE_V ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE != getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) +#endif + { + // If the system is DVT, check the primary heater's power line voltage + F32 powerMainPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_POWER_PRIM_HTR_V ); + BOOL isPriPowerOut = ( fabs( powerMainPriVoltage - HEATERS_MAX_OPERATING_VOLTAGE_V ) > PRIMARY_HEATER_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + + checkPersistentAlarm( ALARM_ID_DG_PRIMARY_HEATER_POWER_VOLTAGE_OUT_OF_RANGE, isPriPowerOut, powerMainPriVoltage, PRIMARY_HEATER_VOLTAGE_TOLERANCE_V ); + } } }