Hello community OSCAT.
I found a algorithm at
http://homepage.smc.edu/kennedy_john/DEC2FRAC.PDF which can be used to convert any decimal number in a fraction.
I needed this solution, because I use MOVIDRIVE from SEW-EURODRIVE to control aplications such as Flying Saw to cut materials during synchronized moviment.
The problem is that the ratio between master and slave must be adjusted in two variables or parameters of Movidrive named GFMaster and GFSlave which works as a fraction.
With this algorithm I rewrote a function block below that cam be used for this purpose.
I made some tests with it running in MoviPLC model DEH41B from SEW and worked very well.
I would be grateful if this function can be added in the next revision of the library Oscat.lib
FUNCTION_BLOCK REAL_TO_FRAC
VAR_INPUT
Decimal: REAL;
AccuracyFactor: REAL := 5.E-007;
END_VAR
VAR_OUTPUT
Numerator: DINT;
Denominator: DINT;
END_VAR
VAR
DecimalSign : REAL;
Z : REAL;
PreviousDenominator : REAL;
ScratchValue : REAL;
FractionNumerator: REAL;
FractionDenominator: REAL;
END_VAR
IF Decimal < 0.0 THEN
DecimalSign := -1.0;
ELSE DecimalSign := 1.0;
END_IF
Decimal := ABS (Decimal);
IF Decimal=D_TRUNC(Decimal) THEN (*handles exact integers including 0*)
FractionNumerator := Decimal*DecimalSign;
FractionDenominator := 1.0;
RETURN; (*EXIT;*)
END_IF;
IF (Decimal < 1.0E-19) THEN (*X = 0 already taken care of *)
FractionNumerator := DecimalSign;
FractionDenominator := 9999999999999999999.0;
RETURN;
END_IF;
IF (Decimal > 1.0E19) THEN
FractionNumerator := 9999999999999999999.0*DecimalSign;
FractionDenominator := 1.0;
RETURN;
END_IF;
Z := Decimal;
PreviousDenominator := 0.0;
FractionDenominator := 1.0;
REPEAT
Z := 1.0 / ( Z - D_TRUNC( Z ) );
ScratchValue := FractionDenominator;
FractionDenominator := FractionDenominator*D_TRUNC(Z)+PreviousDenominator;
PreviousDenominator := ScratchValue;
FractionNumerator :=D_TRUNC(Decimal*FractionDenominator + 0.5); (* Rounding Function *)
UNTIL (ABS((Decimal-(FractionNumerator/FractionDenominator))) < AccuracyFactor) OR (Z = D_TRUNC(Z))
END_REPEAT;
FractionNumerator := DecimalSign*FractionNumerator;
(*These last lines where used only to convert the output variables in double integer*)
Numerator := REAL_TO_DINT(FractionNumerator);
Denominator:= REAL_TO_DINT(FractionDenominator);