Skip to content

Commit 1ac5485

Browse files
adds DC motor with friction
adds speed sensor test adds DC motor test in runtests.jl adds test for speed sensor adds rel. speed sensor adds tests adds comment adds parameter checks adds ViscousFriction adds checks for return codes Update analog.jl Update rotational.jl fix test adds missing default value add missing link to tutorial Update Electrical.jl fixes voltage source
1 parent 538fb2b commit 1ac5485

File tree

17 files changed

+702
-78
lines changed

17 files changed

+702
-78
lines changed

Project.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ version = "1.4.0"
77
IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
88
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
99
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
10-
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
1110
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
1211

1312
[compat]
@@ -19,8 +18,11 @@ Symbolics = "0.1, 1, 2, 3, 4"
1918
julia = "1.6"
2019

2120
[extras]
21+
DASSL = "e993076c-0cfd-5d6b-a1ac-36489fdf7917"
2222
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
23+
Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4"
24+
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
2325
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
2426

2527
[targets]
26-
test = ["SafeTestsets", "Test"]
28+
test = ["DASSL", "SafeTestsets", "Sundials", "OrdinaryDiffEq", "Test"]

src/Blocks/Blocks.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
The module `Blocks` contains common input-output components, referred to as blocks.
33
"""
44
module Blocks
5-
using ModelingToolkit, Symbolics, OrdinaryDiffEq
5+
using ModelingToolkit, Symbolics
66
using IfElse: ifelse
77

88
@parameters t

src/Electrical/Analog/ideal_components.jl

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,77 @@ function Short(; name)
161161
@unpack v, i = oneport
162162
eqs = [v ~ 0]
163163
extend(ODESystem(eqs, t, [], []; name=name), oneport)
164+
165+
"""
166+
HeatingResistor(;name, R_ref=1.0, T_ref=300.15, alpha=0)
167+
168+
Temperature dependent electrical resistor
169+
170+
# States
171+
- See [OnePort](@ref)
172+
- `R(t)`: [`Ω`] Temperature dependent resistance `R ~ R_ref*(1 + alpha*(heat_port.T(t) - T_ref))`
173+
174+
# Connectors
175+
- `p` Positive pin
176+
- `n` Negative pin
177+
178+
# Parameters:
179+
- `R_ref`: [`Ω`] Reference resistance
180+
- `T_ref`: [K] Reference temperature
181+
"""
182+
function HeatingResistor(;name, R_ref=1.0, T_ref=300.15, alpha=0)
183+
@named oneport = OnePort()
184+
@unpack v, i = oneport
185+
@named heat_port = HeatPort()
186+
pars = @parameters begin
187+
R_ref=R_ref
188+
T_ref=T_ref
189+
alpha=alpha
190+
end
191+
@variables R
192+
eqs = [
193+
R ~ R_ref*(1 + alpha*(heat_port.T - T_ref))
194+
heat_port.Q_flow ~ -v * i # -LossPower
195+
v ~ i * R
196+
]
197+
extend(ODESystem(eqs, t, [R], pars; name=name, systems=[heat_port]), oneport)
198+
end
199+
200+
"""
201+
EMF(;name, k)
202+
203+
Electromotoric force (electric/mechanic transformer)
204+
205+
# States
206+
- `v(t)`: [`V`] The voltage across component `p.v - n.v`
207+
- `i(t)`: [`A`] The current passing through positive pin
208+
- `phi`: [`rad`] Rotation angle (=flange.phi - support.phi)
209+
- `w`: [`rad/s`] Angular velocity (= der(phi))
210+
211+
# Connectors
212+
- `p` Positive pin
213+
- `n` Negative pin
214+
- `flange` Shaft of EMF shaft
215+
- `support` Support/housing of emf shaft
216+
217+
# Parameters:
218+
- `k`: [`N⋅m/A`] Transformation coefficient
219+
"""
220+
function EMF(;name, k)
221+
@named p = Pin()
222+
@named n = Pin()
223+
@named flange = Flange()
224+
@named support = Support()
225+
@parameters k=k
226+
@variables v(t)=0.0 i(t)=0.0 phi(t)=0.0 w(t)=0.0
227+
eqs = [
228+
v ~ p.v - n.v
229+
0 ~ p.i + n.i
230+
i ~ p.i
231+
phi ~ flange.phi - support.phi
232+
D(phi) ~ w
233+
k*w ~ v
234+
flange.tau ~ -k*i
235+
]
236+
ODESystem(eqs, t, [v, i, phi, w], [k]; name=name, systems=[p, n, flange, support])
164237
end

src/Electrical/Electrical.jl

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,27 @@ This library contains electrical components to build up analog circuits.
44
"""
55
module Electrical
66

7-
using ModelingToolkit, Symbolics, IfElse, OrdinaryDiffEq
7+
using ModelingToolkit, Symbolics, IfElse
88
using OffsetArrays
9+
using ..Thermal: HeatPort
10+
using ..Mechanical.Rotational: Flange, Support
11+
using ..Blocks: RealInput, RealOutput
912

1013
@parameters t
1114
D = Differential(t)
1215

13-
using ..Blocks: RealInput, RealOutput
14-
16+
export Pin, OnePort
1517
include("utils.jl")
18+
19+
export Capacitor, Ground, Inductor, Resistor, Short, IdealOpAmp, EMF
1620
include("Analog/ideal_components.jl")
21+
22+
export CurrentSensor, PotentialSensor, VoltageSensor, PowerSensor, MultiSensor
1723
include("Analog/sensors.jl")
24+
25+
export Voltage, Current
1826
include("Analog/sources.jl")
27+
1928
# include("Digital/components.jl")
2029
# include("Digital/gates.jl")
2130
# include("Digital/tables.jl")
@@ -26,23 +35,4 @@ include("Analog/sources.jl")
2635
# - machines
2736
# - multi-phase
2837

29-
export #Interface
30-
Pin,
31-
# Analog Components
32-
Capacitor, Ground, Inductor, Resistor, Conductor,
33-
Short, IdealOpAmp,
34-
# Analog Sensors
35-
CurrentSensor, PotentialSensor, VoltageSensor,
36-
PowerSensor, MultiSensor,
37-
# Analog Sources
38-
Voltage, Current
39-
40-
41-
# # Digital Gates
42-
# And, Or, Not, Xor, Nand, Nor, Xnor,
43-
# # Digital components
44-
# HalfAdder, FullAdder, MUX, DEMUX, Encoder, Decoder,
45-
# # Digital Sources
46-
# DigitalPin, Pulse, PulseDiff
47-
4838
end

src/Mechanical/Rotational/Rotational.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@ Library to model 1-dimensional, rotational mechanical systems
33
"""
44
module Rotational
55

6-
using ModelingToolkit, Symbolics, IfElse, OrdinaryDiffEq
6+
using ModelingToolkit, Symbolics, IfElse
77
using OffsetArrays
88
using ...Blocks: RealInput, RealOutput
99

1010
@parameters t
1111
D = Differential(t)
1212

13-
export Flange
13+
export Flange, Support
1414
include("utils.jl")
1515

16-
export Fixed, Inertia, Spring, Damper, IdealGear
16+
export Fixed, Inertia, Spring, Damper, IdealGear, RotationalFriction, ViscousFriction
1717
include("components.jl")
1818

19-
export Torque
19+
export Torque, Speed
2020
include("sources.jl")
2121

22+
export AngleSensor, SpeedSensor, TorqueSensor, RelSpeedSensor
23+
include("sensors.jl")
24+
2225
end

src/Mechanical/Rotational/components.jl

Lines changed: 96 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,43 @@
33
44
Flange fixed in housing at a given angle.
55
6+
# Connectors:
7+
- `flange` flange
8+
69
# Parameters:
710
- `phi0`: [rad] Fixed offset angle of housing
811
"""
912
function Fixed(;name, phi0=0.0)
1013
@named flange = Flange()
11-
@parameters phi0=phi0
14+
# @parameters phi0=phi0
1215
eqs = [flange.phi ~ phi0]
13-
return compose(ODESystem(eqs, t, [], [phi0]; name=name), flange)
16+
return compose(ODESystem(eqs, t, [], []; name=name), flange)
1417
end
1518

