Index: firmware/App/Controllers/DialysateFlow.c =================================================================== diff -u -r3dd12fb9d032f85126db82ca48812a4652a5b75f -r5c53288436774f0cf6a24132ace29a64a66d619d --- firmware/App/Controllers/DialysateFlow.c (.../DialysateFlow.c) (revision 3dd12fb9d032f85126db82ca48812a4652a5b75f) +++ firmware/App/Controllers/DialysateFlow.c (.../DialysateFlow.c) (revision 5c53288436774f0cf6a24132ace29a64a66d619d) @@ -17,6 +17,7 @@ #include +#include "FlowSensors.h" #include "FPGA.h" #include "NVDataMgmt.h" #include "PersistentAlarm.h" @@ -167,7 +168,7 @@ { DIALYSATE_FLOW_METER_DATA_T dialysateFlowData; - dialysateFlowData.measuredDialysateFlowRate = getMeasuredDialysateFlowRate(); + dialysateFlowData.measuredDialysateFlowRate = getMeasuredFlowRateLPM( DIALYSATE_FLOW_SENSOR ); //getMeasuredDialysateFlowRate(); broadcastData( MSG_ID_DG_DIALYSATE_FLOW_METER_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&dialysateFlowData, sizeof( DIALYSATE_FLOW_METER_DATA_T ) ); dialysateFlowDataPublicationTimerCounter = 0; } Index: firmware/App/Controllers/FlowSensors.c =================================================================== diff -u --- firmware/App/Controllers/FlowSensors.c (revision 0) +++ firmware/App/Controllers/FlowSensors.c (revision 5c53288436774f0cf6a24132ace29a64a66d619d) @@ -0,0 +1,317 @@ + +#include + +#include "ConcentratePumps.h" +#include "FlowSensors.h" +#include "FPGA.h" +#include "NVDataMgmt.h" +#include "PersistentAlarm.h" +#include "SystemCommMessages.h" +#include "TaskPriority.h" +#include "Utilities.h" + +/** + * @addtogroup FlowSensors + * @{ + */ + +// ********** private definitions ********** + +#define FLOW_SENSORS_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the Dialysate flow data is published on the CAN bus. + +#define FLOW_SENSORS_ZERO_READING 0xFFFF // TODO remove ///< Flow sensor reading indicates zero flow (or flow lower than can be detected by sensor). +#define FLOW_SENSORS_EDGES_BUFFER_LENGTH 100 +#define FLOW_SENSORS_PULSES_PER_LITER 110000 // TODO calibration record + +#define FLOW_OUT_OF_RANGE_PERSISTENT_INTERVAL ( 12 * MS_PER_SECOND ) // Why is this so long? ///< Flow out of range time out in counts. +#define DATA_PUBLISH_COUNTER_START_COUNT 20 ///< Data publish counter start count. + +static const F32 FLOW_SENSORS_LITERS_PER_PULSES = ( 1.0 / (F32)FLOW_SENSORS_PULSES_PER_LITER ); + +// ********** private data ********** + +typedef struct +{ + U08 edgeCountsIndex; + U16 edgeCountsBuffer[ FLOW_SENSORS_EDGES_BUFFER_LENGTH ]; + OVERRIDE_F32_T measuredFlowLPM; + OVERRIDE_F32_T measuredROFlowWithCPsLPM; +} FLOW_SENSOR_STATUS_T; + +static U32 dataPublicationCounter; ///< Used to schedule Dialysate flow data publication to CAN bus. +static OVERRIDE_U32_T flowSensorsDataPublishInterval = { FLOW_SENSORS_DATA_PUB_INTERVAL, + FLOW_SENSORS_DATA_PUB_INTERVAL, + 0, 0 }; ///< Interval (in ms) at which to publish Dialysate flow data to CAN bus. +static FLOW_SENSOR_STATUS_T flowSensorStatus[ NUM_OF_FLOW_SENSORS ]; +static DG_FLOW_SENSORS_CAL_RECORD_T flowSensorsCalRecord; ///< Flow sensors calibration record. + +// ********** private function prototypes ********** + +static F32 getCalibrationAppliedFlowLPM( U32 sensorId, F32 flow ); +static void publishFlowSensorsData( void ); + +/*********************************************************************//** + * @brief + * The initFlowSensors function initializes the flow sensors module. + * @details Inputs: none + * @details Outputs: flowSensorStatus, dataPublicationCounter + * @return none + *************************************************************************/ +void initFlowSensors( void ) +{ + U08 i; + + for ( i = 0; i < NUM_OF_FLOW_SENSORS; i++ ) + { + memset( &flowSensorStatus[ i ], 0x0, sizeof( FLOW_SENSOR_STATUS_T ) ); + } + + // Initialize the persistent alarm for flow out of upper and lower range + initPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_RATE_OUT_OF_RANGE, FLOW_OUT_OF_RANGE_PERSISTENT_INTERVAL, FLOW_OUT_OF_RANGE_PERSISTENT_INTERVAL ); + + dataPublicationCounter = DATA_PUBLISH_COUNTER_START_COUNT; +} + +/*********************************************************************//** + * @brief + * The execFlowSensorsSelfTest function executes the flow sensor's self-test. + * @details Inputs: none + * @details Outputs: none + * @return flow sensor self test results (SELF_TEST_STATUS_T) + *************************************************************************/ +SELF_TEST_STATUS_T execFlowSensorsSelfTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + BOOL calStatus = getNVRecord2Driver( GET_CAL_FLOW_SENSORS, (U08*)&flowSensorsCalRecord, sizeof( DG_FLOW_SENSORS_CAL_RECORD_T ), + NUM_OF_CAL_DATA_FLOW_SENSORS, ALARM_ID_DG_DIALYSATE_FLOW_SENSOR_INVALID_CAL_RECORD ); + result = ( TRUE == calStatus ? SELF_TEST_STATUS_PASSED : SELF_TEST_STATUS_FAILED ); + + return result; +} + +/*********************************************************************//** + * @brief + * The execFlowSesnorsMonitor function executes the flow sensors monitor. + * @details Inputs: none + * @details Outputs: flowSensorStatus, flowSensorsCalRecord + * @return none + *************************************************************************/ +void execFlowSesnorsMonitor( void ) +{ + U08 i; + U08 countsIndex; + U16 oldestEdgeCount; + U16 oldest2CurrentEdgeDiff; + F32 flowBeforeCalibrationLPM; + + // Check if a new calibration is available + if ( TRUE == isNewCalibrationRecordAvailable() ) + { + getNVRecord2Driver( GET_CAL_FLOW_SENSORS, (U08*)&flowSensorsCalRecord, sizeof( DG_FLOW_SENSORS_CAL_RECORD_T ), + NUM_OF_CAL_DATA_FLOW_SENSORS, ALARM_ID_DG_DIALYSATE_FLOW_SENSOR_INVALID_CAL_RECORD ); + } + + for ( i = 0; i < NUM_OF_FLOW_SENSORS; i++ ) + { + countsIndex = flowSensorStatus[ i ].edgeCountsIndex; + oldestEdgeCount = flowSensorStatus[ i ].edgeCountsBuffer[ countsIndex ]; + + switch ( i ) + { + case RO_FLOW_SENSOR: + flowSensorStatus[ i ].edgeCountsBuffer[ countsIndex ] = getFPGAROFlowSensorEdgeCount(); + oldest2CurrentEdgeDiff = u16DiffWithWrap( oldestEdgeCount, flowSensorStatus[ i ].edgeCountsBuffer[ countsIndex ] ); + flowBeforeCalibrationLPM = oldest2CurrentEdgeDiff * FLOW_SENSORS_LITERS_PER_PULSES * SEC_PER_MIN; + flowSensorStatus[ i ].measuredROFlowWithCPsLPM.data = getCalibrationAppliedFlowLPM( i, flowBeforeCalibrationLPM ); + flowSensorStatus[ i ].measuredFlowLPM.data = flowSensorStatus[ i ].measuredROFlowWithCPsLPM.data - + ( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) / ML_PER_LITER ) - + ( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) / ML_PER_LITER ); + break; + + case DIALYSATE_FLOW_SENSOR: + flowSensorStatus[ i ].edgeCountsBuffer[ countsIndex ] = getFPGADialysateFlowSensorEdgeCount(); + oldest2CurrentEdgeDiff = u16DiffWithWrap( oldestEdgeCount, flowSensorStatus[ i ].edgeCountsBuffer[ countsIndex ] ); + flowBeforeCalibrationLPM = oldest2CurrentEdgeDiff * FLOW_SENSORS_LITERS_PER_PULSES * SEC_PER_MIN; + flowSensorStatus[ i ].measuredFlowLPM.data = getCalibrationAppliedFlowLPM( i, flowBeforeCalibrationLPM ); + break; + +#ifndef _VECTORCAST_ + default: + // TODO software fault + break; +#endif + } + + flowSensorStatus[ i ].edgeCountsIndex = INC_WRAP( countsIndex, 0, FLOW_SENSORS_EDGES_BUFFER_LENGTH ); + } + + + // TODO dialysate flow alarm. Is it needed? + //currentFlow = getMeasuredDialysateFlowRate(); + //isFlowOutOfUpperRange = ( currentFlow > MAX_DIALYSATE_FLOWRATE_LPM ? TRUE : FALSE ); + //checkPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_RATE_OUT_OF_RANGE, isFlowOutOfUpperRange, currentFlow, MAX_DIALYSATE_FLOWRATE_LPM ); + + publishFlowSensorsData(); +} + +/*********************************************************************//** + * @brief + * The getMeasuredFlowRateLPM function gets the measured flow rate of a flow sensor + * in L/min. + * @details Inputs: flowSensorStatus + * @details Outputs: flowSensorStatus + * @return the current flow rate (in L/min). + *************************************************************************/ +F32 getMeasuredFlowRateLPM( FLOW_SENSORS_T sensorId ) +{ + return getF32OverrideValue( &flowSensorStatus[ sensorId ].measuredFlowLPM ); +} + +/*********************************************************************//** + * @brief + * The publishFlowSensorsData function publishes flow sensors data at + * the set interval. + * @details Inputs: flowSensorsDataPublicationCounter, + * flowSensorsDataPublishInterval + * @details Outputs: flowSensorsDataPublicationCounter + * @return none + *************************************************************************/ +static void publishFlowSensorsData( void ) +{ + // publish dialysate flow meter data on interval + if ( ++dataPublicationCounter >= getU32OverrideValue( &flowSensorsDataPublishInterval ) ) + { + FLOW_SENSORS_DATA_T data; + data.ROFlowRateLPM = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); + data.dialysateFlowRateLPM = getMeasuredFlowRateLPM( DIALYSATE_FLOW_SENSOR ); + data.ROFlowRateWithCPsLPM = getF32OverrideValue( &flowSensorStatus[ RO_FLOW_SENSOR ].measuredROFlowWithCPsLPM ); + dataPublicationCounter = 0; + + broadcastData( MSG_ID_DG_FLOW_SENSORS_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( FLOW_SENSORS_DATA_T ) ); + + } +} + +/*********************************************************************//** + * @brief + * The getCalibrationAppliedFlowLPM function applies the calibration record + * values to the flow. + * @details Inputs: flowSensorsCalRecord + * @details Outputs: none + * @param sensorId which is the flow sensor ID + * @param flow which is the flow in L/min to apply calibration to it + * @return the calibration applied flow value + *************************************************************************/ +static F32 getCalibrationAppliedFlowLPM( U32 sensorId, F32 flow ) +{ + F32 flowAfterCal = pow( flow, 4 ) * flowSensorsCalRecord.flowSensors[ (CAL_DATA_DG_FLOW_SENSORS_T)sensorId ].fourthOrderCoeff + + pow( flow, 3 ) * flowSensorsCalRecord.flowSensors[ (CAL_DATA_DG_FLOW_SENSORS_T)sensorId ].thirdOrderCoeff + + pow( flow, 2 ) * flowSensorsCalRecord.flowSensors[ (CAL_DATA_DG_FLOW_SENSORS_T)sensorId ].secondOrderCoeff + + flow * flowSensorsCalRecord.flowSensors[ (CAL_DATA_DG_FLOW_SENSORS_T)sensorId ].gain + + flowSensorsCalRecord.flowSensors[ (CAL_DATA_DG_FLOW_SENSORS_T)sensorId ].offset; + return flowAfterCal; +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetFlowDataPublishIntervalOverride function overrides the + * flow sensors data publish interval. + * @details Inputs: none + * @details Outputs: flowSensorsDataPublishInterval + * @param: value override flow data publish interval with (in ms) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetFlowDataPublishIntervalOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = value / TASK_PRIORITY_INTERVAL; + flowSensorsDataPublishInterval.ovData = intvl; + flowSensorsDataPublishInterval.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetFlowDataPublishIntervalOverride function resets the + * override of the flow sensors data publish interval. + * @details Inputs: flowSensorsDataPublishInterval + * @details Outputs: flowSensorsDataPublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetFlowDataPublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + flowSensorsDataPublishInterval.override = OVERRIDE_RESET; + flowSensorsDataPublishInterval.ovData = flowSensorsDataPublishInterval.ovInitData; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetMeasuredFlowRateOverride function overrides the measured + * flow rate. + * @details Inputs: none + * @details Outputs: flowSensorStatus + * @param: sensorId the Id of the sensor which its value is overridden. + * @param: value override measured flow rate in LPM + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetMeasuredFlowRateOverride( U32 sensorId, F32 flowLPM ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + flowSensorStatus[ sensorId ].measuredFlowLPM.ovInitData = flowSensorStatus[ sensorId ].measuredFlowLPM.data; + flowSensorStatus[ sensorId ].measuredFlowLPM.ovData = flowLPM; + flowSensorStatus[ sensorId ].measuredFlowLPM.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetMeasuredFlowRateOverride function resets the override + * of the measured flow rate. + * @details Inputs: none + * @details Outputs: flowSensorStatus + * @param: sensorId the Id of the sensor which its value is reset. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetMeasuredFlowRateOverride( U32 sensorId ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + flowSensorStatus[ sensorId ].measuredFlowLPM.data = flowSensorStatus[ sensorId ].measuredFlowLPM.ovInitData; + flowSensorStatus[ sensorId ].measuredFlowLPM.override = OVERRIDE_RESET; + flowSensorStatus[ sensorId ].measuredFlowLPM.ovInitData = 0.0; + flowSensorStatus[ sensorId ].measuredFlowLPM.ovData = 0.0; + result = TRUE; + } + + return result; +} + +/**@}*/ Index: firmware/App/Controllers/FlowSensors.h =================================================================== diff -u --- firmware/App/Controllers/FlowSensors.h (revision 0) +++ firmware/App/Controllers/FlowSensors.h (revision 5c53288436774f0cf6a24132ace29a64a66d619d) @@ -0,0 +1,55 @@ + + +#ifndef _FLOW_SENSORS_H_ +#define _FLOW_SENSORS_H_ + +#include "DGCommon.h" + +/** + * @defgroup FlowSensors + * @brief Dialysate and RO flow rate monitor module. Monitors the flow sensors. + * The flow sensors are manufactured by Swiss Flow, PN: 0045 + * + * @addtogroup FlowSensors + * @{ + */ + +// ********** public definitions ********** +#define MAX_FLOWRATE_LPM 2.00F ///< Maximum target flow rate in L/min. +#define MIN_FLOWRATE_LPM 0.05F ///< Minimum target flow rate in L/min. + +/// Flow meters name +typedef enum +{ + RO_FLOW_SENSOR = 0, ///< RO flow sensor. + DIALYSATE_FLOW_SENSOR, ///< Dialysate flow sensor. + NUM_OF_FLOW_SENSORS, ///< Number of flow sensors. +} FLOW_SENSORS_T; + +/// Flow meters data struct. +typedef struct +{ + F32 ROFlowRateLPM; ///< RO flow rate in L/min. + F32 ROFlowRateWithCPsLPM; ///< RO flow rate with concentrate pumps in L/min. + F32 dialysateFlowRateLPM; ///< Dialysate flow rate L/min. +} FLOW_SENSORS_DATA_T; + +// ********** public function prototypes ********** + +void initFlowSensors( void ); + +SELF_TEST_STATUS_T execFlowSensorsSelfTest( void ); + +void execFlowSesnorsMonitor( void ); + +F32 getMeasuredFlowRateLPM( FLOW_SENSORS_T sensorId ); + +BOOL testSetFlowDataPublishIntervalOverride( U32 value ); +BOOL testResetFlowDataPublishIntervalOverride( void ); + +BOOL testSetMeasuredFlowRateOverride( U32 sensorId, F32 flowLPM ); +BOOL testResetMeasuredFlowRateOverride( U32 sensorId ); + +/**@}*/ + +#endif Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r3dd12fb9d032f85126db82ca48812a4652a5b75f -r5c53288436774f0cf6a24132ace29a64a66d619d --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 3dd12fb9d032f85126db82ca48812a4652a5b75f) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 5c53288436774f0cf6a24132ace29a64a66d619d) @@ -22,6 +22,7 @@ #include "AlarmMgmt.h" #include "DGDefs.h" +#include "FlowSensors.h" #include "Heaters.h" #include "MessageSupport.h" #include "ModeFill.h" @@ -48,8 +49,9 @@ #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_MAX_EFFICIENCY 0.0F ///< Heaters minimum efficiency. -#define HEATERS_MIN_EFFICIENCY 1.0F ///< Heaters maximum efficiency. +#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. #define HEATERS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heaters data publish interval. @@ -93,7 +95,7 @@ F32 dutycycle; ///< Heater duty cycle. F32 targetFlow; ///< Heater target flow. BOOL hasTargetTempChanged; ///< Heater target temperature change flag indicator. - F32 heaterEfficiency; ///< Heater efficiency during the run. + F32 heaterEstGain; ///< Heater estimation gain during the run. BOOL hasTargetBeenReached; ///< Heater flag to indicate whether the target temperature has been reached. F32 calculatedTemperature; ///< Heater calculated temperature. DG_RESERVOIR_ID_T inactiveRsrvr; ///< Heater inactive reservoir. @@ -148,7 +150,7 @@ heatersStatus[ heater ].dutycycle = 0.0; heatersStatus[ heater ].targetFlow = 0.0; heatersStatus[ heater ].hasTargetTempChanged = FALSE; - heatersStatus[ heater ].heaterEfficiency = 1.0; // Assuming 100% efficiency during initialization until it is updated + heatersStatus[ heater ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; heatersStatus[ heater ].hasTargetBeenReached = FALSE; } @@ -333,7 +335,7 @@ { // TODO add the function that gets the flow of the new flow sensor for DG. For now it is assumed that trimmer heater flow sensor // is not 0 so the heater can run if needed - F32 measFlow = ( DG_PRIMARY_HEATER == heater ? getMeasuredROFlowRateLPM() : 50.0 ); + F32 measFlow = ( DG_PRIMARY_HEATER == heater ? getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) /*getMeasuredROFlowRateLPM()*/ : 50.0 ); F32 minFlow = ( DG_PRIMARY_HEATER == heater ? MIN_RO_FLOWRATE_LPM : MIN_RO_FLOWRATE_LPM ); BOOL isFlowLow = ( measFlow < minFlow ? TRUE : FALSE ); @@ -366,8 +368,8 @@ *************************************************************************/ void resetHeatersEfficiency( void ) { - heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency = 1.0; - heatersStatus[ DG_TRIMMER_HEATER ].heaterEfficiency = 1.0; + heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; + heatersStatus[ DG_TRIMMER_HEATER ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; } /*********************************************************************//** @@ -630,44 +632,47 @@ static F32 calculatePrimaryHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ) { // Get the primary heater's efficiency and the last fill temperature from the ModeFill - F32 heaterEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency; + F32 heaterEstGain = heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain; + // Duty cycle = ( 69.73 * flow rate * deltaT / primary heater maximum power ) ^ 1/2 + // Multiply the duty cycle to the heater efficiency + F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * fabs( targetTemperature - currentTemperature ) * flow ) / + PRIMARY_HEATERS_MAXIMUM_POWER_WATTS ); #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_HEATERS_EFFICIENCY ) != SW_CONFIG_ENABLE_VALUE ) #endif { if ( TRUE == checkEfficiency ) { + F32 heaterDutyCycle = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle; F32 lastFillTemperature = getLastFillTemperature(); F32 primaryTargetTemperature = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; + BOOL isTempUnderTarget = ( lastFillTemperature < primaryTargetTemperature ? TRUE : FALSE ); - // If the last fill temperature > target temperature, it means the primary heater overshot the duty cycle - // so with its efficiency is toned down for the next fill cycle - // If the heater under-shoots the duty cycle, the efficiency increases the duty cycle for the next fill cycle - if ( lastFillTemperature - primaryTargetTemperature < NEARLY_ZERO ) + if ( TRUE == isTempUnderTarget ) { - heaterEfficiency -= ( lastFillTemperature - primaryTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + if ( heaterDutyCycle < HEATERS_MAX_DUTY_CYCLE ) + { + heaterEstGain += ( primaryTargetTemperature - lastFillTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + } } else { - heaterEfficiency += ( primaryTargetTemperature - lastFillTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + if ( heaterDutyCycle > HEATERS_MIN_DUTY_CYCLE ) + { + heaterEstGain -= ( lastFillTemperature - primaryTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + } } - // Check the heater's efficiency to make sure it is in between 0 and 1 (0 to 100%) - heaterEfficiency = MIN( heaterEfficiency, HEATERS_MAX_EFFICIENCY ); - heaterEfficiency = MAX( heaterEfficiency, HEATERS_MIN_EFFICIENCY ); - - // Update the heaters efficiency - heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency = heaterEfficiency; + heaterEstGain = MAX( heaterEstGain, HEATERS_MIN_EST_GAIN ); + heaterEstGain = MIN( heaterEstGain, HEATERS_MAX_EST_GAIN ); + heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain = heaterEstGain; } } - // Duty cycle = ( 69.73 * flow rate * deltaT / primary heater maximum power ) ^ 1/2 - // Multiply the duty cycle to the heater efficiency - F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * fabs( targetTemperature - currentTemperature ) * flow ) / PRIMARY_HEATERS_MAXIMUM_POWER_WATTS ); - dutyCycle = ( heaterEfficiency > NEARLY_ZERO ? dutyCycle * heaterEfficiency : dutyCycle ); - dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); - dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); + dutyCycle *= heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain; + dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); + dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); return dutyCycle; } @@ -688,7 +693,7 @@ static F32 calculateTrimmerHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ) { // Get the primary heater's efficiency and the last fill temperature from the ModeFill - F32 heaterEfficiency = heatersStatus[ DG_TRIMMER_HEATER ].heaterEfficiency; + F32 heaterEfficiency = heatersStatus[ DG_TRIMMER_HEATER ].heaterEstGain; F32 dutyCycle = 0.0; #ifndef _RELEASE_ @@ -800,7 +805,7 @@ 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 ].heaterEfficiency * 100; + data.primaryEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain * 100; data.primaryCalcTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].calculatedTemperature; data.trimmerCalcCurrentTemp = heatersStatus[ DG_TRIMMER_HEATER ].calculatedTemperature; broadcastData( MSG_ID_DG_HEATERS_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( HEATERS_DATA_T ) ); Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r3dd12fb9d032f85126db82ca48812a4652a5b75f -r5c53288436774f0cf6a24132ace29a64a66d619d --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 3dd12fb9d032f85126db82ca48812a4652a5b75f) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 5c53288436774f0cf6a24132ace29a64a66d619d) @@ -21,6 +21,7 @@ #include "mibspi.h" #include "ConcentratePumps.h" +#include "FlowSensors.h" #include "FPGA.h" #include "InternalADC.h" #include "NVDataMgmt.h" @@ -649,7 +650,7 @@ // Get the current pressure from the sensor F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); F32 targetFlowRate = getTargetROPumpFlowRateLPM(); - F32 actualFlowRate = (F32)getMeasuredROFlowRateLPM(); + F32 actualFlowRate = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); //(F32)getMeasuredROFlowRateLPM(); F32 flowRateDeviation = fabs( targetFlowRate - actualFlowRate ) / targetFlowRate; BOOL isFlowOutOfRange = flowRateDeviation > ROP_FLOW_TARGET_TOLERANCE; F32 targetPressure = getTargetROPumpPressure(); @@ -713,7 +714,7 @@ } else { - roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, getTargetROPumpFlowRateLPM(), getMeasuredROFlowRateLPM() ); + roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, getTargetROPumpFlowRateLPM(), getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) /*getMeasuredROFlowRateLPM()*/ ); } setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); @@ -749,7 +750,7 @@ } else { - roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_MAX_PRES, getTargetROPumpFlowRateLPM(), getMeasuredROFlowRateLPM() ); + roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_MAX_PRES, getTargetROPumpFlowRateLPM(), getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) /*getMeasuredROFlowRateLPM()*/ ); } setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); @@ -846,10 +847,9 @@ if ( ++roPumpDataPublicationTimerCounter >= getU32OverrideValue( &roPumpDataPublishInterval ) ) { RO_PUMP_DATA_T pumpData; - pumpData.roPumpTgtFlowRateLM = getTargetROPumpFlowRateLPM(); pumpData.roPumpTgtPressure = getTargetROPumpPressure(); - pumpData.measROFlowRate = getMeasuredROFlowRateLPM(); + pumpData.measROFlowRate = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); //getMeasuredROFlowRateLPM(); pumpData.roPumpDutyCycle = roPumpDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; pumpData.roPumpState = (U32)roPumpState; pumpData.roPumpFBDutyCycle = roPumpFeedbackDutyCyclePct * FRACTION_TO_PERCENT_FACTOR; Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -r544e9782a1b8d444224f41efef38a5204c262722 -r5c53288436774f0cf6a24132ace29a64a66d619d --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 544e9782a1b8d444224f41efef38a5204c262722) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 5c53288436774f0cf6a24132ace29a64a66d619d) @@ -1019,7 +1019,7 @@ } } - //checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, isTemperatureOutOfRange, i, temperature ); // TODO DEBUG_DENALI + checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, isTemperatureOutOfRange, i, temperature ); } } Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r3dd12fb9d032f85126db82ca48812a4652a5b75f -r5c53288436774f0cf6a24132ace29a64a66d619d --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 3dd12fb9d032f85126db82ca48812a4652a5b75f) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 5c53288436774f0cf6a24132ace29a64a66d619d) @@ -83,8 +83,9 @@ #define FPGA_FLUIDLEAK_STATE_MASK 0x0004 ///< Bit mask for fluid leak detector. -#define CONCENTRATE_CAP_SWITCH_MASK 0x10 ///< Concentrate cap switch bit mask -#define DIALYSATE_CAP_SWITCH_MASK 0x20 ///< Dialysate cap switch bit mask.. +#define CONCENTRATE_CAP_SWITCH_MASK 0x10 ///< Concentrate cap switch bit mask. +#define DIALYSATE_CAP_SWITCH_MASK 0x20 ///< Dialysate cap switch bit mask. +#define FPGA_THD_CONTROL_COMMAND 0X01 ///< FPGA THd control command. #define FPGA_POWER_OUT_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< FPGA power out timeout in milliseconds. #define FPGA_GPIO_POWER_STATUS_PIN 7 ///< FPGA GPIO power status pin. #define FPGA_READ_V3_START_BYTE_NUM 256 ///< FPGA V3 read sensors start byte number. @@ -196,8 +197,8 @@ U16 fpgaADCVccAux; ///< Reg 408. Internal FPGA Vcc auxiliary voltage U16 fpgaADCVPVN; ///< Reg 410. Internal FPGA VPVN voltage U16 fpgaDialysateFlowRate; ///< Reg 412. Dialysate flow rate measurement - U16 fpgaROFlowRateCount; ///< Reg 414. RO flow rate count - U16 fpgaDialysateFlowRateCount; ///< Reg 416. Dialysate flow rate count + U16 fpgaROFlowSensorEdgeCount; ///< Reg 414. RO flow sensor edge count + U16 fpgaDialysateFlowSensorEdgeCount; ///< Reg 416. Dialysate flow sensor edge count // DVT changes U16 fpgaDrainPumpSpeedFeedback; ///< Reg 418. Drain pump speed feedback @@ -367,6 +368,9 @@ memset( &fpgaSensorReadings, 0, sizeof(DG_FPGA_SENSORS_T) ); memset( &fpgaActuatorSetPoints, 0, sizeof(FPGA_ACTUATORS_T) ); + // Set the THd control register to 0x1 to make sure its ADC is running + fpgaActuatorSetPoints.fpgaTHdControlReg = FPGA_THD_CONTROL_COMMAND; + // TODO Remove the below line // Initialize the valves fpgaActuatorSetPoints.fpgaValveStates = 0x015F; @@ -2291,4 +2295,30 @@ return fpgaSensorReadings.fpgaTHdRTDErrorCount; } +/*********************************************************************//** + * @brief + * The getFPGAROFlowSensorEdgeCount function gets the FPGA RO flow sensor + * edge count. + * @details Inputs: fpgaSensorReadings.fpgaROFlowSensorEdgeCount + * @details Outputs: none + * @return RO flow sensor edge count + *************************************************************************/ +U16 getFPGAROFlowSensorEdgeCount( void ) +{ + return fpgaSensorReadings.fpgaROFlowSensorEdgeCount; +} + +/*********************************************************************//** + * @brief + * The getFPGADialysateFlowSensorEdgeCount function gets the FPGA dialysate + * flow sensor edge count + * @details Inputs: fpgaSensorReadings.fpgaDialysateFlowSensorEdgeCount + * @details Outputs: none + * @return Dialysate flow sensor edge count + *************************************************************************/ +U16 getFPGADialysateFlowSensorEdgeCount( void ) +{ + return fpgaSensorReadings.fpgaDialysateFlowSensorEdgeCount; +} + /**@}*/ Index: firmware/App/Services/FPGA.h =================================================================== diff -u -r544e9782a1b8d444224f41efef38a5204c262722 -r5c53288436774f0cf6a24132ace29a64a66d619d --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision 544e9782a1b8d444224f41efef38a5204c262722) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision 5c53288436774f0cf6a24132ace29a64a66d619d) @@ -162,6 +162,9 @@ U08 getFPGATHdReadCount( void ); U08 getFPGATHdErrorCount( void ); +U16 getFPGAROFlowSensorEdgeCount( void ); +U16 getFPGADialysateFlowSensorEdgeCount( void ); + /**@}*/ #endif Index: firmware/App/Tasks/TaskPriority.c =================================================================== diff -u -r224b86c0847207c168d38fa1713a1e9116642267 -r5c53288436774f0cf6a24132ace29a64a66d619d --- firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision 224b86c0847207c168d38fa1713a1e9116642267) +++ firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision 5c53288436774f0cf6a24132ace29a64a66d619d) @@ -20,6 +20,7 @@ #include "Accel.h" #include "ConductivitySensors.h" #include "DrainPump.h" +#include "FlowSensors.h" #include "FluidLeak.h" #include "FPGA.h" #include "Heaters.h" @@ -98,6 +99,8 @@ // Monitor fluid leak detector execFluidLeak(); + execFlowSesnorsMonitor(); + // Second pass for FPGA execFPGAOut(); #endif