Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

convert signals to correct type before computations #7

Merged
merged 1 commit into from
Jun 29, 2023
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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "DiscretePIDs"
uuid = "c1363496-6848-4723-8758-079b737f6baf"
authors = ["Fredrik Bagge Carlson"]
version = "0.1.2"
version = "0.1.3"

[compat]
julia = "1.7"
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ u = calculate_control!(pid, r, y, uff)

The parameters $K, T_i, T_d$ may be updated using the functions, `set_K!, set_Ti!, set_Td!`.

The numeric type used by the controller (the `T` in `DiscretePID{T}`) is determined by the types of the parameters. To use a custom number type, e.g., a fixed-point number type, simply pass the parameters as that type, see example below. The controller will automatically convert measurements and references to this type before performing the control calculations.

## Example using ControlSystems:
The following example simulates the PID controller using ControlSystems.jl. We will simulate a load disturbance $d(t) = 1$ entering on the process input, while the reference is $r(t) = 0$.

Expand Down Expand Up @@ -125,7 +127,7 @@ pid = DiscretePID(; K = T(K), Ts = T(Ts), Ti = T(Ti), Td = T(Td))
res_fp = lsim(P, ctrl, Tf)
plot([res, res_fp], plotu=true, lab=["Float64" "" string(T) ""]); ylabel!("u + d", sp=2)
```
![Fixed-point simulation result](https://user-images.githubusercontent.com/3797491/249722782-2157d625-7eb0-4f77-b630-69199237f164.png)
![Fixed-point simulation result](https://user-images.githubusercontent.com/3797491/249732319-0a3890d5-cb9c-45c2-93c7-20d3c7db0cf2.png)

The fixed-point controller behaves roughly the same in this case, but artifacts are clearly visible. If the number of bits used for the fractional part is decreased, the controller will start to misbehave.

Expand Down
6 changes: 5 additions & 1 deletion src/DiscretePIDs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,12 @@ end
(pid)(r, y, uff=0) # Alternative syntax

Calculate the control output from the PID controller when `r` is the reference (set point), `y` is the latest measurement and `uff` is the feed-forward contribution.
If the type of the input arguments differ from the numeric type used by the PID controller, they will be converted before computations are performed.
"""
function calculate_control!(pid::DiscretePID, r, y, uff=0)
function calculate_control!(pid::DiscretePID{T}, r0, y0, uff0=0) where T
r = T(r0)
y = T(y0)
uff = T(uff0)
P = pid.K * (pid.b * r - y)
pid.D = pid.ad * pid.D - pid.bd * (y - pid.yold)
v = P + pid.I + pid.D + uff
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ res2 = lsim(P, ctrl, Tf)

## Test with FixedPointNumbers
using FixedPointNumbers
T = Fixed{Int16, 10} # 16-bit signed fixed-point with 11 bits for the fractional part
T = Fixed{Int16, 10} # 16-bit signed fixed-point with 10 bits for the fractional part
pid = DiscretePID(; K = T(K), Ts = T(Ts), Ti = T(Ti), Td = T(Td))
@test pid isa DiscretePID{T}

Expand Down