TIA Portal SCL Time to DINT and division

qwemx

Member
Join Date
Jul 2017
Location
Earth
Posts
195
I have a ramp function which is using Time data type for calculation , I have converted the time to DINT and divided these values and saved in a variable which is Real - This is accepted by the compiler but the value of the division stays at zero all the time .No error but code does not work


Code:
FUNCTION_BLOCK "RAMP"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      RUN : Bool;   // 0 - track X0, 1 - ramp to/track X1 
      X0 : Real;
      X1 : Real;
      TR : Time;   // Ramp duration 
      CYCLE : Time;   // Sampling period 
   END_VAR

   VAR_OUTPUT 
      BUSY : Bool;   // BUSY = 1 during ramping period 
      XOUT : Real := 0.0;
   END_VAR

   VAR 
      XI : Real;   // Initial value 
      T : Time := T#0MS;   // Elapsed time of ramp 
      Change : Real;
   END_VAR


BEGIN
	#BUSY := #RUN;
	IF #RUN THEN
	    IF #T >= #TR THEN
	        #BUSY := 0;
	        #XOUT := #X1;
	    ELSE
	        #Change := (TIME_TO_DINT(#T) / TIME_TO_DINT(#TR));
	        #XOUT := #XI + ((#X1 - #XI) * #Change) ;
	        #T := #T + #CYCLE;
	    END_IF;
	ELSE
	    #XOUT := #X0;
	    #XI := #X0;
	    #T := t#0s;
	END_IF;
END_FUNCTION_BLOCK

Screenshot_5.jpg
 
Now for the simulation i need a ramp that goes up and then comes down and so on..... I struggled with IF Else a lot and it did not work then I used case statement and wrote this code not tested yet
any comments ?
Code:
FUNCTION_BLOCK "RAMP"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      RUN : Bool;   // 0 - track X0, 1 - ramp to/track X1 
      XStart : Real;
      XFinal : Real;
      TRamptime : Time;   // Ramp duration 
      CYCLE : Time;   // Sampling period 
   END_VAR

   VAR_OUTPUT 
      BUSY : Bool;   // BUSY = 1 during ramping period 
      XOUT : Real := 0.0;
   END_VAR

   VAR 
      Xinitial : Real;   // Initial value 
      T_elapsed : Time := T#0MS;   // Elapsed time of ramp 
      State : Int;
      RampDwnCompleted : Bool;
      RampupCompleted : Bool;
   END_VAR


BEGIN
	#BUSY := #RUN;
	CASE #State OF
	    1:
	        IF #RUN AND #RampDwnCompleted AND #T_elapsed <= #TRamptime THEN
	            #XOUT := #XStart + (#XFinal - #XStart) * (DINT_TO_REAL(TIME_TO_DINT(#T_elapsed)) / DINT_TO_REAL(TIME_TO_DINT(#TRamptime)));
	            #T_elapsed := #T_elapsed + #CYCLE;
	        ELSE
	            #T_elapsed := t#0S;
	            #RampupCompleted := 1;
	            #RampDwnCompleted := 0;
	            #State := 2;
	            
	        END_IF;
	    2:
	        IF #RUN AND #RampupCompleted AND #T_elapsed <= #TRamptime THEN
	            #XOUT := #XFinal - (#XFinal * (DINT_TO_REAL(TIME_TO_DINT(#T_elapsed)))) / DINT_TO_REAL(TIME_TO_DINT(#TRamptime));
	            #T_elapsed := #T_elapsed + #CYCLE;
	        ELSE
	            #T_elapsed := t#0S;
	            #RampDwnCompleted := 1;
	            #RampupCompleted := 0;
	            #State := 1;
	        END_IF;
	END_CASE;
	
END_FUNCTION_BLOCK

Screenshot_17.png
 
