Analog input to digital output using structured text or one of IEC 61131-3 standard

Whenever a new member posts a school assignment, we ask you to show what you've already done before offering advice on how to make improvements.
The challenging part of your assignment will be determining when your scaled result is a prime number. I don't know of any PLC which has an IsPrime() function. Since your range is only up to 1000 you could use a lookup table. Are you expected to determine whether or not the scaled value is prime within a single PLC scan or are you allowed to iterate over multiple scans?
Doesn't say anything about the number of scans but I assume it will be one.
 
I was thinking of a lookup table with 1000 boolean entries with trues for the prime number entries :geek:
32 DINTs, with 32-bits each, can represent the primality of all natural numbers from 0 to 1023; see below. Each DINT represents 32 of those natural numbers, e.g. bit kprime_dint_array[1].2 represents the natural number 33; each bit either is 1 if its corresponding natural number is prime, or is 0 if its corresponding natural number is composite.

Writing the AOI that takes a natural number and returns the corresponding bit from the array is left as an exercise for the student.

$ cat kprime.py
"""Sieve of Eratosthenes"""
import os
import struct

### Set all bits as prime for natural numbers 0-1023
primebits = [0xFFFFFFFF]*32

### function to convert natural number to index and mask into primebits

imask_idx = lambda ival: (1 << (ival & 31),ival >> 5,)

### Clear prime bits for natural number 0 and 1
for ii in [0,1]:
imask,intno = imask_idx(ii)
primebits[intno] ^= imask
if 'DEBUG' in os.environ: print(f"Removed {(ii,hex(imask),intno,)}")

### Clear bits for natural numbers caught in the Sieve of Eratosthenes
for i in range(2,33,1):
imask,intno = imask_idx(i)
if 0==(primebits[intno] & imask): continue
for ii in range(i*i,1024,i):
imask,intno = imask_idx(ii)
if (primebits[intno] & imask):
if 'DEBUG' in os.environ: print(f"Removed {(ii,hex(imask),intno,)}")
primebits[intno] ^= imask

### Convert from unsigned to signed 32-bit integers, and output results
print(struct.unpack('i'*32,struct.pack('I'*32,*primebits)))


$ python kprime.py | tee x.x | tr , \\n | tr -d ' ()' ; cat x.x
32 DINTs in a column, hopefully suitable for pasting into Studio 5k:
-1601558356
673221152
34112136
-2147342174
547359240
-2144853880
-2146959198
134382120
169910402
579338272
671221760
-2011135870
33693728
142770216
-2146917886
545785984
536873472
168304648
-2105407486
8391200
2629770
537397282
545292320
35684488
537395234
681576960
-1977614208
9052160
8423424
34087426
-2138961792
673316896
32-bit DINTs comma-separated on one line:
(-1601558356, 673221152, 34112136, -2147342174, 547359240, -2144853880, -2146959198, 134382120, 169910402, 579338272, 671221760, -2011135870, 33693728, 142770216, -2146917886, 545785984, 536873472, 168304648, -2105407486, 8391200, 2629770, 537397282, 545292320, 35684488, 537395234, 681576960, -1977614208, 9052160, 8423424, 34087426, -2138961792, 673316896)
E.g 673221152, the second number, representing 32-63:
Code:
  63                             32
  |                              |
  v                              v
2#001[COLOR=Blue][B]0[/B][/COLOR]10000[COLOR=blue][B]0[/B][/COLOR]10000[COLOR=blue][B]0[/B][/COLOR]10001[COLOR=blue][B]0[/B][/COLOR]10001[COLOR=blue][B]0[/B][/COLOR]0000
    ^ ^     ^     ^   ^ ^   ^
    | |     |     |   | |   |
    | 59    53    47  | 41  37
    61                43
N.B. 6n values are highlighted in bold blue
 
Last edited:
Here are some of the pieces of a solution which found all 172 primes less than 1024. The SCL Function could be used in OP's problem; the guts of the algorithm have been removed, since this is a homework problem. It's eight statements and an eleven-element array.

It's TIA portal, but it should be a straightforward conversion to Logix.

find_primes_tia_trace.png find_primes_tia_fc_scl.png find_primes_tia.png
 
Last edited:
A version of the Sieve of Eratosthenes to make a bit file of the primality of integers less than 1024 is attached, implemented in three rung for MicroLogix; Studio 5k would be similar.

It takes under 1500 scans to identify the 172 primes and from the 850 composites and 2 "neithers," so maybe 2s on an unloaded PLC, after that it we can use a constant-time lookup to flag the primality of any analog value.
 
I basically copied the formula out the RsLogix help file for the SCL instruction and tried to make it work like the SCP function.

Code:
FUNCTION_BLOCK scp_real
VAR_INPUT
	raw_real: REAL;
	raw_min_real: REAL;
	raw_max_real: REAL;
	eu_min_real: REAL;
	eu_max_real: REAL;
	limit_overflow: BOOL;
	fail_hi: BOOL;
END_VAR
VAR_OUTPUT
	scaled_out: REAL;
END_VAR
VAR
	fail: BOOL;
	input_real: REAL;
	input_min: REAL;
	input_max: REAL;
	scaled_min: REAL;
	scaled_max: REAL;
	rate: REAL;
	offset: REAL;
	output_real: REAL;
END_VAR

