diff --git a/Modelica/Blocks/Math.mo b/Modelica/Blocks/Math.mo index c2c5d3fa36..fedd484716 100644 --- a/Modelica/Blocks/Math.mo +++ b/Modelica/Blocks/Math.mo @@ -1930,6 +1930,104 @@ Otherwise the input angle u is wrapped to the ")); end WrapAngle; + block UnwrapAngle "Angle tracking observer" + extends Modelica.Blocks.Interfaces.SISO(u(final unit="rad", displayUnit="deg"), + y(final unit="rad", displayUnit="deg")); + Modelica.Blocks.Interfaces.RealOutput w(final unit="rad/s", displayUnit="rpm") + "Angular velocity" + annotation (Placement(transformation(extent={{100,-70},{120,-50}}))); + parameter Modelica.Units.SI.Time Ti=1e-6 "Integral time constant of controller"; + parameter Modelica.Units.SI.Angle phi0=0 "Initial angle"; + Modelica.Blocks.Math.Cos cos1 + annotation (Placement(transformation(extent={{-70,-30},{-50,-10}}))); + Modelica.Blocks.Math.Sin sin1 + annotation (Placement(transformation(extent={{-70,10},{-50,30}}))); + Modelica.Electrical.Machines.SpacePhasors.Blocks.Rotator rotator + annotation (Placement(transformation(extent={{-30,10},{-10,-10}}))); + Modelica.Blocks.Continuous.Integrator integralController( + k=1, + initType=Modelica.Blocks.Types.Init.InitialOutput, + y_start=phi0) + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Modelica.Blocks.Math.Gain gain(k=1/Ti) + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + equation + connect(u, sin1.u) annotation (Line(points={{-120,0},{-80,0},{-80,20},{-72,20}}, + color={0,0,127})); + connect(u, cos1.u) annotation (Line(points={{-120,0},{-80,0},{-80,-20},{-72,-20}}, + color={0,0,127})); + connect(integralController.y,rotator. angle) annotation (Line(points={{61,0},{ + 80,0},{80,20},{-20,20},{-20,12}}, color={0,0,127})); + connect(gain.y,integralController. u) + annotation (Line(points={{21,0},{38,0}}, color={0,0,127})); + connect(rotator.y[2],gain. u) + annotation (Line(points={{-9,0},{-2,0}}, color={0,0,127})); + connect(sin1.y, rotator.u[2]) annotation (Line(points={{-49,20},{-40,20},{-40, + 0},{-32,0}}, color={0,0,127})); + connect(cos1.y, rotator.u[1]) annotation (Line(points={{-49,-20},{-40,-20},{-40, + 0},{-32,0}}, color={0,0,127})); + connect(integralController.y, y) + annotation (Line(points={{61,0},{110,0}}, color={0,0,127})); + connect(gain.y, w) annotation (Line(points={{21,0},{30,0},{30,-60},{110,-60}}, + color={0,0,127})); + annotation ( + Icon(graphics={ + Polygon( + points={{0,90},{-8,68},{8,68},{0,90}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line(points={{0,-80},{0,68}}, color={192,192,192}), + Polygon( + points={{90,0},{68,8},{68,-8},{90,0}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line(points={{-90,0},{68,0}}, color={192,192,192}), + Line(points={{-72,20},{-72,20},{-40,60},{-40,-40},{40,60},{40,-60},{56,-40}}), + Line( + points={{56,80},{-72,-80}}, + color={0,0,127}, + thickness=0.5)}), + Documentation(info=" +

+This block "unwraps" the input angle u having time discontinuities. +Such discontinuities are typical for angles exceeding interval limits, +e.g. ]-π, π], cf. +Modelica.Blocks.Math.WrapAngle. +The output angle y approximates the input angle u in continuous matter. +

+