In the [2:] CASE statement I think the second [#XFinal] in the assignment to [#Xout] should be [(#XFinal - #XStart)]


Also, instead of duplicating all of that scaling code, I would swap the meaning of #XFinal and #XStart based on the case, and then have the formula in only one place e.g.


Code:
  IF #RampDwnCompleted THEN
    #X0 := #XStart;
    #X1 := #XFinal;
  ELSE
    #X0 := #XFinal;
    #X1 := #XStart
  END_IF;


  IF #T_elapsed <= #TRamptime THEN
    #XOut = #X0 + ((#X1 - #X0) * (<numerator>) / (<denominator));
    #T_elapsed := #T_elapsed + #CYCLE;
  ELSE
    #T_elapsed := t#0s;
    #RampDwnCompleted := NOT #RampDwnCompleted;
    #RampUpCompleted := NOT  #RampDwnCompleted;
  END_IF;
That might have transition/restart problems (it assumes ramp down on start), but the guts are there and the scaling formula only appears once.
 
In the [2:] CASE statement I think the second [#XFinal] in the assignment to [#Xout] should be [(#XFinal - #XStart)]


Also, instead of duplicating all of that scaling code, I would swap the meaning of #XFinal and #XStart based on the case, and then have the formula in only one place e.g.


Code:
  IF #RampDwnCompleted THEN
    #X0 := #XStart;
    #X1 := #XFinal;
  ELSE
    #X0 := #XFinal;
    #X1 := #XStart
  END_IF;


  IF #T_elapsed <= #TRamptime THEN
    #XOut = #X0 + ((#X1 - #X0) * (<numerator>) / (<denominator));
    #T_elapsed := #T_elapsed + #CYCLE;
  ELSE
    #T_elapsed := t#0s;
    #RampDwnCompleted := NOT #RampDwnCompleted;
    #RampUpCompleted := NOT  #RampDwnCompleted;
  END_IF;
That might have transition/restart problems (it assumes ramp down on start), but the guts are there and the scaling formula only appears once.


that looks so much better and efficient
why i not able to think like that
 
that looks so much better and efficient
why i not able to think like that


1) Looks nicer? yes. More efficient? not much.



1.1) You have an engineering mindset that got the job done first; that is often far more valuable than pretty code.



2) You may not be old enough yet. You should see some of my early stuff; I can hardly bear looking at it.


2.1) You see the difference, so you will get there.


3) Thank you for the compliment, but PLCtalk.net is a small pond; out in the big wide world I am a hack.
 
Thank you for the feedback .

my code did not work - state has default value of Zero but i used 1 and 2 so i chaged it

FUNCTION_BLOCK "RAMP"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
RUN : Bool; // 0 - track X0, 1 - ramp to/track X1
XStart : Real;
XFinal : Real;
TRamptime : Time; // Ramp duration
CYCLE : Time; // Sampling period
END_VAR

VAR_OUTPUT
BUSY : Bool; // BUSY = 1 during ramping period
XOUT : Real := 0.0;
END_VAR

VAR
Xinitial : Real; // Initial value
T_elapsed : Time := T#0MS; // Elapsed time of ramp
State : Int;
RampDwnCompleted : Bool;
RampupCompleted : Bool;
END_VAR


BEGIN
#BUSY := #RUN;

IF #RUN THEN
CASE #State OF
0:
IF #RUN AND #RampDwnCompleted AND #T_elapsed <= #TRamptime THEN
#XOUT := #XStart + (#XFinal - #XStart) * (DINT_TO_REAL(TIME_TO_DINT(#T_elapsed)) / DINT_TO_REAL(TIME_TO_DINT(#TRamptime)));
#T_elapsed := #T_elapsed + #CYCLE;
ELSE
#T_elapsed := t#0S;
#RampupCompleted := 1;
#RampDwnCompleted := 0;
#State := 1;

END_IF;
1:
IF #RUN AND #RampupCompleted AND #T_elapsed <= #TRamptime THEN
#XOUT := (#XFinal - #Xinitial) - (#XFinal * (DINT_TO_REAL(TIME_TO_DINT(#T_elapsed)))) / DINT_TO_REAL(TIME_TO_DINT(#TRamptime));
#T_elapsed := #T_elapsed + #CYCLE;
ELSE
#T_elapsed := t#0S;
#RampDwnCompleted := 1;
#RampupCompleted := 0;
#State := 0;
END_IF;
END_CASE
;
END_IF;

END_FUNCTION_BLOCK
 
Last edited:
Thank you for the feedback .

my code did not work - state has default value of Zero but i used 1 and 2 so i chaged it

FUNCTION_BLOCK "RAMP"...


It does not need #State; #RampUpCompleted always has the same value as #State, so it can use that. For that matter, it does not use #RampDwnCompleted, so that can be removed as well.
 
Yes it works i was talking about my code
i added three variables and state 0 is used to ramp till start value

Code:
FUNCTION_BLOCK "RAMP_1"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      RUN : Bool;   // 0 - track X0, 1 - ramp to/track X1
      XStartVoltage : Real;
      XFinalVoltage : Real;
      XStartCurrent : Real;
      XFinalCurrent : Real;
      XStartSpeed : Real;
      XFinalSpeed : Real;
      TRamptime : Time;   // Ramp duration
      TRamptoStartValue : Time;
      CYCLE : Time;   // Sampling period
      RampupdownVoltage : Bool;
      RampupdownCurrent : Bool;
      RampupdownSpeed : Bool;
   END_VAR

   VAR_OUTPUT 
      BUSY : Bool;   // BUSY = 1 during ramping period
   END_VAR

   VAR_IN_OUT 
      XoutVoltage : Real := 0.0;
      XoutCurrent : Real;
      XoutSpeed : Real;
   END_VAR

   VAR 
      Xinitial : Real;   // Initial value
      T_elapsed_toStartValue : Time := T#0MS;   // Elapsed time of ramp
      T_eslaped_Ramp : Time;
      State : Int;
      RampDwnCompleted : Bool;
      Rampupcompleted : Bool;
      K1 : Real;
      K2 : Real;
      X0 : Real;
      X1 : Real;
      y0 : Real;
      y1 : Real;
      z0 : Real;
      z1 : Real;
   END_VAR


