Solving Struct Mapping Problem in CODESYS for Modbus/TCP Commands

Question:

I am exploring the use of STRUCT in parsing Modbus/TCP commands. In this setup, the Modbus client populates bytes with data related to a particular command (such as type and parameters), which the PLC (Codesys) accesses. By implementing a STRUCT, the process of parsing the data is streamlined, eliminating the need to parse byte by byte. Instead, the data can be easily accessed by mapping addresses to a struct. However, I have encountered an issue where the compiler does not allow me to specify the location of the struct for a %MW register. Specifically, using the code block VAR_COMMAND AT %MW1002: structGenericModbusCommand results in an error message stating "Bad declaration, use '%ML' for 'structGenericModbusCommand' variable." However, changing it to %ML allocates the struct to a different memory address upon going online. This inconsistency raises the question of why a struct type is being mapped to a %MW location instead of a specified one. Is there a way to control where the struct is mapped? In order to establish a reliable method for mapping STRUCT to specific Modbus addresses, I am seeking a solution to this issue. Any insights or suggestions would be greatly appreciated. Thank you. - Paulo (Using Codesys OEM: Schneider Machine Expert Logic Builder M241)

Top Replies

The size of the structGenericModbusCommand varies depending on the type of memory being used: MB (1 byte), MW (2 bytes), MD (4 bytes), and possibly ML (8 bytes). It appears that the memory addressing may be overlapping, with memory addresses progressing in the sequence MW1002 -> MB2004 -> MD501. For further information on memory mapping, visit: https://product-help.schneider-electric.com/Machine%20Expert/V1.1/en/m241prg/m241prg/M2xx_-_Memory_Mapping/M2xx_-_Memory_Mapping-3.htm.

Hi Paulo! It sounds like you're working on quite an interesting project. The issue you're experiencing might be due to %MW being a word type area, intended for unsigned integers, while %ML is for double words, and is likely used for allocating structures. Altering that would require deeper manipulation of the system, so instead, I'd suggest creating an array of words (%MW) of the size of your structure. Then, use a UNION to superimpose your structure over the array. Essentially, it’s a workaround to manually allocate memory for your structured data using the array language construct. This should allow you to control the mapping location precisely. Hope this helps!

Hi Paulo, it seems like you're trying to directly map the STRUCT to a %MW memory address, which could be causing the issue. Generally, Codesys isn't really fond of mixing memory areas (%ML, %MW, etc.) when it concerns complex data types like STRUCT. A common workaround is to use a MOVE block to copy the data from your %MW area to the STRUCT, and vice versa for output. Thus, effectively maintaining the desired address association while still utilizing the ease of structured variables. This might be a limitation based on Codesys's memory management constraints, or due to the architecture of the PLC you're using. I suggest giving this method a try and see if it resolves your issue. Good luck!

Hi Paulo, it appears you're facing an issue with data type and memory allocation. %MW usually refers to word data type (16 bits), hence it's giving an error when you're trying to assign it to a struct which is a more complex data type. As such, by using %ML (stands for Long Word aka double word which is 32 bits), it is capable of dealing with complex data types such as the struct. If there's an issue with it assigning different memory addresses when using %ML, it might be due to other parts of your code or the way in which the PLC is assigning memory. Also, the compiler might be minimizing fragmentation or optimizing performance which could lead to changes in the address. To control where the struct is mapped, you may want to look at any memory management features provided by your specific PLC. Alternatively, you might have to manually manage memory. I hope this helps and leads you to the solution you're searching for! -Jim

Hi Paulo! It sounds like you're running into the classic issue of memory addressing in Codesys. When working with STRUCTs and trying to access specific Modbus addresses, it can definitely be tricky. Have you considered checking the data type definitions and ensuring that the STRUCT is correctly defined for the Modbus memory map? Sometimes, certain types like %MW are treated differently, so double-checking their alignments and the memory area configurations could help. Additionally, some users have found success by using pointer variables that point to the designated memory addresses. It might allow you to keep the benefits of your STRUCT while controlling the mapping more precisely. Hope this helps a bit!

Hey Paulo, it sounds like you're dealing with some tricky memory alignment issues in Codesys. Generally, when using structures, the compiler may restrict you to certain memory areas based on the data types they contain. Since Modbus/TCP uses specific byte alignments, you might want to take a closer look at the structure definition itself—particularly how the data types are set up. Additionally, using the `%ML` directive might be the way to go even if it moves addresses since it can help with maintaining data integrity during Modbus transfers. You can also try explicitly defining the layout of your STRUCT to align with Modbus requirements, possibly by tweaking padding or using specific data types. Lastly, consult the Codesys documentation or forums for any peculiarities related to your specific OEM version; there might be nuances there that could help. Good luck!

More Replies →

Streamline Your Asset Management
See How Oxmaint Works!!

✅   Work Order Management

✅   Asset Tracking

✅   Preventive Maintenance

✅   Inspection Report

We have received your information. We will share Schedule Demo details on your Mail Id.

You must be a registered user to add a comment. If you've already registered,
sign in. Otherwise, register and sign in.

Frequently Asked Questions (FAQ)

FAQ: FAQs:

Answer: 1. Why am I encountering an error when trying to specify the location of a struct for a %MW register in CODESYS? - The error message "Bad declaration, use '%ML' for 'structGenericModbusCommand' variable" indicates that the compiler does not allow mapping a struct to a %MW register. Instead, it suggests using '%ML' for the struct variable.

FAQ: 2. How can I control where the struct is mapped in CODESYS when working with Modbus addresses?

Answer: - In order to specify a specific memory address for a struct in CODESYS, you should use '%ML' instead of '%MW'. Mapping a struct to a %MW location may lead to inconsistencies in memory allocation.

FAQ: 3. What is the recommended approach for mapping STRUCT to specific Modbus addresses in CODESYS?

Answer: - To ensure consistency and reliability in mapping a struct to Modbus addresses in CODESYS, it is advisable to use '%ML' for specifying the memory location of the struct variable. This helps in avoiding allocation inconsistencies when going online.

Ready to Simplify Maintenance?

Join hundreds of satisfied customers who have transformed their maintenance processes.
Sign up today and start optimizing your workflow.

Request Demo  â†’