Studio 5000 - SWPB or similar function for a SINT array?

sterky

Member
Join Date
Jul 2023
Location
ontario
Posts
18
Howdy, I am currently struggling with an array of values that I want to re-arrange in a programmatic way. My program is a mix of ladder and STX, with some tricks to make user input of array values on the HMI a little less of a headache.

To start I have a string that the user can edit, formatted;
Code:
"1,2,3#4,6,5#7,8#9"

I then convert the string to a 2 dim array of sint[20,4], formatted;
Code:
array[0,0] = 1 
array[0,1] = 2
array[0,2] = 3

array[1,0] = 4
array[1,1] = 6
array[1,2] = 5

array[2,0] = 7
array[2,1] = 8

array[3,0] = 9

all other array values = 0;


For some of the User input, they would need to modify the order of each array. Rather than have them retype the order, I'd like to rearrange it as follows
Reversed order of the 1st dim array values
Code:
array[0,0] = 3 
array[0,1] = 2
array[0,2] = 1

array[1,0] = 5
array[1,1] = 6
array[1,2] = 4

array[2,0] = 8
array[2,1] = 7

array[3,0] = 9

I was looking at the SWPB (Swap Byte), but not sure if it will accomplish what I need since my bytes are across array elements. Maybe some ladder with some FIFOs, if I can get it to reverse with the empty 0 elements offsetting the reversal of values.


Seems like something simple but curious if someone has a different approach besides STX for loops.

P.S. I'll need to reassemble the reversed string too, to inform the user of the change in order.
 
I see major faults in your future

Anyway, there's no trick to use here as you can't address a single row of a multi-dimensional array. Just loop over the user buffer, outputting the re-ordered array into a 2nd array. then copy it back to the user buffer.

But if you really want a trick, you could run bubble sort in ascending/descending order on the rows.
 
are the digits always in the range 0-9, i.e. are the comma- and #-delimited numbers always single digits?


Actually that does not matter, because all that needs to be done is

  1. reverse each phrase sub-string between the # delimiters,
  2. then reverse each numeric sub-string between each [,,] or [,#] or [#,] pair delimiter.
E.g.

1,23,456#789,0,12#34,567#8 <= Original string
654,32,1#21,0,987#765,43#8 <= Reverse inter-# phrases
456,23,1#12,9,789#567,34#8 <= Reverse numbers

And an intermediate 2D array is not needed, just a single SINT to hold the temporary value for the swap (and even that is not actually needed, but memory is cheap and that is another story).

So summat like this:
Code:
string := '1,23,456#789,0,12#34,567#8';
total_length := 26;
FOR pass := 0 TO 1 DO          (* pass 0:swap phrases; pass 1:swap digits *)
  hi := -1;                    (* implicit delimiter "before" string *)
  WHILE hi < total_length DO   (* implicit delimiter "after" string *)
    lo := hi;                  (* delimiter before string *)
    hi := lo + 1;              (* initialize delimiter search *)
    WHILE hi < total_length DO (* search for next delimiter *)
      IF string.data[hi] = 35  (* # character is a delimiter on both passes *)
      THEN
        EXIT;
      END_IF;
      IF  pass = 1
      AND string.data[hi] = 44 (* , is a delimiter on pass 1 only *)
      THEN
        EXIT;
      END_IF;
      hi := hi + 1;            (* delimiter not found yet, increment search index *)
    END_WHILE;
    sublo := lo + 1;           (* index of left end of sub-string *)
    subhi := hi - 1;           (* index of right end of sub-string *)
    WHILE sublo < subhi DO     (* swap characters in sub-string *)
      string_temp := string.data[sublo];
      string.data[sublo] := string.data[subhi];
      string.data[subhi] := string_temp;
      sublo := sublo + 1;
      subhi := subhi - 1;
    END_WHILE;
  END_WHILE;
END_FOR;
 
Definitely not swap byte. There is no swap data equivalent instruction across array elements. Easiest is just do a bubble sort. I do them all the time for arrays in CLX.
 
Pascal equivalent of my previous post that works

  • string characters can be accessed and compared without SINT .data[...] and ASCII codes
  • BREAK instead of EXIT to get out of a loop.
  • BEGIN..END instead of END_IF, END_FOR and END_WHILE.
 
I see major faults in your future

Oh yeah, been faulting the simulator a fair bit. šŸ˜…
Have been adding variable limiters to protect array dimensions as I go but I'm gonna have QA try to find any I'm missing before the operator finds it. I did build my own onscreen keypad to limit the expected characters.

but as the saying goes, "Each time you idiot proof a system, someone builds a better idiot"


Actually that does not matter, because all that needs to be done is

  1. reverse each phrase sub-string between the # delimiters,
  2. then reverse each numeric sub-string between each [,,] or [,#] or [#,] pair delimiter.
E.g.

1,23,456#789,0,12#34,567#8 <= Original string
654,32,1#21,0,987#765,43#8 <= Reverse inter-# phrases
456,23,1#12,9,789#567,34#8 <= Reverse numbers

And an intermediate 2D array is not needed, just a single SINT to hold the temporary value for the swap (and even that is not actually needed, but memory is cheap and that is another story).

So summat like this:
Code:
string := '1,23,456#789,0,12#34,567#8';
total_length := 26;
FOR pass := 0 TO 1 DO          (* pass 0:swap phrases; pass 1:swap digits *)
  hi := -1;                    (* implicit delimiter "before" string *)
  WHILE hi < total_length DO   (* implicit delimiter "after" string *)
    lo := hi;                  (* delimiter before string *)
    hi := lo + 1;              (* initialize delimiter search *)
    WHILE hi < total_length DO (* search for next delimiter *)
      IF string.data[hi] = 35  (* # character is a delimiter on both passes *)
      THEN
        EXIT;
      END_IF;
      IF  pass = 1
      AND string.data[hi] = 44 (* , is a delimiter on pass 1 only *)
      THEN
        EXIT;
      END_IF;
      hi := hi + 1;            (* delimiter not found yet, increment search index *)
    END_WHILE;
    sublo := lo + 1;           (* index of left end of sub-string *)
    subhi := hi - 1;           (* index of right end of sub-string *)
    WHILE sublo < subhi DO     (* swap characters in sub-string *)
      string_temp := string.data[sublo];
      string.data[sublo] := string.data[subhi];
      string.data[subhi] := string_temp;
      sublo := sublo + 1;
      subhi := subhi - 1;
    END_WHILE;
  END_WHILE;
END_FOR;

After taking the weekend to think about it, I just include the reverse array and reversing string logic in the original deconstruction logic FOR loop.

Ends up being fairly compact as once the first dimension is deconstructed since I have the number of used elements handy in a variable, so I have another FOR loop that copies in reverse and builds the reversed string with DTOS and adds , and # with individual COP.

Then the overall for loop moves on to the next 2nd dimension.
 

Similar Topics

Hi Everyone. Not posted on here for a long time, but I am hoping someone can help me. I am doing a differential pressure calculation in a L27ERM...
Replies
15
Views
237
Hi, how do I convert 2x Integer registers to a Real? The two integers are from Modbus registers that contain a floating point value, I need to...
Replies
2
Views
119
What is the best way to extract the hour and minute from the register that comes from Yaskawa VFD. In studio 5000 I have a register saved as INT...
Replies
3
Views
123
I have an Allen Bradley temperature switch that I am trying to use in studio 5000. I am getting the message "Unable to interpret the IODD file"...
Replies
0
Views
74
Hi all. I want to ask what may seem a stupid question, as I have a project to send live data to a Yeacode line printer which will print meterage...
Replies
10
Views
198
Back
Top Bottom