HerculesRockefeller (Customer) asked a question.

Address mapping for ModbusTCP

This being the first time I've used this controller, I'm trying to figure out how to map variables to Modbus addresses so I can access them on my CM5 HMI. As stated in the title, I'm using ModbusTCP instead of ModbusRTU.

 

A basic overview of how address mapping works would be helpful. Here are a few questions I've already run into:

  • How are double-word variable types like DINT mapped to Modbus addresses?
  • Are the bit/byte addresses listed on the I/O mapping page listed in order of Modbus address?
  • When a variable tag is assigned, the default address is struck through which to me implies that it is being overridden to map to the tag. Is this accurate?
  • Is assigning variable tags in the I/O mapping page the correct approach, or should I be listing register addresses in my variable declarations?
  • Can a single variable tag be mapped both to an I/O address and to a Modbus address to reduce redundancy?

 

In addition, I'm curious if my current approach of using the PLC as the ModbusTCP server and the HMI as the client is advisable. I'm planning to store all of my state information in the PLC, and simply display status & prompt the PLC to change the value of variables from the HMI.

 

I'm coming from a troubleshooting & service background, so apologies for my limited/lacking knowledge of basic protocol setup.


  • Durallymax (Customer)

    I haven't used Cmore much lately, if they don't have a symbolic driver for Codesys I'd re-evaluate why you want to use a Cmore as you'll be creating a lot of extra work vs simply using the built in Codesys visu and a web client or an HMI with full symbolic support for Codesys.

     

    Regarding your questions though. Nothing is pre-configured for Modbus so you'll be on your own to define things as needed. HMI as master and PLC as slave is correct.

    • As with anything Codesys, there are many ways to accomplish the same thing. The screenshot below shows four methods to put a DINT value into WORDs.
    • The modbus addresses on the IO mapping tab will be contiguous from the start address you define under "General". Though, not sure what BYTE addresses you're referring to?
    • If you map an existing variable to an I/O point, that is now the access for that point/address. These addresses are internal to Codesys, nothing to do with Modbus.
    • Not a fan of using register addresses anywhere. Memory shifts and it's hard to debug. Also, keep in mind if using pointers, always make sure they are re-initialized somewhere and not simply set in the declaration area as an online change can shift data without updating the pointers. How you map to the Modbus slave device IO is up to you, but IME it will be easiest to simply create a new var to act as an array of Modbus words for mapping in an FB elsewhere. You can certainly map directly into the slave but as you note, different data types pose a challenge. Handling this in a separate FB makes it easier using the methods shown below.
    • Can't map one IO directly to another IO and even if you could, data types would get messy.

     

    Development in Codesys can be incredibly fast and efficient but it does take a different way of thinking vs "traditional" PLCs.

     

     

    Screenshot 2025-05-15 082050

    Expand Post
  • FACTS_MikeSc (AutomationDirect)

    Just wanted to comment on that last question about using a single variable for both modbus address and i/o.

     

    Because our i/o has a address and so does the modbus registers, you can't map an existing variable with an address. At least for our devices anyways.

     

    But like Durallymax says, that would be messy. I myself prefer to separate my i/o variables from modbus variables.

     

    Edit: Sorry you can use a program variable to map to both modbus and i/o address. My initial thought you were asking is if you can map a variable created in the i/o to a modbus variable.

     

    Expand Post
    • Durallymax (Customer)

      Doesn't work on the hardware I have either "map to existing variable with address is not allowed!"

    • FACTS_MikeSc (AutomationDirect)

      Thanks for the feedback. Yeah there are so many ways to do things in Codesys.

  • I appreciate the feedback guys - all this flexibility is a little overwhelming, but it's also the reason I'm trying to migrate to Codesys in the first place.

     

    As for why I'm using CMore with Codesys - our facility already uses CMore everywhere, so I wanted to keep consistent with the HMIs our operators are already using. The DirectLogic and CLICK controllers we have everywhere are a bit limiting though, so I opted to upgrade to the Codesys unit for my current project. I naively didn't even consider that the PLC<->HMI connection might be more complicated with this setup.

     

    To make sure I understand correctly -- having my modbus and io addresses point to program/global variables instead of having my program variables point to modbus/io addresses during variable declaration is a valid approach then? I'll probably still have dedicated program variables point to my I/O addresses, but being able to point modbus addresses to my program variables (of compatible data types) instead of vise versa seems useful.

     

    **edited last paragraph for clarity

    Expand Post
    • Durallymax (Customer)

      Well this is where it gets interesting. For physical IO cards I put the full path to a program variable at each IO point as one of the last steps once a program is finished.

       

      For Modbus, Ethernet/IP, etc. I like to also do this, but due to type conversion errors in some cases you're left to create a new variable in that device's I/O and point to it, then do the work from there in some sort of FB to handle the mapping.

       

      A lot of this depends on how you're trying to write your program as well. A traditional PLC program would take a much different approach vs something using more OOP and trying to remain flexible.

      Expand Post
      • "For physical IO cards I put the full path to a program variable at each IO point as one of the last steps once a program is finished." After making some tweaks to my I/O assignments, this honestly seems like the best approach. It makes things cleaner inside the variable declarations and less headache-y when I need to alter my I/O mapping.

         

        I'll test transmission of 32-bit floats and integers between the PLC and HMI just to see what I can get the C-More to cooperate with. Hopefully I can report back with some positive results - the more I get into this, the simpler it looks, so fingers crossed.

        Expand Post
  • FACTS_MikeSc (AutomationDirect)

    "having my modbus and io addresses point to program/global variables instead of having my program variables point to modbus/io addresses during variable declaration is a valid approach then"

     

    Sorry if I made things more confusing. Yes either way works with program and global variables.