Integer arithmetic, no decimalpoint

somlioy

Member
Join Date
Jan 2011
Location
Localhost
Posts
27
Hello

I'm dealing with a couple of PLCs that arent able to handle floats.

The task I have is to program a regulator and not use the integrated one.

Say I'm multiplying every number comming from the HMI with 100, and then dividing on 100 in the PLC. How do I then take care of the reminder. If for instance the Kp is set to anything between 0 and 0.99 (0-99) this will end up as 0.

I have access to regular math operations lik divison, multiplication and modulo.

I tried doing some searching, but I'm not quite sure what I should search for...
 
Some Questions:

Real project or learning assignment?
What type of regulator? and why not use the integrated one?
What processor? 8 bit? 16 bit? 32 bit?

Some things to think about:

Multiply before divide to preserve resolution
Limits of a fixed number system - signed and unsigned
Shift Left / shift right to multiply/divide by 2

Notes on efficiency of code:

Multiplying is much faster than dividing - think how you would code each function in assembly code and you will begin to understand!

To divide by 100 in many CPUs it is quicker to convert INT to BCD, Shift Right 8 and then convert BCD to INT.

Nick
 
Its a learning task on lab equipment.

PI regulator with PD feed forward. Not using the integrated one because we're supposed to use what we've learnt about z-transformation and discrete mathematics.

It's an Mitsubishi FX1N PLC, so 32bit.

Here's the D-part of the PD-regulator:


Where Kpff, Nff, Tdff and Ts all are regulator parameters. v(k) and v(k-1) is the measured disturbance (now and previous) and u(k) and u(k-1) is the output (now and previous). Ts is the sampling time.

Kpff, Tdff and Ts is multiplied with 100 from HMI and can be decimals. Nff is integer only.
 
With 32-bit integers you have a value range between −2147483648 to 2147483647

If we assume that the decimal point is offset by 2 positions, then you can represent −21474836.48 to 21474836.47.
If we assume that the decimal point is offset by 4 positions, then you can represent −214748.3648 to 214748.3647.


The problem will be that the values used risk hitting the limits for every calculation in the formulas.
So you have to perform a what-if analysis of every possible combination of data that is input into the formulas, and see if you hit the limits. If you see that you risk hitting a limit, you may have to rearrange the math in a way that the limit is avoided. It wont be simple !
Also, in your runtime code you should make checks for if there has been an overflow.


Apart from that, a PLC without floating point support is c**p. Seriously.

edit: And even if this is for training only, then it is IMO useless training. You wont ever use it again in real life.
 
Last edited:
Use fixed-point number representation.

the maths is faster if you use a decimal fraction as a power of 2, but you can do it with 100 if this makes more sense.

your 4 operators:
Code:
Fixed Point operation   32bit integer equivelent
a+b                     a+b
a-b                     a-b
a/b                     a*100/b
a*b                     a*b/100
 
I am pretty certain the FX1N is capable of doing the arithmetics you are wanting?

Are you certain you are doing conversion correctly?
 
Hello

I'm dealing with a couple of PLCs that arent able to handle floats.

The task I have is to program a regulator and not use the integrated one.

Say I'm multiplying every number comming from the HMI with 100, and then dividing on 100 in the PLC. How do I then take care of the reminder. If for instance the Kp is set to anything between 0 and 0.99 (0-99) this will end up as 0.

I have access to regular math operations lik divison, multiplication and modulo.

I tried doing some searching, but I'm not quite sure what I should search for...

From memory non floating division in the Fx series results in the whole number in register n and the remainder in register n+1 so you need to make sure your destination is 2 registers so for instance 99/12 = 8.25 so reg n would be 8 and register n+1 25

But like i say this is from memory and its a while since i used Fx for maths !

In fact here is a manual, i was half right, sort of, its described on page 5-25:

http://www.autocontcontrol.cz/Files/FA/PLC/FX_Programming_Manual_Basic.pdf
 
Last edited:
Back in the dark ages when floating point cost a lot I used lots of integer math. DSP programming was mostly integer math. The suggestions provided so far are not optimal.
DSP programmers use what they call Q15 format but that was for 16 bit DSPs. What this meant is that all numbers were scaled from -1 to 0.99999 with the lower 15 bits being used as a mantissa and bit 15 was the sign bit. Note, since FN1 has 32 bit math I would use Q16 format. In this case the lower 16 bits are fractions of one and the upper 16 bits are a sign + integer. Q formats reduce or eliminate the need to do division.
The trick is to use the right Q??? for the application. Look into DSP Q15 math routines. Much of the scaling is done with quick shift lefts or rights.

