How to configure Opta as a ModBus Slave?

Hi,

I just got a new Opta WiFi and the new PLC IDE 1.0.3. I've been dealing with industrial automation equipment for many years, so I am quite curious about the possibilities and features brought by this new crop of OPTA Devices and the PLC IDE. For now, I am just exploring some basic features, specifically, accessing variables in the PLC using ModBus TCP. However, I didn't find any way to map variables to ModBus addresses and it seems that the Opta is always enabled as a ModBus slave.

==> Has anyone been able to find out how to configure the OPTA as a ModBus TCP slave through the PLC IDE?

Just for reference, I enabled the wired ethernet connection and I was able to connect to the Opta using QModMaster and there seems to be some default mapping already in place. This is what I've found so far just by doing some quick trial and error:

  • Coils 1, 2, 3, 4 correspond to the Output Relays 1, 2, 3, 4, respectively (the Opta must be externally powered for the relays to be actually energized). Coils 5, 6, 7, 8 correspond to the Status LEDs 1, 2, 3, 4, respectively. You can read from and write to those coils (Modbus function codes 0x01, 0x05). I didn't find an obvious mapping for the other LEDs (Green/Red, Blue).

  • Discrete Input 9 corresponds to the User Button and you can read its status (Modbus function code 0x02).

  • I tried to read/write Holding Registers and read Input Registers to no avail (I tried different starting addresses 0, 1, 30000, 30001, 40000, 40001, etc.), but this doesn't surprise me since I didn't find any way to actually map variables to ModBus addresses.

Nicolas

1 Like

Hi Nicolas! This video explains how to use Modbus TCP using the Arduino PLC IDE: Arduino PLC ❤️ Beckhoff PLC - YouTube

In the video there is Modbus TCP communication between two different PLC brands.

It's using a Portenta Machine Control but the principle should stay the same.

1 Like

I haven't tried it yet, but I think it might be this setting

Tools->Run Modbus Custom Editor

@yoshinobu1 Hi... that Modbus Custom Editor lets you create a file that stores custom mappings when the Opta is used as a ModBus Master. I tried it and you cannot even include the mapping file in the project unless you enable the ModBus Master functionality (Either for ModBus RTU or ModBus TCP). Perhaps there is a similar mechanism to configure the mappings when the Opta is used as a ModBus Slave too, but I haven't found it (yet)...

@nineplanets : Thanks for the link! I'll check the video later and post an update then.

UPDATE: @nineplanets That's a great video that shows how to configure the Opta or Portenta Machine Control as a ModBus Master (a.k.a. client), which I haven't tried yet. I think that a more commonplace application for the Opta would be as ModBus Slave (a.k.a. Server), so that's why I started experimenting there... but thanks again for the link to the video!

Hi,

@nsubotich
Thank you for your post i played a little bit with your discovered addresses and found that Coil 9,10 is LED red, green (I have the lite version so no blue LED :-))

Discrete input 1..8 is I1..8 (digital input)

The posted video above was more about Modbus Master as far as i understood i watched it yesterday.

@yoshinobu1
Nice photos of the opta at your page so i do not have to open it :slight_smile:
And your modbus master sample looks nice :+1:

1 Like

Someone just got an Uno talking to Ignition. Maybe it's close enough to help?

