Instead of OptoMMP


I maintain a system that contain 5 SNAP-PAC-S2 controller with serial I/O units (for example G4A8R, G4RAX, G4D16R).
I need to read/write I/O points value/state between the PLCs (for example start/stop pump or read a float value (weight, level etc.)).
Now I use the OptoMMP protocol for this function (Get/Set I/O Unit Scratch Pad Integer 32 Table), but it is not so easy to use or modify (add more points).
My question is what can I use instead of OptoMMP? Or if not, is it exist an useful sample code how can I use OptoMMP protocol correctly?

I’ll thanks for any advice.

Best regards,


Hi Peter,

Here is how I would tackle this one…

As often as you want the data fresh, I would run the command ‘Move I/O Unit to Numeric Table Ex’ for each of the I/O units hanging off that S2 controller.
This will, very efficiently, get the whole rack, digital, analog, in, out, the whole shebang, and move it into said table.

I would then store that table in the scratch pad (MMP) by using the command ‘Set I/O Unit Scratch Pad Float Table’. This will move the table from the I/O rack into a chunk of the scratch pad.
When it comes to moving it in, I would break the scratch pad into clear breaks, and I would leave some space between each chunk.
For example, the first rack might go from index 0 to 50, the second from index 100 to 150, the third from 200 to 250 and so on, (or what ever numbing order makes sense to your application).
This is how you make it easy to, as you say, ‘add more points’.
By giving space between each of the I/O unit chunks in the MMP, if you add a new point, the first command will just pick it up and put it in the table, the second command will just write it to the MMP, there will be nothing you need to do to the code after configuring the point.

Ok, so we now have, in very short order, got the I/O values in the scratch pad of the controller that the I/O is attached to.
Now, the last part of the job is to configure each controller in each controller as a ‘Generic OptoMMP Device’.
In other words, each of the 5 controllers will have 6 MMP I/O devices configured, itself and the 5 other S2 units.
Once you have that, your done.

You can then either address any point on the network by its index, or you can move tables around.

I’m sure Mary would like to see you do all the above with pointer tables, but they confuse the beep out of me, so I would do it the long hand way, but your welcome to do it anyway you like Peter!

As an aside, if you are using groov or PAC Display to look at any of those I/O points, I would seriously consider changing the tag from the I/O point to its matching table index number.
You will find your system speed (throughput) go up a notch or seven as then the HMI will not longer be holding up the serial I/O bus every time it needs to get a value, but it will be getting from the controller, much, much, much, much, much faster.

Anyone else got any peer to peer advice?



Since Ben speculated (incorrectly) :wink: on what I might like to see, and the original question did include: “what can I use INSTEAD of MMP,” let me just add one other alternative here…

In this post (click here), I shared a peer-to-peer example that can work for a variety of controllers talking to each other. However, that post only had subroutines for getting individual variables from yonder controller. I’ll include a few more below for getting/setting yonder Numeric Table values.

But before I get to that, let me be clear… since we’re talking about serial I/O here, you FOR SURE want to do that first part that Ben mentioned, which is to read a whole I/O Unit into one table, at the lowest frequency that makes sense for your application.

At this point if you’d rather NOT use the MMP, you could do something like I explain in the post mentioned above: use a subroutine where you pass the IP address/port of yonder S2 controller, along with the name and index of the table that’s been pre-loaded with I/O values (using the command Ben mentioned: Move I/O Unit…).

The downsides to this:

  1. a few more bytes flying back and forth across your network since this method of doing peer-to-peer is not as compact as the MMP method
  2. if someone re-names a table on one S2 and another S2 didn’t get the memo, you’ll have a problem
  3. some of my subroutines can be even more scary than a pointer table! (although most of what I’m doing here is the same idea as our “initialization file” download option in PAC Control). The nice thing about a subroutine is that you can use it like a black box–in your strategy it just looks like another command you don’t NEED to look at what’s in it.


  1. A table name to keep track of yonder I/O might be more meaningful than pre-agreed upon addresses in the MMP map
  2. No MMP at all, which I think is what you’d hoped for?

Attached find promised 9.3 Basic subroutines which augment this example. (13.6 KB)

Hope that makes sense!


Here’s another alternative for getting values into your controller, other than going through MMP:
A subroutine to listen for incoming tag assignments