Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -rf38051e1882be3e774f10ba924343a6ce1334890 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision f38051e1882be3e774f10ba924343a6ce1334890) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -57,7 +57,6 @@ #define MAXIMUM_TARGET_TEMPERATURE 90.0 ///< Maximum allowed target temperature for the heaters. #define MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE 58.0 ///< Maximum allowed target temperature for the idle and drain modes. -#define HEATERS_RAMP_STATE_CHECK_INTERVAL_COUNT 20U // TODO remove ///< Heaters ramp check interval count. #define HEATERS_CONTROL_STATE_CHECK_INTERVAL_COUNT ( ( 10 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Temperature sensors interval count. #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 170.0 ///< Heaters max allowed internal temperature in C. @@ -70,13 +69,8 @@ #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 // 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_TEMPERATURE_TIME_COSNTANT_C 8.6 ///< Delta temperature calculated from time constant. -#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). @@ -103,6 +97,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. + F32 heaterEfficiency; PI_CONTROLLER_ID_T controllerID; ///< Heater PI controller ID TODO remove this? U32 tempOutOfRangeTimer; ///< Heater temperature out of range timer TODO remove once the mechanical thermal cutoff was implemented @@ -133,6 +128,7 @@ static void checkTrimmerHeaterTempSensors( void ); static void monitorHeatersVoltage( void ); static void checkHeaterOnStatus( DG_HEATERS_T heater ); +static void getHeatersEfficiencyFromRTCRAM(); /*********************************************************************//** * @brief @@ -165,6 +161,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 ].heaterEfficiency = 1.0; // Assuming 100% efficiency until it is updated } // Initialize the PI controller for the trimmer heater @@ -445,128 +442,29 @@ HEATERS_STATE_T state = HEATER_EXEC_STATE_RAMP_TO_TARGET; F32 inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_HEAT_DISINFECT ); F32 targetFlow = 0.0; - F32 targetTemperature = heatersStatus[ heater ].originalTargetTemp; F32 dutyCycle = 0.0; + F32 targetTemperature = heatersStatus[ heater ].originalTargetTemp; + F32 heaterEfficiency = heatersStatus[ heater ].heaterEfficiency; if ( DG_MODE_FILL == getCurrentOperationMode() ) { // Get the previous fill's average flow rate - targetFlow = getAverageFillFlowRate(); - dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow ); + targetFlow = getAvgFillFlowRate(); + dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow ); + // Multiply the duty cycle to the heater efficiency + dutyCycle *= heaterEfficiency; } else if ( ( DG_MODE_GENE == getCurrentOperationMode() ) || ( DG_MODE_DRAI == getCurrentOperationMode() ) ) { + targetTemperature += DELTA_TEMPERATURE_TIME_COSNTANT_C; + // Use target flow rate during Idle and drain targetFlow = getTargetROPumpFlowRate(); + dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow ); } + setHeaterDutyCycle( heater, dutyCycle ); + state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; - - // TODO For testing only remove - //dutyCycle = calculatePrimaryHeaterDutyCycle( 39.0, inletTemperature, 0.8 ); - //heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; - // TODO for testing only remove - - - /*if ( heatersStatus[ heater ].initialDutyCycle - 0.0 < NEARLY_ZERO ) - { - if ( ++heatersStatus[ heater ].controlTimerCounter > HEATERS_RAMP_STATE_CHECK_INTERVAL_COUNT ) - { - U32 i; - F32 slope; - F32 deltaTemperature; - F32 deltaDutyCycle; - F32 revDeltaDutyCycle; - - // Update the temperature data array as well as the next index - U32 currentIndex = heatersStatus[ heater ].previousTempsIndex; - heatersStatus[ heater ].previousTemps[ currentIndex ] = feedbackTemperature; - heatersStatus[ heater ].previousTempsIndex = INC_WRAP( currentIndex, 0, TEMPERATURES_MOVING_AVG_SIZE - 1 ); - - // If the target temperature changed, set it the flag to FALSE. In the ramp state, the target temperature - // change is addressed automatically - if ( TRUE == heatersStatus[ heater ].hasTargetTempChanged ) - { - heatersStatus[ heater ].hasTargetTempChanged = FALSE; // TODO do we need this? - } - - // Calculate the running sum of the temperatures - for ( i = 0; i < TEMPERATURES_MOVING_AVG_SIZE; i++ ) - { - slope += heatersStatus[ heater ].previousTemps[ i ]; - } - - // TODO add comments - if ( ( ( DG_MODE_DRAI == getCurrentOperationMode() ) || ( DG_MODE_GENE == getCurrentOperationMode() ) ) ) - { - targetTemperature = MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE; - } - else if ( ( DG_MODE_FILL == getCurrentOperationMode() ) ) - { - targetFlow = getTargetROPumpFlowRate(); // TODO change this to the moving average flow from fill - } - - slope = slope / (F32)TEMPERATURES_MOVING_AVG_SIZE; - dutyCycle = calculateHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow ); - deltaDutyCycle = ( feedbackTemperature <= targetTemperature ? HEATERS_MAX_DUTY_CYCLE - dutyCycle : dutyCycle ); - - revDeltaDutyCycle = ( deltaDutyCycle - 0.0 < NEARLY_ZERO ? 0.0 : 1.0 / deltaDutyCycle ); - revDeltaDutyCycle = ( revDeltaDutyCycle * DELTA_DUTY_CYCLE_GAIN < HEATERS_MAX_DUTY_CYCLE ? - revDeltaDutyCycle * DELTA_DUTY_CYCLE_GAIN : HEATERS_MAX_DUTY_CYCLE ); - deltaTemperature = ( ( atanf( slope ) * DELTA_TEMPERATURE_GAIN ) / targetFlow ) + revDeltaDutyCycle; - - if ( fabs( targetTemperature - feedbackTemperature ) < deltaTemperature ) - { - if ( TRUE == didTimeout( heatersStatus[ heater ].rampStateStartTime, HEATERS_MIN_RAMP_TIME_MS ) ) - { - isItHandOffTime = TRUE; - } - } - else if ( feedbackTemperature > targetTemperature ) - { - isItHandOffTime = TRUE; - } - - if ( ( TRUE == isItHandOffTime ) && ( DG_MODE_FILL == getCurrentOperationMode() ) ) - { - heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; - } - - heatersStatus[ heater ].controlTimerCounter = 0; - } - } - else - { - if ( ( DG_MODE_FILL == getCurrentOperationMode() ) ) - { - dutyCycle = calculateHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow ); - heatersStatus[ heater ].targetTemp = targetTemperature; - isItHandOffTime = TRUE; - } - else if ( ( ( DG_MODE_DRAI == getCurrentOperationMode() ) || ( DG_MODE_GENE == getCurrentOperationMode() ) ) ) - { - F32 highTempDutyCycle = calculateHeaterDutyCycle( MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE, inletTemperature, targetFlow ); - - dutyCycle = ( dutyCycle < highTempDutyCycle ? dutyCycle : highTempDutyCycle ); - - targetTemperature = ( pow( ( dutyCycle + PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_INTERCEPT ) / PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_SLOPE, 2 ) - / targetFlow ) + feedbackTemperature; - - targetTemperature = ( targetTemperature > MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE ? MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE : targetTemperature ); - heatersStatus[ heater ].targetTemp = targetTemperature; - - isItHandOffTime = TRUE; - } - }*/ - - if ( TRUE /*== isItHandOffTime*/ ) - { - setHeaterDutyCycle( heater, dutyCycle ); - - //heatersStatus[ heater ].initialDutyCycle = dutyCycle; //TODO do we need this? - - state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; - } - if ( FALSE == heatersStatus[ heater ].isHeaterOn ) { setHeaterDutyCycle( heater, HEATERS_MIN_DUTY_CYCLE ); @@ -587,45 +485,15 @@ *************************************************************************/ static HEATERS_STATE_T handleHeaterStateControlToTarget( DG_HEATERS_T heater ) { - F32 dutyCycle; - HEATERS_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; - F32 targetFlow = getTargetROPumpFlowRate(); - BOOL hasFlowChanged = ( fabs( targetFlow - heatersStatus[ heater ].targetROFlow ) > NEARLY_ZERO ? TRUE : FALSE ); - F32 feedbackTemperature = getTemperatureValue( (U32)heatersStatus[ heater ].feedbackSensor ); - F32 targetTemperature = heatersStatus[ heater ].targetTemp; + // TODO do we need any control to maintain the temperature? + if ( TRUE == haveHeaterControlConditionsChanged( heater ) ) { state = HEATER_EXEC_STATE_RAMP_TO_TARGET; } - // Check if it is the control time - /*else if ( ++heatersStatus[ heater ].controlTimerCounter > HEATERS_CONTROL_STATE_CHECK_INTERVAL_COUNT ) - { - dutyCycle = heatersStatus[ heater ].dutycycle; - dutyCycle += ( targetTemperature - feedbackTemperature ) * PRIMARY_HEATER_P_COEFFICIENT * getMeasuredROFlowRate(); - - F32 deltaDutyCycle = dutyCycle - heatersStatus[ heater ].initialDutyCycle; - - if ( ( fabs( deltaDutyCycle ) > HEATERS_CONTROL_TO_TARGET_DUTY_CYCLE_CAP ) && ( deltaDutyCycle < 0.0 ) ) - { - dutyCycle = heatersStatus[ heater ].initialDutyCycle - HEATERS_CONTROL_TO_TARGET_DUTY_CYCLE_CAP; - } - else if ( deltaDutyCycle > HEATERS_CONTROL_TO_TARGET_DUTY_CYCLE_CAP ) - { - dutyCycle = heatersStatus[ heater ].initialDutyCycle + HEATERS_CONTROL_TO_TARGET_DUTY_CYCLE_CAP; - } - - // Cap the duty cycle ranges in case they exceeded the limit - dutyCycle = ( dutyCycle > HEATERS_MAX_DUTY_CYCLE ? HEATERS_MAX_DUTY_CYCLE : dutyCycle ); - dutyCycle = ( dutyCycle < HEATERS_MIN_DUTY_CYCLE ? HEATERS_MIN_DUTY_CYCLE : dutyCycle ); - - setHeaterDutyCycle( heater, dutyCycle ); - - heatersStatus[ heater ].controlTimerCounter = 0; - }*/ - // Check if the heater is requested to be off if ( FALSE == heatersStatus[ heater ].isHeaterOn ) { @@ -696,8 +564,6 @@ *************************************************************************/ static BOOL haveHeaterControlConditionsChanged( DG_HEATERS_T heater ) { - F32 dutyCycle; - BOOL status = FALSE; F32 targetFlow = getTargetROPumpFlowRate(); BOOL hasFlowChanged = ( fabs( targetFlow - heatersStatus[ heater ].targetROFlow ) > NEARLY_ZERO ? TRUE : FALSE ); @@ -710,45 +576,8 @@ // Moving back from control to target to ramp. heatersStatus[ heater ].targetROFlow = targetFlow; heatersStatus[ heater ].hasTargetTempChanged = FALSE; - - // If the new target flow is less than the measured current flow, it means the new target flow is faster so it needs more heat power - //dutyCycle = ( getMeasuredROFlowRate() < heatersStatus[ heater ].targetROFlow ? HEATERS_MAX_DUTY_CYCLE : HEATERS_MIN_DUTY_CYCLE ); - - // Go back to ramp state - //setHeaterDutyCycle( heater, dutyCycle ); - - //setHeaterDutyCycle( heater, 100.00 ); } - /*if ( DG_PRIMARY_HEATER == heater ) - { - // Check if the mode is drain or the mode is gen idle - if ( ( DG_MODE_DRAI == getCurrentOperationMode() ) || ( DG_MODE_GENE == getCurrentOperationMode() ) ) - { - // If the operation mode is not the same as the current operation mode - if ( operationMode != getCurrentOperationMode() ) - { - // Add an offset to the dialysate temperature - operationMode = getCurrentOperationMode(); - //heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp + DRAIN_AND_IDLE_MODE_TARGET_TEMPERATURE_OFFSET; - } - } - else if ( ( DG_MODE_FILL == getCurrentOperationMode() ) && ( operationMode != getCurrentOperationMode() ) ) - { - // If the mode is fill and the operation mode has changed, set the temperature back to the original temperature - operationMode = getCurrentOperationMode(); - heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; - } - - if ( ( getCurrentOperationMode() != DG_MODE_DRAI ) || ( getCurrentOperationMode() != DG_MODE_GENE ) ) - { - if ( TRUE == ( fabs( heatersStatus[ heater ].targetTemp - heatersStatus[ heater ].originalTargetTemp ) > NEARLY_ZERO ) - { - - } - } - }*/ - return status; } Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -r7cd1a0f1b82cde58d1d67bf722deac5c004e1b94 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 7cd1a0f1b82cde58d1d67bf722deac5c004e1b94) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -37,7 +37,6 @@ #define LOAD_CELL_REPORT_PERIOD (100 / TASK_PRIORITY_INTERVAL) ///< Broadcast load cell values message every 100 ms. /// Conversion factor from ADC counts to grams. static const F32 ADC2GRAM = (0.0894 * 1.1338); -#define LOAD_CELL_FILTER_ALPHA 0.05 ///< Alpha factor for the alpha filter used on load cell readings. #define SIZE_OF_SMALL_LOAD_CELL_AVG 100 ///< Small load cell moving average has 100 raw samples @ 10ms intervals (1-second). #define SIZE_OF_LARGE_LOAD_CELL_AVG 40 ///< Large load cell moving average has 40 samples from small filter @ 100ms intervals (4-second). @@ -46,10 +45,12 @@ #define LOAD_CELL_MIN_ALLOWED_WEIGHT_GRAMS 0.0 ///< Load cell minimum allowed weight in grams. #define LOAD_CELL_MAX_ALLOWED_WEIGHT_GRAMS 4500.0 ///< Load cell maximum allowed weight in grams. #define LOAD_CELL_MIN_ALLOWED_WEIGHT_BEFORE_TARE_GRAMS 1600.0 ///< Load cell minimum allowed weight before tare in grams. -#define MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_TARE_GRAMS 300.0 ///< Max allowed extra weight before tare in grams. #define LOAD_CELL_WEIGHT_OUT_RANGE_PERSISTENT_PERIOD_MS (5 * MS_PER_SECOND) ///< Load cell weight out of range persistent period in milliseconds. -#define LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS 60.0 ///< Load cell primary and backup maximum allowed weight drift in grams. #define LOAD_CELL_PRIMARY_BACKUP_MAX_DRIFT_PERSISTENT_PERIOD_MS (5 * MS_PER_SECOND) ///< Load cell primary and backup maximum allowed weight drift persistent period in milliseconds. +#define EMPTY_RESERVOIR_WEIGHT_GRAMS 1600 ///< Reservoirs empty weight in grams. +#define MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_FIRST_TARE_GRAMS 300 ///< Max allowed extra weight before first tare in grams. +#define MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_TARE_GRAMS 60 ///< Max allowed extra weight before tare in grams. +#define LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS 60.0 ///< Load cell primary and backup maximum allowed weight drift in grams. /// Load cell data structure. typedef struct @@ -189,8 +190,16 @@ // Rolling average of last 100 raw samples in small filter for ( ii = 0; ii < NUM_OF_LOAD_CELLS; ++ii ) { - loadcells[ ii ].weight.data = (F32)loadcells[ ii ].rawReading * ADC2GRAM; + F32 loadCell = (F32)loadcells[ ii ].rawReading * ADC2GRAM; + // Apply the calibration factors to the data. + // load_cell_weight = fourth_order_coeff * (load_cell^4) + third_order_coeff * (load_cell^3) + second_order_coeff * (load_cell^2) + gain * load_cell + offset + loadcells[ ii ].weight.data = pow(loadCell, 4) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].fourthOrderCoeff + + pow(loadCell, 3) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].thirdOrderCoeff + + pow(loadCell, 2) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].secondOrderCoeff + + loadCell * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].gain + + loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].offset; + loadcells[ ii ].loadCellVelocity_g_min = ( getLoadCellWeight( (LOAD_CELL_ID_T)ii ) - loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ] ) * (F32)SEC_PER_MIN; @@ -200,14 +209,7 @@ loadcells[ ii ].smallFilterTotal += getLoadCellWeight( (LOAD_CELL_ID_T)ii ); // Calculate the load cell value before applying calibration to it - F32 loadCell = (F32)( loadcells[ ii ].smallFilterTotal / (F64)SIZE_OF_SMALL_LOAD_CELL_AVG ); - // Apply the calibration factors to the data. - // load_cell_weight = fourth_order_coeff * (load_cell^4) + third_order_coeff * (load_cell^3) + second_order_coeff * (load_cell^2) + gain * load_cell + offset - loadcells[ ii ].smallFilteredWeight = pow(loadCell, 4) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].fourthOrderCoeff + - pow(loadCell, 3) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].thirdOrderCoeff + - pow(loadCell, 2) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].secondOrderCoeff + - loadCell * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].gain + - loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].offset; + loadcells[ ii ].smallFilteredWeight = (F32)( loadcells[ ii ].smallFilterTotal / (F64)SIZE_OF_SMALL_LOAD_CELL_AVG ); // Monitor the load cells weight monitorLoadCellsWeightOutOfRange( (LOAD_CELL_ID_T)ii ); @@ -300,8 +302,8 @@ { // For the first tare, the weight of the reservoir should be considered // The current weight of the load cell should not be greater than the weight of the reservoir + the extra weight - F32 deltaWeight = fabs( weight - LOAD_CELL_MIN_ALLOWED_WEIGHT_BEFORE_TARE_GRAMS ); - isWeightOutOfRange = ( deltaWeight > MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_TARE_GRAMS ? TRUE : FALSE ); + F32 deltaWeight = fabs( weight - EMPTY_RESERVOIR_WEIGHT_GRAMS ); + isWeightOutOfRange = ( deltaWeight > MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_FIRST_TARE_GRAMS ? TRUE : FALSE ); } else { Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -rf38051e1882be3e774f10ba924343a6ce1334890 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision f38051e1882be3e774f10ba924343a6ce1334890) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -71,6 +71,8 @@ #define RO_FLOW_ADC_TO_LPM_FACTOR 5555 ///< Conversion factor from ADC counts to LPM (liters/min) for RO flow rate (multiply this by inverse of FPGA reading). #endif +#define RO_FLOW_ADC_TO_LPM_FACTOR_TEMP_REMOVE 5555 + #define ROP_FLOW_TO_PWM_SLOPE 0.1 ///< Slope of flow to PWM line equation. #define ROP_FLOW_TO_PWM_INTERCEPT 0.0 ///< Intercept of flow to PWM line equation. @@ -139,6 +141,12 @@ static U32 flowFilterCounter = 0; ///< Flow filtering counter. static DG_FLOW_SENSORS_CAL_RECORD_T flowSensorsCalRecord; ///< Flow sensors calibration record. +// TODO remove +static S32 temporaryFlowVariableRemove; +static F32 temporaryFlowValueRemove; + +// TODO remove + // ********** private function prototypes ********** static RO_PUMP_STATE_T handleROPumpOffState( void ); @@ -195,6 +203,10 @@ roPumpState = RO_PUMP_OFF_STATE; roPumpControlMode = NUM_OF_PUMP_CONTROL_MODES; isROPumpOn = FALSE; + + + temporaryFlowVariableRemove = 0; + temporaryFlowValueRemove = 0.0; } /*********************************************************************//** @@ -332,6 +344,11 @@ // Update sum for flow average calculation measuredFlowReadingsSum += (S32)roFlowReading; + // TODO remove this code + U16 tempROFlowRemove = getFPGAFMPTemporaryFlow(); + temporaryFlowVariableRemove += (S32)tempROFlowRemove; + // TODO remove this code + // Read the pressure at the sensor. The pump cannot be more that the maximum allowed pressure // to make sure the hardware (especially the ROF) is not damaged. If it is the case, we need to stop immediately F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); @@ -365,6 +382,25 @@ measuredFlowReadingsSum = 0; flowFilterCounter = 0; + + // TODO remove this code after testing + F32 flowTemp = RO_FLOW_ADC_TO_LPM_FACTOR_TEMP_REMOVE / ( (F32)temporaryFlowVariableRemove * FLOW_AVERAGE_MULTIPLIER ); + + temporaryFlowValueRemove = pow(flowTemp, 4) * flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].fourthOrderCoeff + + pow(flowTemp, 3) * flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].thirdOrderCoeff + + pow(flowTemp, 2) * flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].secondOrderCoeff + + flowTemp * flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].gain + + flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].offset; + + // If the flow is less than a certain value, FPGA will return 0xFFFF meaning that + // the flow is 0. + if ( FLOW_SENSOR_ZERO_READING == tempROFlowRemove ) + { + temporaryFlowValueRemove = 0.0; + } + + temporaryFlowVariableRemove = 0; + // TODO remove this code after testing } #ifndef IGNORE_RO_PUMP_MONITOR @@ -839,6 +875,8 @@ pumpData.roPumpDutyCycle = roPumpDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; pumpData.roPumpState = (U32)roPumpState; + pumpData.roPumpTemporaryFlowRateRemove = temporaryFlowValueRemove; + broadcastROPumpData( &pumpData ); roPumpDataPublicationTimerCounter = 0; } Index: firmware/App/Controllers/ROPump.h =================================================================== diff -u -rdf0a0b9ce1414b00b381e516714f9089d8e4ae21 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision df0a0b9ce1414b00b381e516714f9089d8e4ae21) +++ firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -42,6 +42,8 @@ F32 roPumpDutyCycle; ///< RO pump duty cycle. U32 roPumpState; ///< RO pump current state. F32 roPumpTgtFlowRate; ///< RO pump target flow rate. + + F32 roPumpTemporaryFlowRateRemove; } RO_PUMP_DATA_T; // ********** public function prototypes ********** Index: firmware/App/DGCommon.h =================================================================== diff -u -rf38051e1882be3e774f10ba924343a6ce1334890 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/DGCommon.h (.../DGCommon.h) (revision f38051e1882be3e774f10ba924343a6ce1334890) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -56,7 +56,8 @@ // Turn these flags on to disable dialysate mixing #define DISABLE_DIALYSATE_CHECK 1 #define DISABLE_MIXING 1 - #define USE_SMALL_FLOW_SENSOR_K_FACTOR 1 + //#define USE_SMALL_FLOW_SENSOR_K_FACTOR 1 + //#define DISABLE_FLOW_CONTROL_TREATMENT 1 #include #include Index: firmware/App/Modes/ModeDrain.c =================================================================== diff -u -r2c4dfa08ac8ead07939b4f6aba3b0073e0997706 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 2c4dfa08ac8ead07939b4f6aba3b0073e0997706) +++ firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -98,7 +98,9 @@ // 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 ); +#ifndef DISABLE_FLOW_CONTROL_TREATMENT + setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); +#endif startHeater( DG_PRIMARY_HEATER ); } Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -rf38051e1882be3e774f10ba924343a6ce1334890 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision f38051e1882be3e774f10ba924343a6ce1334890) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -68,15 +68,17 @@ typedef struct { - F32 fillFlowRunningSum; ///< Fill flow running sum. - U32 fillFlowSampleCounter; ///< Fill flow sample counter. - F32 fillFlowAverage; ///< Fill flow average value. -} FILL_FLOW_RATE_STATUS_T; + F32 fillFlowRateRunningSum; ///< Fill flow running sum. + U32 fillSampleCounter; ///< Fill flow sample counter. + F32 fillTemperatureRunningSum; ///< Fill temperature running sum. + F32 fillTemperatureAverage; ///< Fill temperature average value. + F32 fillFlowRateAverage; ///< Fill flow average value. +} FILL_CONDITION_STATUS_T; static DG_FILL_MODE_STATE_T fillState; ///< Currently active fill state. static U32 dialysateFillStartTime; ///< Current time when starting to fill dialysate. static F32 reservoirBaseWeight; ///< Fill reservoir base weight. -static FILL_FLOW_RATE_STATUS_T fillFlowRate; ///< Fill flow rate status. +static FILL_CONDITION_STATUS_T fillStatus; ///< Fill condition status. static U32 waterQualityCheckStartTime; ///< Starting time for inlet water quality check. static U32 concentrateTestStartTime; ///< Starting time for concentrate test. @@ -102,7 +104,7 @@ static BOOL isWaterQualityGood( void ); static BOOL checkDialysateTemperature( void ); static void handleDialysateMixing( F32 measuredROFlowRate_mL_min ); -static void calculateFillAverage( void ); +static void getAvgFillFlowRateFromRTCRAM( void ); /*********************************************************************//** * @brief @@ -113,18 +115,20 @@ *************************************************************************/ void initFillMode( void ) { - fillState = DG_FILL_MODE_STATE_START; - dialysateFillStartTime = 0; - reservoirBaseWeight = 0.0; - totalROFlowRate_mL_min = 0.0; - concentrateTestStartTime = 0; - acidConductivityTotal = 0.0; - dialysateConductivityTotal = 0.0; - conductivitySampleCount = 0; - concentratePumpPrimeCount = 0; - fillFlowRate.fillFlowAverage = 0.79; // TODO get this value from NV RAM at the beginning of the fill - fillFlowRate.fillFlowRunningSum = 0.0; - fillFlowRate.fillFlowSampleCounter = 0; + fillState = DG_FILL_MODE_STATE_START; + dialysateFillStartTime = 0; + reservoirBaseWeight = 0.0; + totalROFlowRate_mL_min = 0.0; + concentrateTestStartTime = 0; + acidConductivityTotal = 0.0; + dialysateConductivityTotal = 0.0; + conductivitySampleCount = 0; + concentratePumpPrimeCount = 0; + fillStatus.fillFlowRateAverage = 0.79; // TODO change this to 0 once RTC RAM is implemented + fillStatus.fillFlowRateRunningSum = 0.0; + fillStatus.fillSampleCounter = 0; + fillStatus.fillTemperatureRunningSum = 0.0; + fillStatus.fillTemperatureAverage = 0.0; initPersistentAlarm( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); initPersistentAlarm( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); @@ -155,7 +159,9 @@ // 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 ); +#ifndef DISABLE_FLOW_CONTROL_TREATMENT + setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); +#endif startHeater( DG_PRIMARY_HEATER ); } @@ -173,6 +179,7 @@ checkInletWaterTemperature(); checkInletPressure(); checkRORejectionRatio(); + getAvgFillFlowRateFromRTCRAM(); // TODO: Check for open straw door status and alarm if closed // Check if run out of time to fill the reservoir @@ -225,19 +232,45 @@ /*********************************************************************//** * @brief - * The getAverageFillFlowRate function returns the moving average fill - * flow rate. + * The getAvgFillFlowRate function returns the average fill flow rate in + * each fill. * @details Inputs: none + * @details Outputs: fillFlowRateAverage + * @return average of the fill flow rate + *************************************************************************/ +F32 getAvgFillFlowRate( void ) +{ + return fillStatus.fillFlowRateAverage; +} + +/*********************************************************************//** + * @brief + * The setAvgFillFlowRateToRTCRAM function sets the average fill flow rate + * at the end of the treatment. + * @details Inputs: none * @details Outputs: averageFillFlowRate - * @return the moving average of the fill flow rate + * @return none *************************************************************************/ -F32 getAverageFillFlowRate( void ) +void setAvgFillFlowRateToRTCRAM( void ) { - return fillFlowRate.fillFlowAverage; + } /*********************************************************************//** * @brief + * The getAverageFillTemperature function returns the average fill temperature + * in each fill. + * @details Inputs: none + * @details Outputs: fillTemperatureAverage + * @return average fill temperature + *************************************************************************/ +F32 getAverageFillTemperature( void ) +{ + return fillStatus.fillTemperatureAverage; +} + +/*********************************************************************//** + * @brief * The handleCheckInletWaterState function checks for inlet water quality * before jumping to dialysate production state. * @details Inputs: Temperature and conductivity alarms @@ -335,11 +368,11 @@ *************************************************************************/ static DG_FILL_MODE_STATE_T handleAcidPumpCheckState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; DG_ACID_CONCENTRATES_RECORD_T acid = getAcidConcentrateCalRecord(); - F32 measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; - F32 acidPumpFlowRate_mL_min = measuredROFlowRate_mL_min * acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio + - CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; + F32 measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; + F32 acidPumpFlowRate_mL_min = measuredROFlowRate_mL_min * acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio + + CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; #ifndef DISABLE_DIALYSATE_CHECK F32 const acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); @@ -448,8 +481,9 @@ conductivitySampleCount++; // DG is delivering dialysate keep collecting the sample counter and the measured flow - fillFlowRate.fillFlowSampleCounter += 1; - fillFlowRate.fillFlowRunningSum += getMeasuredROFlowRate(); + fillStatus.fillSampleCounter += 1; + fillStatus.fillFlowRateRunningSum += getMeasuredROFlowRate(); + fillStatus.fillTemperatureRunningSum += getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); #ifndef DISABLE_DIALYSATE_CHECK if ( ( isWaterQualityGood() != TRUE ) || ( checkDialysateTemperature() != TRUE ) ) @@ -511,11 +545,13 @@ } #endif - // Done with this fill. Calculate the average fill flow rate - fillFlowRate.fillFlowAverage = fillFlowRate.fillFlowRunningSum / (F32)fillFlowRate.fillFlowSampleCounter; + // Done with this fill. Calculate the average fill flow rate and average temperature + fillStatus.fillFlowRateAverage = fillStatus.fillFlowRateRunningSum / (F32)fillStatus.fillSampleCounter; + fillStatus.fillTemperatureAverage = fillStatus.fillTemperatureRunningSum / (F32)fillStatus.fillSampleCounter; // Reset the variables for the next fill - fillFlowRate.fillFlowRunningSum = 0.0; - fillFlowRate.fillFlowSampleCounter = 0; + fillStatus.fillFlowRateRunningSum = 0.0; + fillStatus.fillTemperatureRunningSum = 0.0; + fillStatus.fillSampleCounter = 1; requestNewOperationMode( DG_MODE_GENE ); } @@ -561,6 +597,7 @@ return ( ( isInletPressureGood && isWaterTemperatureGood && isWaterConductivityGood ) ? TRUE : FALSE ); } + /*********************************************************************//** * @brief * The checkDialysateTemperature function checks dialysate temperature after @@ -577,6 +614,7 @@ return ( ( fabs( dialysateTemp - targetTemp ) <= DIALYSATE_TEMPERATURE_TOLERANCE_C ) ? TRUE : FALSE ); } + /*********************************************************************//** * @brief * The handleDialysateMixing function handles the dialysate mixing by setting @@ -602,7 +640,7 @@ #endif } -static void calculateFillAverage( void ) +static void getAvgFillFlowRateFromRTCRAM( void ) { } Index: firmware/App/Modes/ModeFill.h =================================================================== diff -u -rf38051e1882be3e774f10ba924343a6ce1334890 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision f38051e1882be3e774f10ba924343a6ce1334890) +++ firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -37,8 +37,11 @@ void transitionToFillMode( void ); // prepares for transition to fill mode U32 execFillMode( void ); // execute the fill mode state machine (call from OperationModes) -F32 getAverageFillFlowRate( void ); +F32 getAvgFillFlowRate( void ); +void setAvgFillFlowRateToRTCRAM( void ); +F32 getAvgFillTemperature( void ); + /**@}*/ #endif Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -r81dc975f13b9308e40aa0e33e0eca2d407276d44 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 81dc975f13b9308e40aa0e33e0eca2d407276d44) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -48,7 +48,7 @@ #define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. // Flush drain path state defines -#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo it was 2 minutes +#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 /* 60 */ * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo it was 2 minutes // Flush dialysate state defines #define FLUSH_DIALYSATE_WAIT_TIME_MS ( 0.5 * 60 * MS_PER_SECOND ) ///< Flush dialysate wait time in milliseconds. Index: firmware/App/Modes/ModeGenIdle.c =================================================================== diff -u -r373b25b7e3229e9203f4af6bfa491def69e2ce83 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 373b25b7e3229e9203f4af6bfa491def69e2ce83) +++ firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -108,12 +108,11 @@ // 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 ); - - //testSetTargetDutyCycle( 0.8 ); - - setHeaterTargetTemperature( DG_PRIMARY_HEATER, 39.0 ); // TODO remove this line. It comes form HD +#ifndef DISABLE_FLOW_CONTROL_TREATMENT + setROPumpTargetFlowRate( TARGET_FLUSH_LINES_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + setHeaterTargetTemperature( DG_PRIMARY_HEATER, 39.0 ); // TODO remove this line. It comes form HD this for testing only startHeater( DG_PRIMARY_HEATER ); +#endif } /*********************************************************************//** @@ -217,8 +216,9 @@ // When enough water volume has flowed to flush the lines, transition to flush water state if ( flushLinesVolumeL >= getFlushLineVolume() ) { - //setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); TODO remove - //setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); +#ifndef DISABLE_FLOW_CONTROL_TREATMENT + setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); +#endif result = DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; } Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r373b25b7e3229e9203f4af6bfa491def69e2ce83 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 373b25b7e3229e9203f4af6bfa491def69e2ce83) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -99,6 +99,7 @@ switch ( postState ) { case DG_POST_STATE_START: + SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_STARTUP, 0, 0 ); postState = DG_POST_STATE_FW_COMPATIBILITY; #ifdef SKIP_POST postState = DG_POST_STATE_COMPLETED; @@ -127,7 +128,6 @@ case DG_POST_STATE_NVDATAMGMT: testStatus = execNVDataMgmtSelfTest(); - testStatus = SELF_TEST_STATUS_PASSED; // TODO remove I don't know why the changed board in the Unit 002 did not pass postState = handlePOSTStatus( testStatus ); break; @@ -194,8 +194,8 @@ break; case DG_POST_STATE_WATCHDOG: - //testStatus = execWatchdogTest(); - testStatus = SELF_TEST_STATUS_PASSED; + testStatus = execWatchdogTest(); + //testStatus = SELF_TEST_STATUS_PASSED; postState = handlePOSTStatus( testStatus ); break; Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -r992dce16d63424ddd30fe9ac2f819e9a53b21977 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 992dce16d63424ddd30fe9ac2f819e9a53b21977) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -122,6 +122,7 @@ void execOperationModes( void ) { DG_OP_MODE_T newMode; + U32 priorSubMode = currentSubMode; // any new mode requests? newMode = arbitrateModeRequest(); // will return current mode if no pending requests @@ -197,6 +198,13 @@ break; } + // Send sub-mode change event when appropriate + if ( priorSubMode != currentSubMode ) + { + SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_SUB_MODE_CHANGE, priorSubMode, currentSubMode ); + } + priorSubMode = currentSubMode; + // publish op mode on interval broadcastOperationMode(); } @@ -296,6 +304,8 @@ *************************************************************************/ static void transitionToNewOperationMode( DG_OP_MODE_T newMode ) { + SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_OP_MODE_CHANGE, lastMode, newMode ); + // setup for new operating mode switch ( newMode ) { Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r54e58f64179ea382d2e2c403c8c3b9a15a612636 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 54e58f64179ea382d2e2c403c8c3b9a15a612636) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -185,7 +185,17 @@ U16 fpgaFanOut2Pulse; ///< Reg 398. Fan outlet 2 pulse time in 2.5 resolution U16 fpgaFanIn3Pulse; ///< Reg 400. Fan inlet 3 pulse time in 2.5 resolution U16 fpgaFanOut3Pulse; ///< Reg 402. Fan outlet 3 pulse time in 2.5 resolution - U16 fpgaTimerCount_ms; ///< Reg 404. Internal FPGA timer count in ms. + U16 fpgaTimerCount_ms; ///< Reg 404. Internal FPGA timer count in ms. + + U16 fpgaADCVccInt; ///< Reg 406. Internal FPGA Vcc Voltage. + U16 fpgaADCVccAux; ///< Reg 408. Internal FPGA Vcc auxiliary voltage. + U16 fpgaADCVPVN; ///< Reg 410. Internal FPGA VPVN voltage. + + U16 fpgaROPumpFeedback; ///< Reg 412. RO pump duty cycle feedback. + U16 fpgaDrainPumpSpeedFeedback; ///< Reg 414. Drain pump speed feedback. + U16 fpgaDrainPumpCurrentFeedback; ///< Reg 416. Drain pump current feedback. + + U16 fpgaFMPROFlowTemporary; ///< Reg 418. FMP flow sensor temporary register. } DG_FPGA_SENSORS_T; typedef struct @@ -1926,4 +1936,9 @@ return ( fpgaSensorReadings.fpgaGPIO & CONCENTRATE_CAP_SWITCH_MASK ); } +U16 getFPGAFMPTemporaryFlow( void ) +{ + return fpgaSensorReadings.fpgaFMPROFlowTemporary; +} + /**@}*/ Index: firmware/App/Services/FPGA.h =================================================================== diff -u -re6f3a632890f96a5aa282922d11df148bdd06587 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision e6f3a632890f96a5aa282922d11df148bdd06587) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -142,6 +142,9 @@ U08 getFPGADialysateCapStatus( void ); U08 getFPGAConcentrateCapStatus( void ); + +U16 getFPGAFMPTemporaryFlow( void ); + /**@}*/ #endif Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r81dc975f13b9308e40aa0e33e0eca2d407276d44 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 81dc975f13b9308e40aa0e33e0eca2d407276d44) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -212,6 +212,41 @@ /*********************************************************************//** * @brief + * The sendEvent function constructs an DG event message to the UI and + * queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: DG event msg constructed and queued. + * @param event Enumeration of event type that occurred + * @param dat1 First data associated with event + * @param dat2 Second data associated with event + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendEvent( DG_EVENT_ID_T event, EVENT_DATA_T dat1, EVENT_DATA_T dat2 ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + U32 e = (U32)event; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_EVENT; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( EVENT_DATA_T ) * 2; + + memcpy( payloadPtr, &e, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &dat1, sizeof( EVENT_DATA_T ) ); + payloadPtr += sizeof( EVENT_DATA_T ); + memcpy( payloadPtr, &dat2, sizeof( EVENT_DATA_T ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_2_UI, ACK_NOT_REQUIRED ); + + return result; +} + +/*********************************************************************//** + * @brief * The broadcastAlarmTriggered function constructs an alarm triggered msg to * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r81dc975f13b9308e40aa0e33e0eca2d407276d44 -r2468e56fbecd26da713bc78535bd727f4b105fe1 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 81dc975f13b9308e40aa0e33e0eca2d407276d44) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) @@ -55,6 +55,9 @@ // ACK MSG BOOL sendACKMsg( MESSAGE_T *message ); +// MSG_ID_DG_EVENT +BOOL sendEvent( DG_EVENT_ID_T event, EVENT_DATA_T dat1, EVENT_DATA_T dat2 ); + // Serialize message U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq );