- Index
- » Usage and Applications
- » OpenModelica Usage and Applications
- » How to model stops
How to model stops
How to model stops
Hi,
I want to model a stop for a cylinder, so when the piston hits the bottom there will be no further movement.
So I grabbed the sweptVolume model and added a little bit, so that when a certain position is reached a strong spring is kicking in and forces the piston to a hold.
I also found a model of a stop from an old Modelica Library, that sets position and velocity to zero, when the stop is reached. It forces the position and velocity to be state variables. I tried to replicate that in my model, which is currently commented out.
But neither of this ideas had satisfactory results. Now I am out of ideas, so I will be happy for every new idea of you.
Cylinder Code
Code:
model SweptVolumeWithStop "varying cylindric volume depending on the position of the piston"
import Modelica.Constants.pi;
import SI = Modelica.SIunits;
parameter SI.Area pistonCrossArea "cross sectional area of piston";
parameter SI.Volume clearance "remaining volume at zero piston stroke";
SI.Volume V "fluid volume";
//SI.Velocity v(stateSelect = StateSelect.always) "speed of piston";
SI.Force F_stop "";
//SI.Position ps(stateSelect = StateSelect.always) = flange.s;
//parameter SI.Position smin = Modelica.Constants.small;
//parameter SI.Position smax = 1;
parameter SI.ModulusOfElasticity E = 1e6;
// Mass and energy balance, ports
extends Modelica.Fluid.Vessels.BaseClasses.PartialLumpedVessel(final fluidVolume = V, heatTransfer(surfaceAreas = {pistonCrossArea + 2 * sqrt(pistonCrossArea * pi) * (flange.s + clearance / pistonCrossArea)}));
Modelica.Mechanics.Translational.Interfaces.Flange_b flange "translation flange for piston" annotation(Placement(transformation(extent = {{-10, 90}, {10, 110}}, rotation = 0)));
equation
//assert(flange.s >= 0, "Piston stroke (given by flange.s) must not be smaller than zero!");
//v = der(flange.s);
// volume size
V = clearance + flange.s * pistonCrossArea;
0 = flange.f + (medium.p - system.p_ambient) * pistonCrossArea + F_stop;
if flange.s <= clearance / pistonCrossArea then
F_stop = sqrt(0.5) * pistonCrossArea * E / 7e-3 * abs(flange.s - clearance / pistonCrossArea);
else
F_stop = 0;
end if;
// energy balances
Wb_flow = medium.p * pistonCrossArea * (-der(flange.s));
// definition of port pressures
for i in 1:nPorts loop
vessel_ps_static[i] = medium.p;
end for;
/*algorithm
when initial() then
assert(ps > smin or ps >= smin and v >= 0, "Error in initialization of hard stop. (s - L/2) must be >= smin ");
assert(ps < smax or ps <= smax and v <= 0, "Error in initialization of hard stop. (s + L/2) must be <= smax ");
end when;
when not ps < smax then
reinit(ps, smax);
if not initial() or v > 0 then
reinit(v, 0);
end if;
end when;
when not ps > smin then
reinit(ps, smin);
if not initial() or v < 0 then
reinit(v, 0);
end if;
end when;*/
annotation(Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}), graphics = {Rectangle(extent = {{-50, 36}, {50, -90}}, lineColor = {0, 0, 255}, pattern = LinePattern.None, lineThickness = 1, fillColor = {170, 213, 255}, fillPattern = FillPattern.Solid), Polygon(points = {{-52, 62}, {-48, 62}, {-48, -30}, {-52, -30}, {-52, 62}}, lineColor = {95, 95, 95}, smooth = Smooth.None, fillColor = {135, 135, 135}, fillPattern = FillPattern.Backward), Polygon(points = {{48, 60}, {52, 60}, {52, -34}, {48, -34}, {48, 60}}, lineColor = {95, 95, 95}, smooth = Smooth.None, fillColor = {135, 135, 135}, fillPattern = FillPattern.Backward), Rectangle(extent = {{-48, 40}, {48, 30}}, lineColor = {95, 95, 95}, fillColor = {135, 135, 135}, fillPattern = FillPattern.Forward), Rectangle(extent = {{-6, 92}, {6, 40}}, lineColor = {95, 95, 95}, fillColor = {135, 135, 135}, fillPattern = FillPattern.Forward), Polygon(points = {{-48, -90}, {48, -90}, {48, 70}, {52, 70}, {52, -94}, {-52, -94}, {-52, 70}, {-48, 70}, {-48, -90}}, lineColor = {95, 95, 95}, smooth = Smooth.None, fillColor = {135, 135, 135}, fillPattern = FillPattern.Backward), Line(visible = use_HeatTransfer, points = {{-100, 0}, {-52, 0}}, smooth = Smooth.None, color = {198, 0, 0})}));
end SweptVolumeWithStop;
Code of test environment
Code:
model test_cylinder
inner Modelica.Fluid.System system annotation(Placement(visible = true, transformation(origin = {72, -70}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Fluid.Sources.Boundary_pT boundary(p = 200000, nPorts = 1, redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater) annotation(Placement(visible = true, transformation(origin = {-70, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Fluid.Pipes.StaticPipe pipe(length = 20, diameter = 0.01, redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater) annotation(Placement(visible = true, transformation(origin = {-28, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
SweptVolumeWithStop sweptvolumewithstop1(pistonCrossArea = 1, clearance = 2e-7, nPorts = 1, use_portsData = false, redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater) annotation(Placement(visible = true, transformation(origin = {30, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Mechanics.Translational.Components.InitializeFlange initializeflange1(use_s_start = true, use_v_start = false, use_a_start = false) annotation(Placement(visible = true, transformation(origin = {70, 70}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Blocks.Sources.Constant const(k = 1e-3) annotation(Placement(visible = true, transformation(origin = {70, 44}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Mechanics.Translational.Sources.Force force1 annotation(Placement(visible = true, transformation(origin = {-2, 90}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Sources.Ramp ramp1(height = -3e6, duration = 50) annotation(Placement(visible = true, transformation(origin = {-50, 90}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
connect(ramp1.y, force1.f) annotation(Line(points = {{-39, 90}, {-14, 90}, {-14, 90}, {-14, 90}}, color = {0, 0, 127}));
connect(force1.flange, sweptvolumewithstop1.flange) annotation(Line(points = {{8, 90}, {30, 90}, {30, 60}, {30, 60}}, color = {0, 127, 0}));
connect(const.y, initializeflange1.s_start) annotation(Line(points = {{81, 44}, {94, 44}, {94, 76}, {84, 76}, {84, 76}}, color = {0, 0, 127}));
connect(initializeflange1.flange, sweptvolumewithstop1.flange) annotation(Line(points = {{60, 70}, {30, 70}, {30, 60}, {30, 60}}, color = {0, 127, 0}));
connect(pipe.port_b, sweptvolumewithstop1.ports[1]) annotation(Line(points = {{-18, 30}, {30, 30}, {30, 40}, {30, 40}}, color = {0, 127, 255}));
connect(boundary.ports[1], pipe.port_a) annotation(Line(points = {{-60, 30}, {-38, 30}, {-38, 30}, {-38, 30}}, color = {0, 127, 255}));
annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {2, 2})), Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {2, 2})), experiment(StartTime = 0, StopTime = 50, Tolerance = 0.0001, Interval = 0.1));
end test_cylinder;
Models of old Modelica Library (I guess)
Code:
model Stop "Sliding mass with hard stop and Stribeck friction"
extends FrictionBase(s(stateSelect = StateSelect.always));
Modelica.SIunits.Velocity v(stateSelect = StateSelect.always) "Absolute velocity of flange_a and flange_b";
Modelica.SIunits.Acceleration a "Absolute acceleration of flange_a and flange_b";
parameter Modelica.SIunits.Mass m = 1 "mass";
parameter Real F_prop(final unit = "N/ (m/s)", final min = 0) = 1 "velocity dependent friction";
parameter Modelica.SIunits.Force F_Coulomb = 5 "constant friction: Coulomb force";
parameter Modelica.SIunits.Force F_Stribeck = 10 "Stribeck effect";
parameter Real fexp(final unit = "1/ (m/s)", final min = 0) = 2 "exponential decay";
equation
// Constant auxiliary variables
f0 = F_Coulomb + F_Stribeck;
f0_max = f0 * 1.001;
free = f0 <= 0 and F_prop <= 0 and s > smin + L / 2 and s < smax - L / 2;
// Velocity and acceleration of flanges
v = der(s);
a = der(v);
v_relfric = v;
a_relfric = a;
// Equilibrium of forces
0 = flange_a.f + flange_b.f - f - m * der(v);
// Friction force
f = if locked then sa else if free then 0 else if startForward then F_prop * v + F_Coulomb + F_Stribeck else if startBackward then F_prop * v - F_Coulomb - F_Stribeck else if pre(mode) == Forward then F_prop * v + F_Coulomb + F_Stribeck * exp(-fexp * abs(v)) else F_prop * v - F_Coulomb - F_Stribeck * exp(-fexp * abs(v));
// Define events for hard stops and reinitiliaze the state variables velocity v and position s
algorithm
when initial() then
assert(s > smin + L / 2 or s >= smin + L / 2 and v >= 0, "Error in initialization of hard stop. (s - L/2) must be >= smin ");
assert(s < smax - L / 2 or s <= smax - L / 2 and v <= 0, "Error in initialization of hard stop. (s + L/2) must be <= smax ");
end when;
when not s < smax - L / 2 then
reinit(s, smax - L / 2);
if not initial() or v > 0 then
reinit(v, 0);
end if;
end when;
when not s > smin + L / 2 then
reinit(s, smin + L / 2);
if not initial() or v < 0 then
reinit(v, 0);
end if;
end when;
end Stop;
And the BaseClass of this
Code:
partial model FrictionBase "Base class of Coulomb friction elements"
extends Modelica.Mechanics.Translational.Interfaces.PartialRigid;
import SI = Modelica.SIunits;
parameter SI.Position smax = 25 "right stop for (right end of) sliding mass";
parameter SI.Position smin = -25 "left stop for (left end of) sliding mass";
parameter SI.Velocity v_small = 1e-3 "Relative velocity near to zero (see model info text)";
// Equations to define the following variables have to be defined in subclasses
SI.Velocity v_relfric "Relative velocity between frictional surfaces";
SI.Acceleration a_relfric "Relative acceleration between frictional surfaces";
SI.Force f "Friction force (positive, if directed in opposite direction of v_rel)";
SI.Force f0 "Friction force for v=0 and forward sliding";
SI.Force f0_max "Maximum friction force for v=0 and locked";
Boolean free "true, if frictional element is not active";
// Equations to define the following variables are given in this class
Real sa "Path parameter of friction characteristic f = f(a_relfric)";
Boolean startForward "true, if v_rel=0 and start of forward sliding or v_rel > v_small";
Boolean startBackward "true, if v_rel=0 and start of backward sliding or v_rel < -v_small";
Boolean locked "true, if v_rel=0 and not sliding";
constant Integer Unknown = 3 "Value of mode is not known";
constant Integer Free = 2 "Element is not active";
constant Integer Forward = 1 "v_rel > 0 (forward sliding)";
constant Integer Stuck = 0 "v_rel = 0 (forward sliding, locked or backward sliding)";
constant Integer Backward = -1 "v_rel < 0 (backward sliding)";
Integer mode(final min = Backward, final max = Unknown, start = Unknown);
equation
/* Friction characteristic
(locked is introduced to help the Modelica translator determining
the different structural configurations, if for each configuration
special code shall be generated)
*/
startForward = pre(mode) == Stuck and (sa > f0_max and s < smax - L / 2 or pre(startForward) and sa > f0 and s < smax - L / 2) or pre(mode) == Backward and v_relfric > v_small or initial() and v_relfric > 0;
startBackward = pre(mode) == Stuck and (sa < (-f0_max) and s > smin + L / 2 or pre(startBackward) and sa < (-f0) and s > smin + L / 2) or pre(mode) == Forward and v_relfric < (-v_small) or initial() and v_relfric < 0;
locked = not free and not (pre(mode) == Forward or startForward or pre(mode) == Backward or startBackward);
a_relfric = if locked then 0 else if free then sa else if startForward then sa - f0 else if startBackward then sa + f0 else if pre(mode) == Forward then sa - f0 else sa + f0;
/* Friction torque has to be defined in a subclass. Example for a clutch:
f = if locked then sa else if free then 0 else cgeo*fn*
(if startForward then Math.tempInterpol1( w_relfric, mue_pos, 2)
else if startBackward then -Math.tempInterpol1(-w_relfric, mue_pos, 2)
else if pre(mode) == Forward then Math.tempInterpol1(w_relfric, mue_pos, 2)
else -Math.tempInterpol1(-w_relfric, mue_pos, 2));
*/
// finite state machine to determine configuration
mode = if free then Free else if (pre(mode) == Forward or pre(mode) == Free or startForward) and v_relfric > 0 and s < smax - L / 2 then Forward else if (pre(mode) == Backward or pre(mode) == Free or startBackward) and v_relfric < 0 and s > smin + L / 2 then Backward else Stuck;
end FrictionBase;
- MProp
- 14 Posts
- Index
- » Usage and Applications
- » OpenModelica Usage and Applications
- » How to model stops