+The used calculation method is based on an angle tracking observer as common in electrical +engineering. This implementation is very robust. +It determines the angle of a space phasor calculating cos(u) and +sin(u) of a wrapped angle u – independent of the +angle interval. Note: the angles are often wrapped within the interval ]-π, +π] or +[0, 2π[. +

+

+The angle of a complex space phasor is controlled in such a way that its imaginary part is equal to zero. +The controlled angle y is the unwrapped continuous angle. +The output y approximates the desired angle by a first order system +which time constant is the integral time constant of the controller: +

+
+Im(ej*(u-y)) = sin(u - y)
+
+

+This expression can be approximated for small differences by +(u - y). +Using an integral controller, the transfer function of the closed loop can, thus, be +determined as: +y = u / (1 + s*Ti). +

+

+The derivative of the output y is the angular velocity w, +provided as an output signal as well. +

+")); + end UnwrapAngle; + block RealToInteger "Convert Real to Integer signal" extends Modelica.Blocks.Icons.IntegerBlock; public diff --git a/Modelica/Blocks/package.mo b/Modelica/Blocks/package.mo index 2190133239..e10e9c6487 100644 --- a/Modelica/Blocks/package.mo +++ b/Modelica/Blocks/package.mo @@ -1447,6 +1447,76 @@ If desired, the angle can be wrapped to the interval [-π, +π]. ")); end SinCosEncoder; + model DemoUnwrapAngle "Demonstrate unwrap angle" + extends Modelica.Icons.Example; + import Modelica.Constants.pi; + Modelica.Blocks.Sources.Trapezoid refFrequency( + amplitude=100, + rising=1, + width=0.5, + falling=1, + period=3, + nperiod=2, + offset=-50, + startTime=-0.5) + annotation (Placement(transformation(extent={{-70,22},{-50,42}}))); + Modelica.Blocks.Continuous.Integrator f2pos(k=2*pi, y_start=0) + annotation (Placement(transformation(extent={{-40,22},{-20,42}}))); + Modelica.Mechanics.Rotational.Sources.Position position(exact=true) + annotation (Placement(transformation(extent={{-10,22},{10,42}}))); + Modelica.Mechanics.Rotational.Sensors.AngleSensor angleSensor + annotation (Placement(transformation(extent={{20,22},{40,42}}))); + Modelica.Blocks.Math.UnwrapAngle unwrapAngle + annotation (Placement(transformation(extent={{22,-50},{42,-30}}))); + Modelica.Blocks.Math.Cos cos1 + annotation (Placement(transformation(extent={{-50,-70},{-30,-50}}))); + Modelica.Blocks.Math.Sin sin1 + annotation (Placement(transformation(extent={{-50,-30},{-30,-10}}))); + Modelica.Blocks.Math.Atan2 atan2_1 + annotation (Placement(transformation(extent={{-10,-50},{10,-30}}))); + Modelica.Mechanics.Rotational.Sensors.SpeedSensor speedSensor + annotation (Placement(transformation(extent={{20,50},{40,70}}))); + equation + connect(f2pos.y, position.phi_ref) + annotation (Line(points={{-19,32},{-12,32}}, + color={0,0,127})); + connect(position.flange, angleSensor.flange) + annotation (Line(points={{10,32},{20,32}}, color={0,0,0})); + connect(refFrequency.y, f2pos.u) + annotation (Line(points={{-49,32},{-42,32}}, + color={0,0,127})); + connect(angleSensor.phi, sin1.u) annotation (Line(points={{41,32},{50,32},{50, + 0},{-60,0},{-60,-20},{-52,-20}}, color={0,0,127})); + connect(angleSensor.phi, cos1.u) annotation (Line(points={{41,32},{50,32},{50, + 0},{-60,0},{-60,-60},{-52,-60}}, color={0,0,127})); + connect(sin1.y, atan2_1.u1) annotation (Line(points={{-29,-20},{-20,-20},{-20, + -34},{-12,-34}}, color={0,0,127})); + connect(cos1.y, atan2_1.u2) annotation (Line(points={{-29,-60},{-20,-60},{-20, + -46},{-12,-46}}, color={0,0,127})); + connect(atan2_1.y, unwrapAngle.u) + annotation (Line(points={{11,-40},{20,-40}}, color={0,0,127})); + connect(position.flange, speedSensor.flange) + annotation (Line(points={{10,32},{20,32},{20,60}}, color={0,0,0})); + annotation (experiment( + StopTime=3, + Interval=1e-05, + Tolerance=1e-06), Documentation(info=" +

+The reference frequency signal is integrated to obtain the angle, which is measured by an ideal AngleSensor. +The angle is used to build a phasor with real and imaginary part. +From this phasor, the (wrapped angle) is calculated which gets unwrapped using an angle tracking observer. +Compare angleSensor.phi and unwrapAngle.y. +

+

+Additionally, it is possible to detect the angular velocity of the phasor. +Compare speedSensor.w and unwrapAngle.w. +

+

+An ATO (angle tracking observer) is a robust method to evaluate the signals of a sin/cos-encoder. +

+")); + end DemoUnwrapAngle; + model CompareSincExpSine "Compare sinc and exponential sine signal" extends Modelica.Icons.Example; Sources.Sinc sinc(f=5) diff --git a/Modelica/Resources/Reference/Modelica/Blocks/Examples/DemoATO/comparisonSignals.txt b/Modelica/Resources/Reference/Modelica/Blocks/Examples/DemoATO/comparisonSignals.txt new file mode 100644 index 0000000000..5ec49a92e9 --- /dev/null +++ b/Modelica/Resources/Reference/Modelica/Blocks/Examples/DemoATO/comparisonSignals.txt @@ -0,0 +1,5 @@ +time +angleSensor.phi +unwrapAngle.y +speedSensor.w +unwrapAngle.w