# PI Controller oscillating between limit values

**URL:** <https://discourse.julialang.org/t/pi-controller-oscillating-between-limit-values/131510>\
**Category:** Specific Domains\
**Tags:** control, controlsystems, mtk, controlsystemsmtk\
**Created:** [August 10, 2025, 11:55am UTC](https://discourse.julialang.org/t/pi-controller-oscillating-between-limit-values/131510 "2025-08-10T11:55:24Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![madtorresga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/madtorresga/32/216920_2.png) [@madtorresga](https://discourse.julialang.org/u/madtorresga)\
**Post date:** [August 10, 2025, 11:55am UTC](https://discourse.julialang.org/t/pi-controller-oscillating-between-limit-values/131510/1 "2025-08-10T11:55:24Z")

</div>

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:

```julia-auto
@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 🙂

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [August 11, 2025, 9:52am UTC](https://discourse.julialang.org/t/pi-controller-oscillating-between-limit-values/131510/2 "2025-08-11T09:52:20Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![madtorresga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/madtorresga/32/216920_2.png) [@madtorresga](https://discourse.julialang.org/u/madtorresga)\
**Post date:** [August 11, 2025, 4:40pm UTC](https://discourse.julialang.org/t/pi-controller-oscillating-between-limit-values/131510/3 "2025-08-11T16:40:50Z")

</div>

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

```julia-auto
@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))

```

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [August 11, 2025, 4:49pm UTC](https://discourse.julialang.org/t/pi-controller-oscillating-between-limit-values/131510/4 "2025-08-11T16:49:16Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [August 12, 2025, 5:01am UTC](https://discourse.julialang.org/t/pi-controller-oscillating-between-limit-values/131510/5 "2025-08-12T05:01:23Z")

</div>

> [@madtorresga](#):
>
> Here’s the complete code:

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