/** * @file pressureController.c * * @copyright Nehemis SARL reserves all rights even in the event of industrial * property rights. We reserve all rights of disposal such as * copying and passing on to third parties. * * @brief * */ /****************************************************************************** * Include Header Files ******************************************************************************/ #include "pressureController.h" #include "math.h" /****************************************************************************** * Macro constant declarations ******************************************************************************/ /****************************************************************************** * Type declarations ******************************************************************************/ /****************************************************************************** * Module Global Variable Declarations ******************************************************************************/ /****************************************************************************** * Private Function Declarations ******************************************************************************/ /****************************************************************************** * Extern Function Declarations ******************************************************************************/ void PuControllersInitInputs(PuControllersPidInput_st *pumpPin_pst) { /* === Pump RO Pressure === */ pumpPin_pst->kpGain_f32 = 6.0f; pumpPin_pst->kiGain_f32 = 5.0f; pumpPin_pst->kdGain_f32 = -3.0f; pumpPin_pst->satDeriv_f32 = 5.0f; pumpPin_pst->sampleTime_f32 = 0.1f; pumpPin_pst->commandMin_f32 = 0.0f; pumpPin_pst->commandMax_f32 = 100.0f; pumpPin_pst->regulatorActivation_f32 = 1.0f; pumpPin_pst->integralResetFlag_b = false; } void PuControllersPidLoop(const PuControllersPidInput_st *input_pst, PuControllersPidOutput_st *output_pst, PuControllersPidState_st *state_pst) { float32 derivTerm_f32; /* External Trigger */ if (input_pst->integralResetFlag_b) { state_pst->integState_f32 = 0.0f; } if(input_pst->regulatorActivation_f32 == 0.0f) { state_pst->prevMeasFilt2_f32 = 0.0f; state_pst->sumOutput_f32 = 0.0f; state_pst->integState_f32 = 0.0f; output_pst->derivOutput_f32 = 0.0f; output_pst->integOutput_f32 = 0.0f; output_pst->propOutput_f32 = 0.0f; } /* Check if the regulator control should be active */ if (input_pst->regulatorActivation_f32 > 0.0f) { /* If regulator was inactive previously, reset integral and derivative states */ if (!state_pst->isRegulatorActive_b) { state_pst->prevMeasFilt2_f32 = 0.0f; state_pst->integState_f32 = 0.0f; state_pst->isRegulatorActive_b = true; } /* Compute derivative component based on measurement change rate */ derivTerm_f32 = -(input_pst->measFilt2_f32 - state_pst->prevMeasFilt2_f32) * input_pst->kdGain_f32 / input_pst->sampleTime_f32; /* Apply saturation limits to derivative output to prevent excessive corrections */ if (derivTerm_f32 > input_pst->satDeriv_f32) { output_pst->derivOutput_f32 = input_pst->satDeriv_f32; } else if (derivTerm_f32 < -input_pst->satDeriv_f32) { output_pst->derivOutput_f32 = -input_pst->satDeriv_f32; } else { output_pst->derivOutput_f32 = derivTerm_f32; } /* Output current integral state */ output_pst->integOutput_f32 = state_pst->integState_f32; /* Compute proportional output based on setpoint error */ derivTerm_f32 = input_pst->setpoint_f32 - input_pst->measFilt_f32; if (fabsf(derivTerm_f32) > input_pst->tolerance_f32) { output_pst->propOutput_f32 = input_pst->kpGain_f32 * derivTerm_f32; } else { output_pst->propOutput_f32 = 0.0f; output_pst->derivOutput_f32 = 0.0; } /* Sum PID components to form the overall regulator output */ state_pst->sumOutput_f32 = output_pst->propOutput_f32 + output_pst->integOutput_f32 + output_pst->derivOutput_f32; /* Calculate integral contribution based on error */ derivTerm_f32 *= input_pst->kiGain_f32; /* Adjust integral contribution to respect command saturation limits */ if (state_pst->prevCommandInput_f32 >= input_pst->commandMax_f32) { derivTerm_f32 = (float32)(fmin((float64)derivTerm_f32, 0.0f)); } else if (input_pst->commandMin_f32 >= state_pst->prevCommandInput_f32) { derivTerm_f32 = (float32)(fmax(0.0f, (float64)derivTerm_f32)); } /* Update previous measurement for derivative calculation in next cycle */ state_pst->prevMeasFilt2_f32 = input_pst->measFilt2_f32; if (input_pst->kpGain_f32 == 0.0f)// I controller only { state_pst->integState_f32 += input_pst->sampleTime_f32 * derivTerm_f32; } /* Integrate integral term with adjusted contribution */ else { if (fabsf(output_pst->propOutput_f32 / input_pst->kpGain_f32) > input_pst->tolerance_f32) { state_pst->integState_f32 += input_pst->sampleTime_f32 * derivTerm_f32; } } } else if (state_pst->isRegulatorActive_b) { /* Disable regulator and reset summed output if regulator is deactivated */ state_pst->sumOutput_f32 = 0.0f; state_pst->isRegulatorActive_b = false; } /* Combine regulator output with feed-forward command to form total command */ derivTerm_f32 = input_pst->commandRm_f32 + state_pst->sumOutput_f32; /* Ensure final command output respects specified saturation limits */ if (derivTerm_f32 > input_pst->commandMax_f32) { output_pst->commandSetpoint_f32 = input_pst->commandMax_f32; } else if (derivTerm_f32 < input_pst->commandMin_f32) { output_pst->commandSetpoint_f32 = input_pst->commandMin_f32; } else { output_pst->commandSetpoint_f32 = derivTerm_f32; } /* Store last command to aid future saturation checks */ state_pst->prevCommandInput_f32 = derivTerm_f32; } /****************************************************************************** * Private Function Definitions ******************************************************************************/ /****************************************************************************** * Callback Function Definitions ******************************************************************************/