BEGIN
	
	IF #RUN THEN
	    
	    CASE #State OF // 
	        0:
	            
	            IF #RUN AND (#T_elapsed_toStartValue <#TRamptoStartValue)OR(#XoutVoltage < #XStartVoltage)OR (#XoutCurrent < #XStartCurrent)OR(#XoutSpeed < #XStartSpeed) THEN
	                #T_elapsed_toStartValue := #T_elapsed_toStartValue + #CYCLE;
	                #BUSY := 1;
	                #K1 := (DINT_TO_REAL(TIME_TO_DINT(#T_elapsed_toStartValue)) / DINT_TO_REAL(TIME_TO_DINT(#TRamptoStartValue)));
	                
	                IF #XoutVoltage < #XStartVoltage THEN
	                    #XoutVoltage := (#XStartVoltage * #K1);
	                END_IF;
	                
	                IF #XoutCurrent < #XStartCurrent THEN
	                    #XoutCurrent := (#XStartCurrent) * #K1;
	                END_IF;
	                
	                IF #XoutSpeed < #XStartSpeed THEN
	                    #XoutSpeed := (#XStartSpeed * #K1);
	                END_IF;
	            ELSE
	                #State := 1;
	                #T_elapsed_toStartValue := t#0s;
	                #BUSY := 0;
	            END_IF;
	           
	                
	                1:
	                    IF #RampupdownVoltage AND  #RampDwnCompleted THEN
	                        #X0 := #XStartVoltage;
	                        #X1 := #XFinalVoltage;
	                    ELSE
	                        #X0 := #XFinalVoltage;
	                        #X1 := #XStartVoltage;
	                    END_IF;
	                    
	                    IF #RampupdownCurrent AND  #RampDwnCompleted THEN
	                        #y0 := #XStartCurrent;
	                        #y1 := #XFinalCurrent;
	                    ELSE
	                        #y0 := #XFinalCurrent;
	                        #y1 := #XStartCurrent;
	                    END_IF;
	                    
	                    IF #RampupdownSpeed AND  #RampDwnCompleted THEN
	                        #z0 := #XStartSpeed;
	                        #z1 := #XFinalSpeed;
	                    ELSE
	                        #z0 := #XFinalSpeed;
	                        #z1 := #XStartSpeed;
	                    END_IF;
	                    IF (#T_eslaped_Ramp <= #TRamptime) AND (#RampupdownCurrent OR #RampupdownVoltage OR #RampupdownSpeed) THEN
	                        
	                        #T_eslaped_Ramp := #T_eslaped_Ramp + #CYCLE;
	                        #BUSY := 1;
	                        #K2 := (DINT_TO_REAL(TIME_TO_DINT(#T_eslaped_Ramp)) / DINT_TO_REAL(TIME_TO_DINT(#TRamptime)));
	                        IF #RampupdownVoltage THEN
	                            #XoutVoltage := #X0 + (#X1 - #X0) * #K2;
	                        END_IF;
	
	                        IF #RampupdownCurrent THEN
	                            #XoutCurrent := #y0 + (#y1 - #y0) * #K2;
	                        END_IF;
	
	                        IF #RampupdownSpeed THEN
	                            #XoutSpeed := #z0 + (#z1 - #z0) * #K2;
	                        END_IF;
	
	                    ELSE
	                        #T_eslaped_Ramp := t#0s;
	                        #RampDwnCompleted := NOT #RampDwnCompleted;
	                        #Rampupcompleted := NOT #RampDwnCompleted;
	                       
	                    END_IF;
	        END_CASE;
	        
	    END_IF;
	   
	       
	            
	        
	
END_FUNCTION_BLOCK
 
Last edited:

Similar Topics

Hello, In step7 I would be able to access FB has been created by SCL and after assigning an associated instance DB i can monitor to debug the...
Replies
3
Views
2,317
I just found a piece of code using an operator "+=" IF tag1 AND tag2 THEN tag3 += tag4; tag5 := tag5 + tag6; END_IF; I don't...
Replies
11
Views
4,758
Hi All, Just a quick question to see if anybody has found a work around for the symbolic / numbering of datablocks in SCL in TIA Portal V12 ...
Replies
0
Views
5,694
Hey everybody, I've recently started messing around with TIA portal V11. Reviewing my company's software. A lot of it was written in poorly...
Replies
6
Views
7,346
Hi All, Someone at work has put a PLC system on my desk, that's just been taken off an idle production line. He said "It's an S7 PLC. We don't...
Replies
10
Views
185
Back
Top Bottom