1619
"""
1720
Inertia(;name, J, phi_start=0.0, w_start=0.0, a_start=0.0)
1821
1922
1D-rotational component with inertia.
2023
24+
# States:
25+
- `phi`: [rad] Absolute rotation angle of component
26+
- `w`: [rad/s] Absolute angular velocity of component (= der(phi))
27+
- `a`: [rad/s²] Absolute angular acceleration of component (= der(w))
28+
29+
# Connectors:
30+
- `flange_a` Left flange
31+
- `flange_b` Right flange
32+
2133
# Parameters:
2234
- `J`: [kg·m²] Moment of inertia
2335
- `phi_start`: [rad] Initial value of absolute rotation angle of component
2436
- `w_start`: [rad/s] Initial value of absolute angular velocity of component
2537
- `a_start`: [rad/s²] Initial value of absolute angular acceleration of component
26-
27-
# States:
28-
- `phi`: [rad] Absolute rotation angle of component
29-
- `w`: [rad/s] Absolute angular velocity of component (= der(phi))
30-
- `a`: [rad/s²] Absolute angular acceleration of component (= der(w))
3138
"""
3239
function Inertia(;name, J, phi_start=0.0, w_start=0.0, a_start=0.0)
3340
@named flange_a = Flange()
3441
@named flange_b = Flange()
42+
J > 0 || throw(ArgumentError("Expected `J` to be positive"))
3543
@parameters J=J
3644
sts = @variables begin
3745
phi(t)=phi_start
@@ -53,13 +61,20 @@ end
5361
5462
Linear 1D rotational spring
5563
64+
# States:
65+
- See [PartialCompliant](@ref)
66+
67+
# Connectors:
68+
- See [PartialCompliant](@ref)
69+
5670
# Parameters:
5771
- `c`: [N.m/rad] Spring constant
5872
- `phi_rel0`: Unstretched spring angle
5973
"""
6074
function Spring(;name, c, phi_rel0=0.0)
6175
@named partial_comp = PartialCompliant()
6276
@unpack phi_rel, tau = partial_comp
77+
c > 0 || throw(ArgumentError("Expected `c` to be positive"))
6378
pars = @parameters begin
6479
c=c
6580
phi_rel0=phi_rel0
@@ -73,12 +88,19 @@ end
7388
7489
Linear 1D rotational damper
7590
91+
# States:
92+
- See [PartialCompliantWithRelativeStates](@ref)
93+
94+
# Connectors:
95+
- See [PartialCompliantWithRelativeStates](@ref)
96+
7697
# Parameters:
7798
- `d`: [N.m.s/rad] Damping constant
7899
"""
79100
function Damper(;name, d)
80101
@named partial_comp = PartialCompliantWithRelativeStates()
81102
@unpack w_rel, tau = partial_comp
103+
d > 0 || throw(ArgumentError("Expected `d` to be positive"))
82104
pars = @parameters d=d
83105
eqs = [tau ~ d*w_rel]
84106
extend(ODESystem(eqs, t, [], pars; name=name), partial_comp)
@@ -98,6 +120,7 @@ This element characterizes any type of gear box which is fixed in the ground and
98120
function IdealGear(;name, ratio, use_support=false)
99121
@named partial_element = PartialElementaryTwoFlangesAndSupport2(use_support=use_support)
100122
@unpack phi_support, flange_a, flange_b = partial_element
123+
ratio > 0 || throw(ArgumentError("Expected `ratio` to be positive"))
101124
@parameters ratio=ratio
102125
sts = @variables phi_a(t)=0.0 phi_b(t)=0.0
103126
eqs = [
@@ -107,4 +130,70 @@ function IdealGear(;name, ratio, use_support=false)
107130
0 ~ ratio*flange_a.tau + flange_b.tau
108131
]
109132
extend(ODESystem(eqs, t, sts, [ratio]; name=name), partial_element)
133+
end
134+
135+
"""
136+
RotationalFriction(;name, f, tau_c, w_brk, tau_brk)
137+
138+
Models rotational friction with Stribeck effect, Coulomb friction and viscous friction between the two flanges.
139+
The friction torque is a function of the relative angular velocity between flange_a and flange_b.
140+
141+
Friction model: "Armstrong, B. and C.C. de Wit, Friction Modeling and Compensation, The Control Handbook, CRC Press, 1995."
142+
143+
# States:
144+
- see [`PartialCompliantWithRelativeStates`](@ref)
145+
146+
# Connectors:
147+
- See [`PartialCompliantWithRelativeStates`](@ref)
148+
149+
# Parameters:
150+
- `f`: [`N⋅m/(rad/s)`] Viscous friction coefficient
151+
- `tau_c`: [`N⋅m`] Coulomb friction torque
152+
- `w_brk`: [`rad/s`] Breakaway friction velocity
153+
- `tau_brk`: [`N⋅m`] Breakaway friction torque
154+
"""
155+
function RotationalFriction(;name, f, tau_c, w_brk, tau_brk)
156+
@named partial_comp = PartialCompliantWithRelativeStates()
157+
@unpack w_rel, tau = partial_comp
158+
w_brk > 0 || throw(ArgumentError("Expected `w_brk` to be positive"))
159+
tau_brk > 0 || throw(ArgumentError("Expected `tau_brk` to be positive"))
160+
tau_c > 0 || throw(ArgumentError("Expected `tau_c` to be positive"))
161+
tau_c <= tau_brk || throw(ArgumentError("`tau_brk` to be greater than `tau_c`"))
162+
f >= 0 || throw(ArgumentError("Expected `f` to be not negative"))
163+
pars = @parameters f=f tau_c=tau_c w_brk=w_brk tau_brk=tau_brk
164+
165+
str_scale = sqrt(2*exp(1)) * (tau_brk - tau_c)
166+
w_st = w_brk * sqrt(2)
167+
w_coul = w_brk / 10
168+
169+
eqs = [
170+
tau ~ str_scale * (exp(-(w_rel/w_st)^2) * w_rel / w_st) + tau_c * tanh(w_rel / w_coul) + f * w_rel # Stribeck friction + Coulomb friction + Viscous friction
171+
]
172+
extend(ODESystem(eqs, t, [], pars; name=name), partial_comp)
173+
end
174+
175+
"""
176+
ViscousFriction(;name, f)
177+
178+
Models rotational viscous friction between the two flanges.
179+
The friction torque is a function of the relative angular velocity between flange_a and flange_b.
180+
# States:
181+
- see [`PartialCompliantWithRelativeStates`](@ref)
182+
183+
# Connectors:
184+
- See [`PartialCompliantWithRelativeStates`](@ref)
185+
186+
# Parameters:
187+
- `f`: [`N⋅m/(rad/s)`] Viscous friction coefficient
188+
"""
189+
function ViscousFriction(;name, f)
190+
@named partial_comp = PartialCompliantWithRelativeStates()
191+
@unpack w_rel, tau = partial_comp
192+
f >= 0 || throw(ArgumentError("Expected `f` to be not negative"))
193+
pars = @parameters f=f
194+
195+
eqs = [
196+
tau ~ f * w_rel # Viscous friction
197+
]
198+
extend(ODESystem(eqs, t, [], pars; name=name), partial_comp)
110199
end

0 commit comments

Comments
 (0)