Index: firmware/App/Drivers/ConductivitySensors.c =================================================================== diff -u -r11fcfaffab49f00f358124c8c285a821632eba24 -rcd4dd9f9928825dd673856bd6cf51ae47576ff79 --- firmware/App/Drivers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 11fcfaffab49f00f358124c8c285a821632eba24) +++ firmware/App/Drivers/ConductivitySensors.c (.../ConductivitySensors.c) (revision cd4dd9f9928825dd673856bd6cf51ae47576ff79) @@ -8,7 +8,7 @@ * @file ConductivitySensors.c * * @author (last) Michael Garthwaite -* @date (last) 20-Apr-2026 +* @date (last) 08-Jul-2026 * * @author (original) Vinayakam Mani * @date (original) 13-Sep-2024 @@ -56,6 +56,19 @@ #define COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Conductivity sensors FPGA error timeout in milliseconds. #define COND_SENSORS_READ_ERR_MAX_CNT 255 ///< Conductivity sensors read and error count max value. +#define COND_TEMP_COMP_LOW_BOUNDS 25.0F ///< Low temperature range for temperature compensation +#define COND_TEMP_COMP_HIGH_BOUNDS 42.0F ///< High temperature range for temperature compensation +#define DIALYSATE_SENSORS_ALPHA_LOW 0.02F ///< Temp compensated low alpha value for D27, D29, D43. +#define DIALYSATE_SENSORS_ALPHA_HIGH 0.0213F ///< Temp compensated high alpha value for D27, D29, D43. +#define DIALYSATE_SENSORS_ALPHA_SLOPE 0.00007647F ///< Calculated linear slope between temp and alpha range for dialysate sensors +#define DIALYSATE_SENSORS_ALPHA_INTERCEPT 0.01808824F ///< Calculated linear intercept between temp and alpha range for dialysate sensors +#define BICARB_SENSORS_ALPHA_SLOPE 0.0001F ///< Calculated linear slope between temp and alpha range for bicarb sensors +#define BICARB_SENSORS_ALPHA_INTERCEPT 0.0186F ///< Calculated linear intercept between temp and alpha range for bicarb sensors +#define BICARB_SENSORS_ALPHA_LOW 0.0211F ///< Temp compensated low alpha value for D17 and D74. +#define BICARB_SENSORS_ALPHA_HIGH 0.0228F ///< Temp compensated high alpha value for D17 and D74. +#define RO_SENSORS_ALPHA 0.02F ///< Temp compensated alpha value for P9, P18 with RO water. +#define TEMP_COMP_LINEAR(slope, intercept, temp) ( ( slope * temp ) + intercept ) ///< Line equation for temp + #define COND_TEMP_OFFSET 25 ///< Temperature offset constant used in RTD calculations. #define SIEMENS_TO_MICROSIEMENS_CONVERSION 1000000.0F ///< Siemens to microSiemens conversion factor. #define KOHMS_TO_OHMS 1000.0F ///< Kilo ohms to ohms conversion factor. @@ -75,6 +88,7 @@ F32 rawResistance; ///< Raw Resistance in kOhms from the conductivity sensor. F32 calculatedTemperature; ///< Calculated temperature in C. F32 calculatedResistance; ///< Calculated resistance in Ohms. + F32 currentAlphaValue; ///< Last used alpha value in temperature compensation. U08 condReadCount; ///< Last conductivity read count. U08 condErrorCount; ///< Last conductivity error count. U08 tempReadCount; ///< Last temperature read count. @@ -90,6 +104,7 @@ // ********** private data ********** static CONDUCTIVITY_STATE_T currentConductivityState; ///< Current conductivity sensor state. +static OVERRIDE_F32_T currentUncompenstatedConductivityReadings[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< TODO: Get Vinay or Sean to tell me to remove this debug array in CR. static OVERRIDE_F32_T currentConductivityReadings[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Current conductivity sensor conductivity readings (overrideable). static OVERRIDE_F32_T currentTemperatureReadings[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Current conductivity sensor temperature readings (overrideable). static OVERRIDE_U32_T lastConductivityReadCounter[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Last conductivity sensor read count (Overrideable). @@ -112,6 +127,7 @@ static BOOL monitorCalDataReads( CONDUCTIVITY_SENSORS_T sensorId ); static BOOL checkConductivityCoefficientRanges( CONDUCTIVITY_SENSORS_T sensorId ); static void calculateConductivityUpdatedStandard( CONDUCTIVITY_SENSORS_T sensorNum, BOOL isFPSensor ); +static void calculateConductivityUpdatedStandardTempCompensated( CONDUCTIVITY_SENSORS_T sensorNum, BOOL isFPSensor ); static void calculateTemperature( CONDUCTIVITY_SENSORS_T sensorNum ); static void calculateResistance( CONDUCTIVITY_SENSORS_T sensorNum, BOOL isFPSensor ); @@ -131,6 +147,11 @@ // Initialize override structures for each conductivity sensor for ( sensor = FIRST_DD_COND_SENSOR; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) { + currentUncompenstatedConductivityReadings[ sensor ].data = 0.0F; + currentUncompenstatedConductivityReadings[ sensor ].ovData = 0.0F; + currentUncompenstatedConductivityReadings[ sensor ].ovInitData = 0.0F; + currentUncompenstatedConductivityReadings[ sensor ].override = OVERRIDE_RESET; + currentConductivityReadings[ sensor ].data = 0.0F; currentConductivityReadings[ sensor ].ovData = 0.0F; currentConductivityReadings[ sensor ].ovInitData = 0.0F; @@ -356,127 +377,138 @@ // Check which counter, assign it, and assign read bool to TRUE per sensor for ( sensor = FIRST_DD_COND_SENSOR; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) { + // check if we have finished reading all values. + conductivitySensorStatus[ sensor ].haveAllCalSlotsBeenRead = monitorCalDataReads( sensor ); if ( FALSE == conductivitySensorStatus[ sensor ].haveAllCalSlotsBeenRead ) { - - switch( conductivitySensorStatus[ sensor ].calMemCount ) + if ( getTestConfigStatus( TEST_CONFIG_DD_FP_DISABLE_CONDUCTIVITY_SENSOR_CHECKS ) == TRUE ) { - case CAL_DATA_1: - memcpy( &conductivitySensorCoefficients[ sensor ].K_high, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_1 ] = TRUE; - break; - case CAL_DATA_2: - memcpy( &conductivitySensorCoefficients[ sensor ].alpha_high, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_2 ] = TRUE; - break; - case CAL_DATA_3: - memcpy( &conductivitySensorCoefficients[ sensor ].eta_high, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_3 ] = TRUE; - break; - case CAL_DATA_4: - memcpy( &conductivitySensorCoefficients[ sensor ].zeta_high, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_4 ] = TRUE; - break; - case CAL_DATA_5: - memcpy( &conductivitySensorCoefficients[ sensor ].K_low, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_5 ] = TRUE; - break; - case CAL_DATA_6: - memcpy( &conductivitySensorCoefficients[ sensor ].alpha_low, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_6 ] = TRUE; - break; - case CAL_DATA_7: - memcpy( &conductivitySensorCoefficients[ sensor ].eta_low, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_7 ] = TRUE; - break; - case CAL_DATA_8: - memcpy( &conductivitySensorCoefficients[ sensor ].zeta_low, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_8 ] = TRUE; - break; - case CAL_DATA_9: - memcpy( &conductivitySensorCoefficients[ sensor ].beta, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_9 ] = TRUE; - break; - case CAL_DATA_10: - memcpy( &conductivitySensorCoefficients[ sensor ].delta, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_10 ] = TRUE; - break; - case CAL_DATA_11: - memcpy( &conductivitySensorCoefficients[ sensor ].reserved1, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_11 ] = TRUE; - break; - case CAL_DATA_12: - memcpy( &conductivitySensorCoefficients[ sensor ].reserved2, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_12 ] = TRUE; - break; - case SW_REV_LOWER_WORD: - memcpy( conductivitySensorRevisions[ sensor ].swRev, &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ SW_REV_LOWER_WORD ] = TRUE; - break; - case SW_REV_MID_WORD: - memcpy( ( conductivitySensorRevisions[ sensor ].swRev + LOWER_WORD_SIZE ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ SW_REV_MID_WORD ] = TRUE; - break; - case SW_REV_UPPER_WORD: - memcpy( ( conductivitySensorRevisions[ sensor ].swRev + ( LOWER_WORD_SIZE + MID_WORD_SIZE ) ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ SW_REV_UPPER_WORD ] = TRUE; - break; - case HW_REV_LOWER_WORD: - memcpy( conductivitySensorRevisions[ sensor ].hwRev, &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_REV_LOWER_WORD ] = TRUE; - break; - case HW_REV_MID_WORD: - memcpy( ( conductivitySensorRevisions[ sensor ].hwRev + LOWER_WORD_SIZE ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_REV_MID_WORD ] = TRUE; - break; - case HW_REV_UPPER_WORD: - memcpy( ( conductivitySensorRevisions[ sensor ].hwRev + ( LOWER_WORD_SIZE + MID_WORD_SIZE ) ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_REV_UPPER_WORD ] = TRUE; - break; - case HW_SERIAL_LOWER_WORD: - memcpy( conductivitySensorRevisions[ sensor ].hwSerial, &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_SERIAL_LOWER_WORD ] = TRUE; - break; - case HW_SERIAL_MID_WORD: - memcpy( ( conductivitySensorRevisions[ sensor ].hwSerial + LOWER_WORD_SIZE ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_SERIAL_MID_WORD ] = TRUE; - break; - case HW_SERIAL_UPPER_WORD: - memcpy( ( conductivitySensorRevisions[ sensor ].hwRev + ( LOWER_WORD_SIZE + MID_WORD_SIZE ) ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); - conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_SERIAL_UPPER_WORD ] = TRUE; - break; - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_CONDUCTIVITY_SENSOR_CAL_CHECK, sensor ) - break; + // When test config is enabled, check first cal data. If we see a 0 there, + // then most likely not talking to a sensor while HW is in development ( cal data here should be non-zero. ) + if ( ( conductivitySensorStatus[ sensor ].calMemCount == 0 ) && + ( conductivitySensorStatus[ sensor ].calData == 0 ) ) + { + conductivitySensorStatus[ sensor ].haveAllCalSlotsBeenRead = TRUE; + } + } + else + { + switch( conductivitySensorStatus[ sensor ].calMemCount ) + { + case CAL_DATA_1: + memcpy( &conductivitySensorCoefficients[ sensor ].K_high, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_1 ] = TRUE; + break; + case CAL_DATA_2: + memcpy( &conductivitySensorCoefficients[ sensor ].alpha_high, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_2 ] = TRUE; + break; + case CAL_DATA_3: + memcpy( &conductivitySensorCoefficients[ sensor ].eta_high, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_3 ] = TRUE; + break; + case CAL_DATA_4: + memcpy( &conductivitySensorCoefficients[ sensor ].zeta_high, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_4 ] = TRUE; + break; + case CAL_DATA_5: + memcpy( &conductivitySensorCoefficients[ sensor ].K_low, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_5 ] = TRUE; + break; + case CAL_DATA_6: + memcpy( &conductivitySensorCoefficients[ sensor ].alpha_low, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_6 ] = TRUE; + break; + case CAL_DATA_7: + memcpy( &conductivitySensorCoefficients[ sensor ].eta_low, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_7 ] = TRUE; + break; + case CAL_DATA_8: + memcpy( &conductivitySensorCoefficients[ sensor ].zeta_low, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_8 ] = TRUE; + break; + case CAL_DATA_9: + memcpy( &conductivitySensorCoefficients[ sensor ].beta, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_9 ] = TRUE; + break; + case CAL_DATA_10: + memcpy( &conductivitySensorCoefficients[ sensor ].delta, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_10 ] = TRUE; + break; + case CAL_DATA_11: + memcpy( &conductivitySensorCoefficients[ sensor ].reserved1, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_11 ] = TRUE; + break; + case CAL_DATA_12: + memcpy( &conductivitySensorCoefficients[ sensor ].reserved2, &conductivitySensorStatus[ sensor ].calData, sizeof(U32)); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ CAL_DATA_12 ] = TRUE; + break; + case SW_REV_LOWER_WORD: + memcpy( conductivitySensorRevisions[ sensor ].swRev, &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ SW_REV_LOWER_WORD ] = TRUE; + break; + case SW_REV_MID_WORD: + memcpy( ( conductivitySensorRevisions[ sensor ].swRev + LOWER_WORD_SIZE ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ SW_REV_MID_WORD ] = TRUE; + break; + case SW_REV_UPPER_WORD: + memcpy( ( conductivitySensorRevisions[ sensor ].swRev + ( LOWER_WORD_SIZE + MID_WORD_SIZE ) ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ SW_REV_UPPER_WORD ] = TRUE; + break; + case HW_REV_LOWER_WORD: + memcpy( conductivitySensorRevisions[ sensor ].hwRev, &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_REV_LOWER_WORD ] = TRUE; + break; + case HW_REV_MID_WORD: + memcpy( ( conductivitySensorRevisions[ sensor ].hwRev + LOWER_WORD_SIZE ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_REV_MID_WORD ] = TRUE; + break; + case HW_REV_UPPER_WORD: + memcpy( ( conductivitySensorRevisions[ sensor ].hwRev + ( LOWER_WORD_SIZE + MID_WORD_SIZE ) ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_REV_UPPER_WORD ] = TRUE; + break; + case HW_SERIAL_LOWER_WORD: + memcpy( conductivitySensorRevisions[ sensor ].hwSerial, &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_SERIAL_LOWER_WORD ] = TRUE; + break; + case HW_SERIAL_MID_WORD: + memcpy( ( conductivitySensorRevisions[ sensor ].hwSerial + LOWER_WORD_SIZE ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_SERIAL_MID_WORD ] = TRUE; + break; + case HW_SERIAL_UPPER_WORD: + memcpy( ( conductivitySensorRevisions[ sensor ].hwRev + ( LOWER_WORD_SIZE + MID_WORD_SIZE ) ), &conductivitySensorStatus[ sensor ].calData, sizeof( U32 ) ); + conductivitySensorStatus[ sensor ].hasCalSlotBeenRead[ HW_SERIAL_UPPER_WORD ] = TRUE; + break; + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_CONDUCTIVITY_SENSOR_CAL_CHECK, sensor ) + break; + } } - // check if we have finished reading all values. - conductivitySensorStatus[ sensor ].haveAllCalSlotsBeenRead = monitorCalDataReads( sensor ); } - // Read all cal values. Check ranges. + + // DD has read all cal values. Check ranges. else { + conductivitySensorStatus[ sensor ].calReadComplete = checkConductivityCoefficientRanges( sensor ); - if ( getTestConfigStatus( TEST_CONFIG_DD_FP_DISABLE_CONDUCTIVITY_SENSOR_CHECKS ) == TRUE ) + // TODO: this retry should be changed to an alarm or fault once we change the functionality of + // BETA 2.0 test config. This is meant to handle the in-between state of FPGA transitioning + // between 2.0 and non-2.0 data structures. + if ( FALSE == conductivitySensorStatus[ sensor ].calReadComplete ) { - conductivitySensorStatus[ sensor ].calReadComplete = TRUE; + conductivitySensorStatus[ sensor ].haveAllCalSlotsBeenRead = FALSE; + memset( conductivitySensorStatus[ sensor ].hasCalSlotBeenRead, 0 ,sizeof( conductivitySensorStatus[ sensor ].hasCalSlotBeenRead ) ); } - else - { - conductivitySensorStatus[ sensor ].calReadComplete = checkConductivityCoefficientRanges( sensor ); - // TODO: this retry should be changed to an alarm or fault once we change the functionality of - // BETA 2.0 test config. This is meant to handle the in-between state of FPGA transitioning - // between 2.0 and non-2.0 data structures. - if ( FALSE == conductivitySensorStatus[ sensor ].calReadComplete ) - { - conductivitySensorStatus[ sensor ].haveAllCalSlotsBeenRead = FALSE; - memset( conductivitySensorStatus[ sensor ].hasCalSlotBeenRead, 0 ,sizeof( conductivitySensorStatus[ sensor ].hasCalSlotBeenRead ) ); - } - } } + if ( getTestConfigStatus( TEST_CONFIG_DD_FP_DISABLE_CONDUCTIVITY_SENSOR_CHECKS ) == TRUE ) + { + conductivitySensorStatus[ sensor ].calReadComplete = TRUE; + } + // calResult determines if we are done reading calibration data from all sensors. // each sensor can re-assign it back to false if it is not completely done reading. if ( TRUE == conductivitySensorStatus[ sensor ].calReadComplete ) @@ -526,8 +558,8 @@ { isFPSensor = TRUE; } - calculateConductivityUpdatedStandard( sensor, isFPSensor ); + calculateConductivityUpdatedStandardTempCompensated( sensor, isFPSensor ); } return state; @@ -554,7 +586,10 @@ { if ( ++conductivitySensorStatus[ sensorId ].interalCondErrorCount > MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ) { + //TODO: restore once conductivity sensor are calibrated and working +#ifndef __CONDUCTIVITY_SENSOR_ALARMS_DISABLED__ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, sensorId ) +#endif } } @@ -567,15 +602,21 @@ { if ( ++conductivitySensorStatus[ sensorId ].interalTempErrorCount > MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ) { + //TODO: restore once conductivity sensor are calibrated and working +#ifndef __CONDUCTIVITY_SENSOR_ALARMS_DISABLED__ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, sensorId ) +#endif } } } else { if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR ) ) { + //TODO: restore once conductivity sensor are calibrated and working +#ifndef __CONDUCTIVITY_SENSOR_ALARMS_DISABLED__ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, sensorId ) +#endif } } } @@ -692,7 +733,10 @@ // Alarm if any data is out of range. if ( FALSE == result ) { + //TODO: restore once conductivity sensor are calibrated and working +#ifndef __CONDUCTIVITY_SENSOR_ALARMS_DISABLED__ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, sensorId, ( U32 )idx ) +#endif } return result; @@ -849,6 +893,35 @@ /*********************************************************************//** * @brief + * The getUncompensatedConductivity function gets the conductivity + * value for a given conductivity sensor id. + * @details \b Inputs: currentUncompenstatedConductivityReadings[] + * @details \b Outputs: none + * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. + * @param sensorId conductivity sensor id + * @return conductivity value + *************************************************************************/ +F32 getUncompensatedConductivity( CONDUCTIVITY_SENSORS_T sensor ) +{ + F32 result = 0.0F; + + if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) + { + result = currentUncompenstatedConductivityReadings[ sensor ].data; + if ( OVERRIDE_KEY == currentUncompenstatedConductivityReadings[ sensor ].override ) + { + result = currentUncompenstatedConductivityReadings[ sensor ].ovData; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID, sensor ) + } + + return result; +} +/*********************************************************************//** + * @brief * The getConductivityTemperatureValue function gets the temperature * value for a given conductivity sensor id. * @details \b Inputs: currentTemperatureReadings[] @@ -879,6 +952,58 @@ /*********************************************************************//** * @brief + * The getConductivityRawResistance function gets the raw conductivity resistance + * value for a given conductivity sensor id. + * @details \b Inputs: conductivitySensorStatus[] + * @details \b Outputs: none + * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. + * @param sensorId conductivity sensor id + * @return temperature value + *************************************************************************/ +F32 getConductivityRawResistance( CONDUCTIVITY_SENSORS_T sensor ) +{ + F32 result = 0.0F; + + if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) + { + result = conductivitySensorStatus[ sensor ].rawResistance; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID1, sensor ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getConductivityRawRTD function gets the raw RTD resistance + * value for a given conductivity sensor id. + * @details \b Inputs: conductivitySensorStatus[] + * @details \b Outputs: none + * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. + * @param sensorId conductivity sensor id + * @return temperature value + *************************************************************************/ +F32 getConductivityRawRTD( CONDUCTIVITY_SENSORS_T sensor ) +{ + F32 result = 0.0F; + + if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) + { + result = conductivitySensorStatus[ sensor ].rawTemperature; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID1, sensor ) + } + + return result; +} + +/*********************************************************************//** + * @brief * The calculateConductivityUpdatedStandard function calculates the conductivity value. * @details \b Inputs: conductivitySensorCoefficients - Conductivity Coefficients * @details \b Inputs: conductivitySensorStatus - Raw measurement values @@ -913,6 +1038,73 @@ /*********************************************************************//** * @brief + * The calculateConductivityUpdatedStandardTempCompensated function calculates the conductivity value with temperature compensation. + * @details \b Inputs: conductivitySensorCoefficients - Conductivity Coefficients + * @details \b Inputs: conductivitySensorStatus - Raw measurement values + * @details \b Outputs: conductivitySensorStatus - calculated conductivity value + * @param sensorNum - Conductivity sensor index value. + * @param isFPSensor - T/F if sensor is on FP hardware. + * @return + *************************************************************************/ +static void calculateConductivityUpdatedStandardTempCompensated( CONDUCTIVITY_SENSORS_T sensorNum, BOOL isFPSensor ) +{ + F64 calculatedConductivity = 0.0; + F64 k = 0.0; + + if ( TRUE == isFPSensor ) + { + k = conductivitySensorCoefficients[ sensorNum ].K_low; + conductivitySensorStatus[ sensorNum ].currentAlphaValue = RO_SENSORS_ALPHA; + } + else + { + k = conductivitySensorCoefficients[ sensorNum ].K_high; + + switch ( sensorNum ) + { + case D74_COND: + case D17_COND: + // check temp range and apply alpha + if ( conductivitySensorStatus[ sensorNum ].calculatedTemperature < COND_TEMP_COMP_LOW_BOUNDS ) + { + conductivitySensorStatus[ sensorNum ].currentAlphaValue = BICARB_SENSORS_ALPHA_LOW; + } + else if ( conductivitySensorStatus[ sensorNum ].calculatedTemperature > COND_TEMP_COMP_LOW_BOUNDS ) + { + conductivitySensorStatus[ sensorNum ].currentAlphaValue = BICARB_SENSORS_ALPHA_HIGH; + } + else + { + conductivitySensorStatus[ sensorNum ].currentAlphaValue = TEMP_COMP_LINEAR( BICARB_SENSORS_ALPHA_SLOPE, BICARB_SENSORS_ALPHA_INTERCEPT, conductivitySensorStatus[ sensorNum ].calculatedTemperature ); + } + break; + default: + // check temp range and apply alpha + if ( conductivitySensorStatus[ sensorNum ].calculatedTemperature < COND_TEMP_COMP_LOW_BOUNDS ) + { + conductivitySensorStatus[ sensorNum ].currentAlphaValue = DIALYSATE_SENSORS_ALPHA_LOW; + } + else if ( conductivitySensorStatus[ sensorNum ].calculatedTemperature > COND_TEMP_COMP_LOW_BOUNDS ) + { + conductivitySensorStatus[ sensorNum ].currentAlphaValue = DIALYSATE_SENSORS_ALPHA_HIGH; + } + else + { + conductivitySensorStatus[ sensorNum ].currentAlphaValue = TEMP_COMP_LINEAR( DIALYSATE_SENSORS_ALPHA_SLOPE, DIALYSATE_SENSORS_ALPHA_INTERCEPT, conductivitySensorStatus[ sensorNum ].calculatedTemperature ); + } + break; + } + } + calculateResistance( sensorNum, isFPSensor ); + calculateTemperature( sensorNum ); + + calculatedConductivity = ( ( k / conductivitySensorStatus[ sensorNum ].calculatedResistance ) * + ( 1 + ( conductivitySensorStatus[ sensorNum ].currentAlphaValue * ( COND_TEMP_OFFSET - conductivitySensorStatus[ sensorNum ].calculatedTemperature ) ) ) ); + currentConductivityReadings[ sensorNum ].data = calculatedConductivity * SIEMENS_TO_MICROSIEMENS_CONVERSION; +} + +/*********************************************************************//** + * @brief * The calculateResistance function calculates the temperature values. * @details \b Inputs: conductivitySensorCoefficients - Conductivity Coefficients * @details \b Inputs: conductivitySensorStatus - Raw measurement values @@ -1149,33 +1341,73 @@ BOOL testHandleConductivitySensorVersionRequest( MESSAGE_T *message ) { BOOL result = FALSE; - U32 condSensorId = 0; - U32 msgId = 0; - U32 channelId = 0; + U32 msgId = MSG_ID_DD_CONDUCTIVITY_SENSOR_VERSION_RESPONSE; + U32 channelId = COMM_BUFFER_OUT_CAN_DD_BROADCAST; if ( message->hdr.payloadLen == sizeof( U32 ) ) { - CONDUCTIVITY_REVISIONS_T CondVersionRecord; + CONDUCTIVITY_VERSION_RESPONSE_T CondVersionRecord; - memcpy( &condSensorId, &message->payload, sizeof( U32 ) ); + memcpy( &CondVersionRecord.sensorID, &message->payload, sizeof( U32 ) ); // Build conductivity version record - if ( condSensorId < LAST_DD_COND_SENSOR ) + if ( CondVersionRecord.sensorID < LAST_DD_COND_SENSOR ) { - msgId = MSG_ID_DD_CONDUCTIVITY_SENSOR_VERSION_RESPONSE; - channelId = COMM_BUFFER_OUT_CAN_DD_BROADCAST; - memcpy( &CondVersionRecord, &conductivitySensorRevisions[ condSensorId ], sizeof( CONDUCTIVITY_REVISIONS_T ) ); + memcpy( &CondVersionRecord.sensorVersion, &conductivitySensorRevisions[ CondVersionRecord.sensorID ], sizeof( CONDUCTIVITY_REVISIONS_T ) ); } - else + else if ( ( CondVersionRecord.sensorID > LAST_DD_COND_SENSOR ) && + ( CondVersionRecord.sensorID < NUM_OF_CONDUCTIVITY_SENSORS ) ) { msgId = MSG_ID_FP_CONDUCTIVITY_SENSOR_VERSION_RESPONSE; channelId = COMM_BUFFER_OUT_CAN_FP_BROADCAST; - memcpy( &CondVersionRecord, &conductivitySensorRevisions[ condSensorId ], sizeof( CONDUCTIVITY_REVISIONS_T ) ); + memcpy( &CondVersionRecord.sensorVersion, &conductivitySensorRevisions[ CondVersionRecord.sensorID ], sizeof( CONDUCTIVITY_REVISIONS_T ) ); } - result = sendMessage( (MSG_ID_T)msgId, (COMM_BUFFER_T)channelId, (U08*)&CondVersionRecord, sizeof( CONDUCTIVITY_REVISIONS_T ) ); + + result = sendMessage( (MSG_ID_T)msgId, (COMM_BUFFER_T)channelId, (U08*)&CondVersionRecord, sizeof( CONDUCTIVITY_VERSION_RESPONSE_T ) ); } return result; } +/*********************************************************************//** + * @brief + * The testHandleConductivitySensorCalRequest function sends + * the conductivity sensor calibration response + * @details \b Inputs: conductivitySensorCoefficients[] + * @details \b Outputs: none + * @param message Override message from Dialin which includes an sensor + * ID. + * @return TRUE if response is successful, FALSE if not + *************************************************************************/ +BOOL testHandleConductivitySensorCalRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + U32 msgId = MSG_ID_DD_CONDUCTIVITY_SENSOR_VERSION_RESPONSE; + U32 channelId = COMM_BUFFER_OUT_CAN_DD_BROADCAST; + + if ( message->hdr.payloadLen == sizeof( U32 ) ) + { + CONDUCTIVITY_CAL_RESPONSE_T CondCalRecord; + + memcpy( &CondCalRecord.sensorID, &message->payload, sizeof( U32 ) ); + + // Build conductivity version record + if ( CondCalRecord.sensorID < LAST_DD_COND_SENSOR ) + { + memcpy( &CondCalRecord.sensorCal, &conductivitySensorCoefficients[ CondCalRecord.sensorID ], sizeof( CONDUCTIVITY_COEFFICIENTS_T ) ); + } + else if ( ( CondCalRecord.sensorID > LAST_DD_COND_SENSOR ) && + ( CondCalRecord.sensorID < NUM_OF_CONDUCTIVITY_SENSORS ) ) + { + msgId = MSG_ID_FP_CONDUCTIVITY_SENSOR_VERSION_RESPONSE; + channelId = COMM_BUFFER_OUT_CAN_FP_BROADCAST; + memcpy( &CondCalRecord.sensorCal, &conductivitySensorCoefficients[ CondCalRecord.sensorID ], sizeof( CONDUCTIVITY_COEFFICIENTS_T ) ); + } + + result = sendMessage( (MSG_ID_T)msgId, (COMM_BUFFER_T)channelId, (U08*)&CondCalRecord, sizeof( CONDUCTIVITY_CAL_RESPONSE_T ) ); + } + + return result; +} + /**@}*/ Index: firmware/App/Services/FpgaDD.c =================================================================== diff -u -r564f2989d8c969b0182c2a1833da38218a175688 -rcd4dd9f9928825dd673856bd6cf51ae47576ff79 --- firmware/App/Services/FpgaDD.c (.../FpgaDD.c) (revision 564f2989d8c969b0182c2a1833da38218a175688) +++ firmware/App/Services/FpgaDD.c (.../FpgaDD.c) (revision cd4dd9f9928825dd673856bd6cf51ae47576ff79) @@ -8,8 +8,8 @@ * * @file FpgaDD.c * -* @author (last) Sameer Kalliadan Poyil -* @date (last) 16-Apr-2026 +* @author (last) Michael Garthwaite +* @date (last) 09-Jul-2026 * * @author (original) Vinayakam Mani * @date (original) 26-Aug-2024 @@ -318,7 +318,7 @@ U16 fpgaD18PresTemp; ///< Reg 534. D18 MPM pressure sensor RAW temperature data U16 fpgaD41PresPressure; ///< Reg 536. D41 MPM pressure sensor RAW pressure data U16 fpgaD41PresTemp; ///< Reg 538. D41 MPM pressure sensor RAW temperature data - U32 fpgaAvailableRegister1; ///< Reg 540. Available register 1 + U32 fpgaD92SpeedCnt; ///< Reg 540. D92 Substitution Pump Hall sensor speed counter. U08 fpgaHallSensInputs; ///< Reg 544. Hall sensor Inputs U08 fpgaD42TxFIFOCnt; ///< Reg 545. Blood leak sensor transmit FIFO count U16 fpgaD42RxErrorCnt; ///< Reg 546. Blood leak sensor Receive error count @@ -458,6 +458,11 @@ U08 fpgaP18TempReadCount; ///< Reg 818. P18 temperature successful read count U08 fpgaP18TempErrorCount; ///< Reg 819. P18 Temperature error read count U08 fpgaP18CalMemCounter; ///< Reg 820. P18 CAL counter + U08 notUsed; ///< Reg 821. Not used. + U16 fpgaACDCPMonIrms; ///< Reg 822. AC DC Power Supply RMS Current + U16 fpgaACDCPMonVrms; ///< Reg 824. AC DC Power Supply RMS Voltage + U16 fpgaACHeaterPMonIrms; ///< Reg 826. AC Heater RMS Current + U16 fpgaACHeaterPMonVrms; ///< Reg 828. AC Heater RMS Voltage. } DD_FPGA_SENSORS_T; // TODO: Remove when Beta 1.9 is obsolete @@ -1422,6 +1427,7 @@ { fpgaActuatorSetPoints.fpgaD92PumpRevCount = count; } + /*********************************************************************//** * @brief * The setFPGAD5HeaterOnOffControl function sets the primary heater @@ -4002,4 +4008,65 @@ return fpgaSensorReadings.fpgaP18CalMemCounter; } +/*********************************************************************//** + * @brief + * The getFPGAD92PumpHallSenseCount function gets substitution pump, D92, + * hall sensor speed counter. + * @details \b Inputs: fpgaD92SpeedCnt + * @details \b Outputs: none + * @return substitution pump hall sense pulse width + *************************************************************************/ +U32 getFPGAD92PumpHallSenseCount( void ) +{ + return fpgaSensorReadings.fpgaD92SpeedCnt; +} + +/*********************************************************************//** + * @brief + * The getFPGAACToDCPowerSupplyCurrent function gets AC/DC Power Supply Current + * @details \b Inputs: fpgaACDCPMonIrms + * @details \b Outputs: none + * @return power supply current in counts. + *************************************************************************/ +U16 getFPGAACToDCPowerSupplyCurrent( void ) +{ + return fpgaSensorReadings.fpgaACDCPMonIrms; +} + +/*********************************************************************//** + * @brief + * The getFPGAACToDCPowerSupplyVoltage function gets AC/DC Power Supply Voltage + * @details \b Inputs: fpgaACDCPMonVrms + * @details \b Outputs: none + * @return power supply voltage in counts. + *************************************************************************/ +U16 getFPGAACToDCPowerSupplyVoltage( void ) +{ + return fpgaSensorReadings.fpgaACDCPMonVrms; +} + +/*********************************************************************//** + * @brief + * The getFPGAACHeaterCurrent function gets AC Heater Current + * @details \b Inputs: fpgaACHeaterPMonIrms + * @details \b Outputs: none + * @return ac heater current in counts. + *************************************************************************/ +U16 getFPGAACHeaterCurrent( void ) +{ + return fpgaSensorReadings.fpgaACHeaterPMonIrms; +} + +/*********************************************************************//** + * @brief + * The getFPGAACHeaterVoltage function gets AC Heater Voltage + * @details \b Inputs: fpgaACHeaterPMonVrms + * @details \b Outputs: none + * @return power supply current in counts. + *************************************************************************/ +U16 getFPGAACHeaterVoltage( void ) +{ + return fpgaSensorReadings.fpgaACHeaterPMonVrms; +} + /**@}*/ Index: firmware/App/Tasks/TaskGeneral.c =================================================================== diff -u -r11fcfaffab49f00f358124c8c285a821632eba24 -rcd4dd9f9928825dd673856bd6cf51ae47576ff79 --- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 11fcfaffab49f00f358124c8c285a821632eba24) +++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision cd4dd9f9928825dd673856bd6cf51ae47576ff79) @@ -7,8 +7,8 @@ * * @file TaskGeneral.c * -* @author (last) Arpita Srivastava -* @date (last) 08-Apr-2026 +* @author (last) Michael Garthwaite +* @date (last) 14-Jul-2026 * * @author (original) Vinayakam Mani * @date (original) 07-Aug-2024 @@ -26,6 +26,7 @@ #include "Heaters.h" #include "FPOperationModes.h" #include "Messaging.h" +#include "MixingControl.h" #include "OperationModes.h" #include "PermeateTank.h" #include "RinsePump.h" @@ -34,6 +35,7 @@ #include "SystemCommDD.h" #include "TaskGeneral.h" #include "WatchdogMgmt.h" +#include "Voltages.h" /** * @addtogroup TaskGeneral @@ -82,7 +84,7 @@ execConcentratePumpMonitor(); // Monitor DD voltages - ///execVoltagesMonitor(); + execVoltagesMonitor(); // run DD operation mode state machine execDDOperationModes(); @@ -99,12 +101,15 @@ // manage concentrate pumps execConcentratePumpController(); - if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == TRUE ) + if ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { - // manage drybicart state machines + // Control drybicart fill, supply , drain and depressurize state machines execDryBicart(); } + // Control closed loop mixing of bicarb and acid + execMixingControl(); + // Control Substitution pump execSubstitutionPumpController(); Index: firmware/source/sys_main.c =================================================================== diff -u -r11fcfaffab49f00f358124c8c285a821632eba24 -rcd4dd9f9928825dd673856bd6cf51ae47576ff79 --- firmware/source/sys_main.c (.../sys_main.c) (revision 11fcfaffab49f00f358124c8c285a821632eba24) +++ firmware/source/sys_main.c (.../sys_main.c) (revision cd4dd9f9928825dd673856bd6cf51ae47576ff79) @@ -80,8 +80,10 @@ #include "FpgaDD.h" #include "FPInterface.h" #include "Heaters.h" +#include "Integrity.h" #include "Interrupts.h" #include "Level.h" +#include "MixingControl.h" #include "ModeGenPermeateDefeatured.h" #include "ModePreGenPermeateDefeatured.h" #include "ModeGenPermeate.h" @@ -210,6 +212,8 @@ initRinsePump(); initDryBiCart(); initSubstitutionPump(); + initMixingControl(); + initIntegrity(); // FP Modules