@feinwerk
Thanks for checking! ... some additional finding from some (very) limited tries:

  • Yes, Discrete Inputs 1..8 are mapped to I1..8. However...

    • The ModBus Discrete Input reflects the state of the physical input when configured as a Digital Input (as expected, no surprise there)
    • The ModBus Discrete Input seems to reflect the Least Significant Bit of the A/D converter when the physical input is configured as an Analog Input (it doesn't seem very useful, other than to generate random boolean values...)
  • Coil 9 is associated with the RED LED, 10 with the GREEN and 11 with the BLUE (when present...). However, I ran into the following when using QModMaster:

    • Reading more than 8 coils in a single request results in a Timeout error, even if all items are within the correct range (1..11). Writing more than 8 coils work ok, though. This might be an issue with QModMaster (I haven't checked yet if the read request sent to the Opta is properly constructed or not)
    • Reading OR writing a coil outside of 1..11 returns an "Illegal data address" error, as expected.

So thanks again!, ...and good progress to figure out the mapping to digital physical I/O.

==> Still to be figured out:

  • Mapping of the A/D converter values when I1..8 are configured as Analog Inputs (I'd expect those to be mapped as Input Registers, but may show as Holding Registers, don't know).
  • Mapping of variables of different data types, even if they are just BOOL or INT. Global variables, I'd expect, or even Shared variables, perhaps, but not Local.

Thanks again and let's keep exploring... (official documentation would be ideal, though, especially if the Opta tries to make inroads into the space of "traditional" PLCs)

@apf1979 Thanks for the link! That should work by using the code in the last post within the "Sketch" under the Resources tab, but I would expect the ModBus Master and slave functionality to be configured with dedicated PLC IDE features, not code that's meant for a generic Arduino device.

Again, thanks for the info! I'd still like to try out the code to make sure it doesn't conflict with anything else in the OPTA when the "main user logic" is configured through the PLC IDE.

@apf1979 @feinwerk UPDATE: PROGRESS!

I was able to map variables to ModBus addresses. Early findings:

  • Under the Resources tab -> Public Objects -> Parameters, create a new entry of type INT. The starting address is 0x4000. Once downloaded, this matches ModBus Input Register 0x4000 (Read Only, basically). The "Parameters" editor shows that these values are non-volatile, so perhaps they are persisted over a power cycle (need to check). The parameter will also show in the Project tree under Global Shared -> Parameters, so it can be used with any of the PLC "languages"

  • Under the Resources tab -> Public Objects -> Status variables, create a new entry of type INT. The starting address is 0x6000. Once downloaded, this matches ModBus Holding Register 0x6000 (Read/Write access). The status variable will also show in the Project tree under Global Shared -> Variables, so it can also be used with any of the PLC "languages"

So, I guess that to read a physical Analog Input (one of I1..8), we have to:

  • Create a new entry in the Parameter Editor (Under the Resources tab -> Public Objects -> Parameters) of type UINT (if using the default Min/Max/Scale/Offset)
  • Copy the value from the Analog Input (sysProgrammableInputs[...] or custom assigned variable name) to the newly created parameter. Since the parameters are available as a Global Shared entity, you can chose when to transfer the input value to the memory to be accessed as a ModBus Input Register location.
  • However, I'm not sure that I'd want to write too often to a non-volatile location. Might use a Status Variable (volatile) instead, but those are Read/Write...

More work to do, too little time, but this looks encouraging... Will have to post a summary with all the findings once I have a better understanding... or just wait for the official documentation, which should be coming out soon, right?

4 Likes

Good to hear

1 Like

@nsubotich Thank you for your reverse engeneering effort very promising results :+1:
When i find the time i will play with them maybe i discover something additional.

Alex

1 Like

@nsubotich
Did a quick test regarding Analog Input idea you mentioned above.

I have created it as you descripted above as "Parameter" or as "Status variable" and write the analog input to it --> tested and both ways do work. For playing with it i stick to "Status variable" not that i fry my memory.

1 Like

Grazie!! Ottimo lavoro @nsubotich funziona il tutto!!! Volevo un informazione sul come utilizzare i blocchetti dedicati alle Funzione FC01...ecc nell IDE PLC...non so se qualcuno abbia provato...

1 Like

Thanks Guys,

nsubotich is right the Opta make most sense as Slave. I am using as Temperature PID controller. Price vs utility is 1/6 of a similar PID controller with TCP. With you help I make it work. I am moving the analogue read to a 4000 register.

Please. What am I doing wrong? I set the variables "Parameters" and "Status variables" in "Public Objects". Modbus addresses are assigned to them. But when I query them from the program qModMaster, so it keeps giving me an error "Illegal data address". When I read or write to Opty addresses for relays and LEDs, it works without problems. But the variables I created do not work for me via Modbus TCP/IP. Thank you for advice.



Looks like you setup an input register but then you try to read a coil??
try Function Code 4..
never used any of the software you are, just what I noticed..
If you still get illegal address try with Start Address 1..

good luck.. ~q

I tried all the function codes and no success. When I enter the starting address 1, it asks for 0x0001 in HEX and not 0x4000.
Of course, when I use function code 1 and query address 1, it returns the relay status.

Hello everyone. I have already figured out how to read and write OPTA variables via Modbus TCP/IP. But now I am solving such a problem. When I change a variable to a value other than the default one via Modbus TCP/IP, after turning off and on OPTA it does not save this value and restores the default value. Can you please advise me how to change the default values for the Modbus variables with a command, or how to save the variables in OPTA to some place and then read them from there? Well thank you.

Hello Tom,

Could you tell me how you did the slave mapping for coils and discrete inputs? I understand that the parameters and status variables correspond to input and holding registers respectively.

Thank you!