// CP: 65001 // SimulationX Version: 3.8.2.45319 x64 within AIDAModelica; model Step_analysis "Step_analysis.mo" Modelica.Blocks.Interfaces.RealInput Consign "'input Real' as connector" annotation(Placement( transformation(extent={{-105,40},{-65,80}}), iconTransformation(extent={{-120,30},{-80,70}}))); Modelica.Blocks.Interfaces.RealInput State "'input Real' as connector" annotation(Placement( transformation(extent={{-105,-15},{-65,25}}), iconTransformation(extent={{-120,-70},{-80,-30}}))); Modelica.Blocks.Interfaces.RealOutput Stabilized(start=0) "'output Real' as connector" annotation(Placement( transformation(extent={{65,35},{85,55}}), iconTransformation(extent={{80,30},{120,70}}))); Modelica.Blocks.Interfaces.BooleanOutput Success(start=false) "'output Boolean' as connector" annotation(Placement( transformation(extent={{64.7,2.3},{84.7,22.3}}), iconTransformation(extent={{80,-70},{120,-30}}))); parameter Boolean Desactivate(start=false); parameter Real Precision(start=0.05); parameter Real Trigger(start=0.1); parameter Real Nb_Osc(start=3.0)=1.5; Boolean Step_Activ(fixed=false); Real Step_Size(start=0); Real Step_Start(start=0); Real Maximum_Overshot(start=0); Real Semi_Period(start=0); Real Last_Osc(start=0); parameter Real period_cst(start=0.2); Real Prev_Consign(start=0); Boolean Inside(start=false); Real Top[2](start={0,0}); Real Prev_Top[2](start={0,0}); Real First(start=0); Real x(start=0); Real DerS; parameter Real T(start=100*Modelica.Constants.eps) "time constant for input State derivation"; algorithm if Desactivate then Step_Start:=0; Step_Size:=0; First:=0; Inside:=false; Success:=false; Maximum_Overshot:=0; Semi_Period:=0; Prev_Top:={0,0}; Top:={0,0}; Stabilized:=0; else //détection d'un step de consign if not Step_Activ then when abs(Consign-Prev_Consign) > Trigger then Step_Activ:=true; Step_Start:=time; Step_Size:=Consign-Prev_Consign; end when; Prev_Consign:=Consign; elseif Step_Activ then //il faut surveiller que la consign ne varie plus /*if abs(Consign-Prev_Consign) > Trigger then Step_Start:=time; Step_Size:=Consign-Prev_Consign; First:=0; Inside:=false; Success:=false; Maximum_Overshot:=0; Semi_Period:=0; Prev_Top:={0,0}; Top:={0,0}; Stabilized:=0; end if ;*/ //Détermination du temps de réponse pour un réponse non oscillatoire when abs(State-Consign) < Precision*abs(Step_Size) then First:=time-Step_Start; Stabilized:=First; Inside:=true; elsewhen abs(State-Consign) >= Precision*abs(Step_Size) then Inside:=false; Success:=false; end when; //si on est à la consigne au bout de N période, la réponse est Inside when time-(First+Step_Start)>Semi_Period*Nb_Osc and Inside and Semi_Period>0 then Success:=true; end when; //calcul de la semi-période d'oscillation, si on est passé une fois autour de la consign (First>0) when not Success and abs(DerS)0 then //si success, la réponse est stabilisée : on ne calcule plus la période //premier passage if Last_Osc==0 then Maximum_Overshot:= (State - Consign)/Step_Size; //deuxième passage elseif Last_Osc<>0 and Semi_Period==0 then Semi_Period:=2*(time-Last_Osc); //troisième passage et plus elseif Last_Osc<>0 then Semi_Period:=(1-period_cst)*Semi_Period+2*period_cst*(time-Last_Osc); end if; Last_Osc:=time; //enregistrement des sommets successifs if (State-Consign)*sign(Step_Size)>0 then Prev_Top:=Top; Top[1]:=time-Step_Start; Top[2]:=State-Consign; end if; // estimation par interpolation du temps de réponse : en prenant le dernier instant ou on passe sous le seuil, le résultat est discontinu car dépend de la localisation extact de la dernière oscillation if Stabilized==First and Inside and Prev_Top[1]>0 and State-Consign>0 then Stabilized:=Top[1]+(Precision*Step_Size-Top[2])*(Top[1]-Prev_Top[1])/(Top[2]-Prev_Top[2]); end if; end when; end if; end if; initial equation x=0; equation //calcul de la dérivée de l'entrée State (sinon ne fonctionne pas en FMU, car on ne peux avoir un bloc dérivé directement sur une entrée : Error type DerOfInput) if Desactivate then DerS=0; else der(x)=(State-x)/T; DerS=(State-x)/T; end if; annotation( Diagram(graphics={ Line( points={{-50,5},{-35,5},{-25,70},{-20,45},{-15,55},{-10, 50},{-5,50},{40,50}}, smooth=Smooth.Bezier), Line(points={{40,55},{-60,55}}), Line(points={{40,45},{-60,45}}), Text( textString="x % of target", fillPattern=FillPattern.Solid, extent={{-5,30},{35,20}}), Line(points={{-20,55},{-20,5}}), Line(points={{-40,15},{-40,5}}), Text( textString="Time to reach", fillPattern=FillPattern.Solid, extent={{-15,35},{35,25}}), Line( points={{-50,5},{-35,5},{-25,70},{-20,45},{-15,55},{-10, 50},{-5,50},{40,50}}, smooth=Smooth.Bezier), Line(points={{40,55},{-60,55}}), Line(points={{40,45},{-60,45}}), Text( textString="x % of target", fillPattern=FillPattern.Solid, extent={{-5,30},{35,20}}), Line(points={{-20,55},{-20,5}}), Line(points={{-40,15},{-40,5}}), Text( textString="Time to reach", fillPattern=FillPattern.Solid, extent={{-15,35},{35,25}})}), experiment( StopTime=1, StartTime=0, Interval=0.001)); end Step_analysis;