PI Controller oscillating between limit values

Hello,
I’m trying to implement a PI controller that turns on once the cell goes out of the voltage limits. My model looks something like this:

@mtkmodel Cell begin
...
    @components begin
...
        deadzone = DeadZone(u_max=4.1, u_min=2.6)
        feedback = Feedback()
        pi_controller = PI(k = 1, T = 0.01)
    end
    @equations begin
        deadzone.input.u ~ v
        feedback.input2.u ~ 0
        connect(deadzone.output, feedback.input1)
        connect(feedback.output, pi_controller.err_input)
        connect(output, pi_controller.ctr_output)
        #output.u ~ ifelse(feedback.output.u == 0, 0, pi_controller.ctr_output.u)
    end
end

@mtkmodel OneCell begin
    @components begin
...
        setpoint = RealOutput() 
        limiter = Limiter(y_max=4.8)
    end
    @equations begin
...
        limiter.input.u ~ setpoint.u - cell.output.u
        setpoint.u ~ i_profile(t)
    end
end

The problem is the PI is still turned on even when the feedback signal reaches 0 again, and only changes once the opposite limit is reached, like bouncing all the time between those values. Any ideas on how to turn it off when it is back in a safe range? Thanks :slight_smile:

I think you will have an easier time getting a good answer if you post code that runs and reproduces your issue, right now there’s too much guesswork required to know what’s wrong.

Hi, thank you for your answer. Here’s the complete code:

@mtkmodel ECM begin
    @extend OnePort()
    @parameters begin
        Q = 4.8
        R0 = 15e-3
        R1 = 15e-3
        τ1 = 60.0
        R2 = 15e-3
        τ2 = 600.0
    end
    @structural_parameters begin
        focv
    end
    @variables begin
        vr(t)
        v1(t) = 0
        v2(t) = 0
        ocv(t)
        soc(t) = 0.5
    end
    @equations begin
        D(soc) ~ i / (Q * 3600.0)
        D(v1) ~ -v1 / τ1 + i * (R1 / τ1)
        D(v2) ~ -v2 / τ2 + i * (R2 / τ2)
        vr ~ i * R0
        ocv ~ focv(soc)
        v ~ ocv + vr + v1 + v2
    end
end

@mtkmodel Cell begin
    @structural_parameters begin
        focv2
    end
    @extend v, i = cell = ECM(; focv=focv2)

    @components begin
        output = RealOutput()
        deadzone = DeadZone(u_max=4.1, u_min=2.6)
        feedback = Feedback()
        pi_controller = PI(k = 1, T = 0.01)
    end
    @equations begin
        deadzone.input.u ~ v
        feedback.input2.u ~ 0
        connect(deadzone.output, feedback.input1)
        connect(feedback.output, pi_controller.err_input)
        connect(output, pi_controller.ctr_output)
    end
end

i_profile = ConstantInterpolation(
    [-0.5, 0.0, 1.5, 0.0], # u
    [0, 6 * 3600, 8 * 3600, 10 * 3600]; # t
    extrapolation=ExtrapolationType.Constant
)

@mtkmodel OneCell begin
    @components begin
        cell = Cell(focv2=focv)
        # setpoint = Interpolation(fi)
        setpoint = RealOutput() 
        source = Current()
        ground = Ground()
        limiter = Limiter(y_max=4.8)
    end
    @equations begin
        connect(source.n, cell.p)
        connect(source.p, cell.n, ground.g)
        connect(limiter.output, source.I)
        limiter.input.u ~ setpoint.u - cell.output.u
        setpoint.u ~ i_profile(t)
    end
end

@mtkbuild sys1 = OneCell()

tspan = (0, 24 * 3600) 
prob1 = ODEProblem(sys1, Pair[], tspan)
sol = solve(prob1, Rodas5(), saveat=(0:24*3600))

You’re using positive feedback, have you switched the two inputs to the feedback block around or is this intentional?

This does not appear to be the case BTWm focv and ExtrapolationType are not defined.