I agree with JesperMP that using integer math is a waste of time now that floating point is so cheap.

I see no feed forwards, integrator or derivative term in Somlioy's formula.
It would be nice to know what is being controlled and what the other parameters are.
I can easily make a PID difference equation in fact I have done it so many times I have it memorized. I know what a PID should look like and many other filters too.

Doing PID control on a PLC is a pain. PLCs are not suitable for fast closed loop control.
It would have been better to use Matlab or Scilab and NOT use the built in functions except for plotting.
Does the FN1 have a plotting function that is fast enough.

This is nuts. Refer to my rant about college professors that know little about doing control in the real world.
 
I have run into PID blocks that require integers only.
I usually multiply the real by 10 and then convert to integer and use that value for the PID. Control is better because the PID is now operating on the least significant digit which is a tenth of the value.

Example...Temp1 is type K TC at 0-2500.0 degrees real. Temp x 10 and then convert to real it is now 0-25000. That value is used in the PID block. This makes the PID block a lot more sensitive to changes.
If you are looking at 0.00 value, the I see why you are using x100 on the real.
 
Last edited:
Thanks for answers everyone.

As I said, formula provided was only the D-part of the feedforward regulator.
Heres complete formulas:
oEMWYnx.png

Upi is the PI-regulator. Sum of Upff + udff makes the PD-regulator.
Sum of PI and PD makes the whole regulator again.

The system is a water tank with variable output flow. The series regulator controlls a proportional inlet valve. Feed forward regulator measures the output flow.

If you implement the PI-regulator without handling the remainder you'll end up with stationary error.
 
Hello

I'm dealing with a couple of PLCs that arent able to handle floats.

The task I have is to program a regulator and not use the integrated one.

Say I'm multiplying every number comming from the HMI with 100, and then dividing on 100 in the PLC. How do I then take care of the reminder. If for instance the Kp is set to anything between 0 and 0.99 (0-99) this will end up as 0.

I have access to regular math operations lik divison, multiplication and modulo.

I tried doing some searching, but I'm not quite sure what I should search for...

Old school solution for dealing with 'rounding' in integer math:

Add 1/2 of your divisor (50) to your integer before doing your divide. 50 and higher becomes above 100, so divide by 100 gives 1 instead of 0. I think that was your original problem.

Agreed with all of the rants about not using such a simple PLC for PID control of the real world.

If you are also processor bound, you can do bit shifts to make the scan time lower. But that is *REALLY* an exercise.

Something like shift left 2, (*4), store as temp1, shift left 3 (*8, *32 total), store as temp2, shift left (*2, * 64 total) gives you *64. Add temp2 for *96, add temp1 for *100. Icky.
 
Old school solution for dealing with 'rounding' in integer math:
Add 1/2 of your divisor (50) to your integer before doing your divide.
This will work correctly only for the dividend and divisor of the same sign.
The complete rule is: increase the dividend absolute value by half of the divisor absolute value, before doing divide.
 
This will work correctly only for the dividend and divisor of the same sign.
The complete rule is: increase the dividend absolute value by half of the divisor absolute value, before doing divide.

Yes, of course!

You caught me in a short cut.

I find it increasingly disturbing that I can't rely on my memory for details like this ... sigh!
 

Similar Topics

Does anyone know of any such PLCs? Usually I'm lazy and don't want to think about precision and overflows.
Replies
20
Views
6,905
Hi. I'm using a Modbus ProSoft where I basically map data to a big INT array. Example, where GX_I_63HPU is a REAL, MNETC.DATA.WriteData[200] an...
Replies
21
Views
341
Good morning all, I'm integerating a device with a Rockwell PLC with V34 Studio 5000. The device reports error codes using a single integer to...
Replies
19
Views
1,222
Ex If I Read from Integer file N7:0 N7:0 is an 8 point input card , input 0 and 2 are on , rest off When I look at : N7:0 -7 6 5 4 3 2 1 0 I...
Replies
5
Views
703
The analog array has 16 individual bits and each bit is an alarm. SCADA is having issues getting the BIT bool value. However they can get the...
Replies
9
Views
978
Back
Top Bottom