(* // convert the inputs to floats*)
input_real:= raw_real;
input_min:= raw_min_real;
input_max:= raw_max_real;
scaled_min:= eu_min_real;
scaled_max:= eu_max_real;

(*// calculates the slope OR rate; i.e. rise over the run*)
IF ((input_max - input_min) <> 0.0) THEN
  rate:= (scaled_max - scaled_min) / (input_max - input_min);
ELSE
  rate:= 0.0;
END_IF;

(*// calculates the offset)*)
offset:= scaled_min - (input_min * rate);

(*// performs the scaling calculation; i.e. y = mx+b*)
output_real:= (input_real * rate) + offset;

(*// IF the "Limit_En" flag is set THEN LIMIT the output TO within the scaling parameters*)
IF limit_overflow THEN
	IF output_real > scaled_max THEN
		output_real:= scaled_max;
		fail:= TRUE;
	ELSIF output_real < scaled_min THEN
		output_real:= scaled_min;
		fail:= TRUE;
	ELSE
		fail:= FALSE;
	END_IF;
ELSE
	fail:= FALSE;
END_IF;

IF fail_hi AND fail THEN
	output_real:= scaled_max;
ELSIF fail THEN
	output_real:= scaled_min;
END_IF;

scaled_out:= output_real;
 
Listed below are a few important aspects to be remembered while dealing with prime numbers and their formulas.

Even numbers placed in the unit's place of any number cannot be a prime number
The number 2 is the only even prime number.
For large numbers, add all the digits together if the sum is divisible by 3 then it is not a prime number.
Except for numbers 2 and 3, all other numbers can be expressed using the prime numbers formula 6n ± 1, where, n = natural number
 
Listed below are a few important aspects to be remembered while dealing with prime numbers and their formulas.

Even numbers placed in the unit's place of any number cannot be a prime number
The number 2 is the only even prime number.
For large numbers, add all the digits together if the sum is divisible by 3 then it is not a prime number.
Except for numbers 2 and 3, all other numbers can be expressed using the prime numbers formula 6n ± 1, where, n = natural number

I was thinking the same, but I hadn't worked out the full solution. I know a prime is only divisible by itself and 1 So I was thinking to do a check on divisible by 2 and rationalise. Saves look-ups and works for numbers bigger than 1K.
 
Slight improvement: the even bits, other than 2, can be reset as not prime in the FLL instruction. This reduces the one-time Eratosthenitic initialization by about 500 scans or one-third, so it's typically under a second.

Once initialization is complete, it takes but a handful of instructions (i.e. four) to test the primality of any natural number from 0-1023.

Untitled.png
 

Attachments

  • primer_eratosthenes_02_running.pdf
    282.7 KB · Views: 7
Copy & paste the prime numbers into an array, check the analogue value then a few compares i.e. 0-99, 100 - 199 etc.
Then limit the search to 100 iterations for the compare, will reduce the scan time & small logic.
this would probably be the easiest for the OP.
 
OP has not posted a single piece of their own work for this assignment.


Multi-scan searches will be more complex than a single constant-time lookup. Even so, the FSC instruction would be available to do a search, and already has the built-in facility to do it over multiple scans.
 
Here is a faster lookup, it requires the 168 prime numbers to be stored in an array, the idea is rather than iterate through possibly all 168 it compares the analogue value in chunks then if it is within that range puts a pointer value into a pointer so values 2-107 sets the pointer to 0 (first register in the array) then does the iteration through the 28 values in the array if a match is found then the pulse timer operates, the loop is then exited, the current number is stored so on next pass through the for/next loop if not changed then will not re-trigger the timer.
This means that the max loop time is only 28 times the processing time of the logic in the for/next loop.
I have assumed that once a prime number appears on the analogue & the timer is triggered, it will not trigger again until a new prime has been detected.
This is done in FBD but could be written in ST.
 
Yes, in Mitsubishi it has one called "SER" it returns 2 values the last position of the register where it is found and the number of finds (if you have more than one location containing the same value but not used it as no idea if this is available in other platforms), however, cannot find the time the function takes, so did a quick try, my loop (only 18 iterations) was less than the 168 binary search using the SER function so not faster in this case but is faster than doing a 168 for/next loop.
 
my loop (only 18 iterations) was less than the 168 binary search

No way, Jose!

A binary search over 168 values takes no more than, and probably exactly, 8 iterations, and all 8 could certainly be completed in one scan on any reasonably current PLC.


By the time @parky's pre-loop algortithm has executed 6 steps, it is down to 28 possibilities and needs an average of 14 more loop steps to complete; by the time binary search has executed 6 steps, it's down to 4 possibilities, and needs but 2 more to complete.


Further, a binary search does look quite so Heath-Robinson.
 
Last edited:

Similar Topics

Hello everybody. for an asignment we are using a s7 1200 siemens starterkit to connect sensores to create a program. we were hoping to save some...
Replies
14
Views
6,478
On a Micrologix 1100 analog input, I appear to be getting an internal offset of about 11 counts out of 1023. Running the program from RSLogix...
Replies
5
Views
4,352
Hi, hope this is not too boring of a question but wondering can a analog input on a micrologix 1400 be used as a digital input? thank you in...
Replies
3
Views
2,460
Within a Chemical/Process Plant what type of instrumentation is considered Digital Input, Digital Output, Analog Input or Analog Output? Where...
Replies
5
Views
3,874
Hi How i can program Analog input 4-20mA to control digital output module with setpoints? I need to create control circuit example for heater...
Replies
4
Views
3,202
Back
Top Bottom