Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/ModelingToolkitSampledData.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export DiscreteIntegrator, DiscreteDerivative, Delay, Difference, ZeroOrderHold,
DiscretePIDParallel, DiscretePIDStandard, DiscreteStateSpace,
DiscreteTransferFunction, NormalNoise, UniformNoise, Quantization,
ExponentialFilter
export DiscreteOnOffController
include("discrete_blocks.jl")

end
40 changes: 40 additions & 0 deletions src/discrete_blocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -971,3 +971,43 @@ Exponential filtering with input-output relation ``y(z) ~ (1 - a) y(z-1) + a u(z
end
end

"""
DiscreteOnOffController(b = 0.1, bool = true)

Discrete-time On-Off controller with hysteresis. The controller switches between two states based on the error signal `reference-input`. The controller is in the on-state if the error signal is within the bandwidth `b` around the reference signal, and in the off-state otherwise.

# Connectors:
- `reference`: The reference signal to the controller
- `input`: The measurement feedback
- `output`: The control signal output

# Parameters:
- `b`: Bandwidth around reference signal within which the controller does not react
- `bool`: (structural) If true (default), the controller switches between 0 and 1. If false, the controller switches between -1 and 1.
- `k`: Controller gain. The output of the contorller is scaled by this gain, i.e., `k = 2, bool = false` will result in an output of -2 or 2.
"""
@mtkmodel DiscreteOnOffController begin
@extend u, y = siso = SISO()
@components begin
reference = RealInput()
end
@structural_parameters begin
z = ShiftIndex()
bool = true
end
@parameters begin
b = 0.1, [description = "Bandwidth around reference signal"]
k = 1, [description = "Controller gain"]
end
@variables begin
s(t)=true, [description = "Internal variable"]
end
@equations begin
s(z) ~ (y(z-1) == k) & (u(z) < reference.u(z) + b/2) | (u(z) < reference.u(z) - b/2)
if bool
y(z) ~ k*s(z)
else
y(z) ~ k*(2*s(z) - 1)
end
end
end
27 changes: 27 additions & 0 deletions test/test_discrete_blocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,33 @@ end
@test 0 ∈ uy
end

@testset "OnOff" begin
@info "Testing OnOff"
cl = Clock(0.1)
z = ShiftIndex(cl)
@mtkmodel OnOffModel begin
@components begin
onoff = DiscreteOnOffController(; z, bool=false)
c = Constant(k=1)
end
@variables begin
x(t) = 0
end
@equations begin
onoff.u ~ Sample(cl)(x)
connect(c.output, onoff.reference)
D(x) ~ 0.1x + Hold(onoff.y)
end
end
@named m = OnOffModel()
m = complete(m)
ssys = structural_simplify(IRSystem(m))
prob = ODEProblem(ssys, [m.onoff.y(z-1) => 0], (0.0, 4.0))
sol = solve(prob, Tsit5(), dtmax=0.1)
# plot(sol, idxs=[m.x, m.onoff.y], title="On-off control of an unstable first-order system")
@test 0.89 <= sol(4, idxs=m.x) <= 1.11
end


@testset "ExponentialFilter" begin
@info "Testing ExponentialFilter"
Expand Down
Loading