Post by bjarne-pagaard on Communication between applications on same device/controller/runtime (Win RTE 3.5.20.20)
CODESYS Forge
talk
(Post)
Hi, I would like to divide a project into multiple applications - as a minimum: one handling visualization and Alarm Manager, one handling I/O and plant control logic. But how to exchange variables between the applications? What have you done to get such a solution? In versions 3.5.19 and earlier, you can have Child applications, where the children can access a GVL in the Parent application. Children apps is no longer possible in 3.5.20 - but you can have 'sibling' apps - Several apps directly under PLC Logic, that is. But how do they best communicate? The Communication Manager / Data Sources Manager is sort of possible via OPC UA, but it seems like overkill and with some limitations - for example no ARRAY OF STRUCT possible this way. If you have separate devices in your project, you can exchange data via 'CODESYS ApplicationV3', but not other applications in the same device (see attachment Datasources.png). You can do it via 'Select the project type'->'Other Project' and select the same project file, but this leads to crashing the Development system when working with the variables afterwards. It would be great to hear your thoughts / experiences on this topic - Bjarne
Last updated: 2024-09-27
Post by breiter on Frustration-Fueled Feedback on Project File Management and Git Integration
CODESYS Forge
talk
(Post)
Hi, supporting a text based storage format is on our roadmap, see https://www.codesys.com/the-system/releases-updates-lifecycle/release-plan-roadmap.html It will be an Add-On feature called "File Based Storage" for the professional developer edition. Structured text POUs will be stored as plain text. Other graphical languages will remain in an xml format. You will be able to switch the storage type for projects. Certain workflows will become easier this way. Nevertheless restrictions will remain because of CODESYS specific storage logic (for example how methods below function blocks are stored as file). So merging using our Git Integration Add-On remains the recommended workflow. A workflow involving Visual Studio Code as the main IDE is not supported. Simply because many topics like library management, task configuration or fieldbus configurators are not available for VS Code. A PLC project is a lot more than just some ST POUs. Best Regards
Last updated: 2024-10-16
Post by imdatatas on Auto Declare window disappears by itself in the Ladder editor
CODESYS Forge
talk
(Post)
Hello Everyone, The "Auto Declare" window disappears by itself in the Ladder editor. For example, a new function block is wanted to be added to the Ladder editor. (For example; MC_Jog block and instance name will be fbMcJog). To do this, "Empty box with EN/ENO" is added to the ladder line from the Toolbox on the right and when you type MC_Jog in the empty box and press enter, normally the "Auto Declare" window appears and you are expected to be asked to write the instance name here. However, this "Auto Declare" window closes itself immediately, it does not wait for the user to enter a value or close the window. I often encounter this situation in many IDE versions. Does this seem like a bug? If anyone has encountered a similar problem while creating a new program name, function or function block instance name regarding the "Auto Declare" window and knows a solution, I would be glad if you could share it. Best wishes Imdat
Last updated: 2025-03-06
Post by mondinmr on Unexpected behavior in cyclic encoder read method during INT overflow (wrap-around)
CODESYS Forge
talk
(Post)
Hi everyone, I’m investigating a potential issue with a cyclic method we use for reading incremental encoders in our libraries. I’ve come across two implementations that, at first glance, appear to perform the same operation: motionUnit.vlPositionActualValue is UINT due strange encoder type. Version A METHOD PROTECTED cyclicReadField VAR_INST actPosFieldOld: INT; rI: INT; delta: INT; END_VAR rI := TO_INT(motionUnit.vlPositionActualValue); delta := rI - actPosFieldOld; m_actPosRaw := m_actPosRaw + TO_LREAL(delta); actPosFieldOld := rI; IF settings.velocityFeebackMapped THEN m_actVelRaw := TO_LREAL(motionUnit.velocityActualValue); END_IF Version B METHOD PROTECTED cyclicReadField VAR_INST actPosFieldOld: INT; END_VAR m_actPosRaw := m_actPosRaw + TO_LREAL(TO_INT(motionUnit.vlPositionActualValue) - actPosFieldOld); actPosFieldOld := TO_INT(motionUnit.vlPositionActualValue); IF settings.velocityFeebackMapped THEN m_actVelRaw := TO_LREAL(motionUnit.velocityActualValue); END_IF Both use INT and the same delta logic, so they seem equivalent. However, when an overflow (wrap-around) occurs, version A continues correctly as expected, while version B unexpectedly resets to -32768 without a clear reason. Has anyone experienced similar behavior or can shed light on what might be happening here? It almost seems as if the cast to LREAL is being applied before the calculation — but that would be illogical and potentially very dangerous in many situations! Thanks!
Last updated: 2025-05-13
Post by bmatlove on Variable Length Array - Cannot mix variable and fixed length dimensions?
CODESYS Forge
talk
(Post)
Using Codesys 3.5.18.30 I am trying to work with an array of variable length in one dimension, but known in the other dimension. For example, using an array that represents a list of items, each with an attribute profile. I do not know how many items will be in the list, but I know that every item has 5 attributes, like size, weight, etc. Codesys does not seem to be able to accept this. I have referenced Data Type: ARRAY OF documentation page, which is not explicit if variable & fixed length array dimensions can be mixed. In the VAR_IN_OUT scope, I initially tried MY_ARRAY : ARRAY [*, *] OF REAL; which was no problem, of course. I then modified it to MY_ARRAY : ARRAY [*, 1..5] OF REAL; which throws C0006: ', or ]' expected instead of '..' among consequent downstream errors. I then used the Auto Declare -> Array Wizard, which accepted (asterisk)-(asterisk) and 1-5 for 2-dimensional lower and upper bounds. It output: MY_ARRAY: ARRAY[*..*, 1..6] OF INT; which throws the same error stream. What's the deal here? Is this possible?
Last updated: 2025-05-23
Post by josul on Web Client HTTPS Communication Issue
CODESYS Forge
talk
(Post)
Web Client Library Documentation Company: 3S - Smart Software Solutions GmbH Title: Web Client Version: 1.0.1.7 Categories: Application|Utils Namespace: WEB_CLIENT Author: 3S - Smart Software Solutions GmbH Placeholder: WebClient I encountered an issue using this library above. Note it is now part of Codesys IIoT Libraries SL in the form of Web Client SL, but I am not using this version. I was sending Content-Type: application/json, HTTP POST using a HTTPS URL. No issue observed initially, successful operation. At some point operation stopped and the codesyscontrol.log file started to accumulate errors: ERROR: TlsCreateContext2: Failed to save context. An application reset failed to resume operation and I was unable observe any TCP connection forming to a destination port 443. The error appeared as a TCP_INIT error. I can find no details as to what may have happened or why a reset of the PLC application did not resume operation. Testing with a curl operation proved to be successful, so I am confident there was no fundamental networking issue preventing a TCP connection forming. The solution was to reboot the hardware itself, but this is not satisfactory in the long term. Is there any description of the TLS error I received? Is there any suggestion here that there might be an issue with certificates? Any advice or information is appreciated.
Last updated: 2025-06-05
Post by ranadheer on Codesys Control for PLCnext (PLC - AXL F 2152)
CODESYS Forge
talk
(Post)
Hello Jaco Pretorius, I came across your post regarding CodeSys control for PLCnext. I’m currently working on a similar setup and had a quick question. Here am using the CODESYS V3.5 SP21 PATCH2 ,VERSION 3.5.21.20 , and Downloaded extension package 4.16.0.0 (old versions are not available in the extension CodeSys installer) Devices used here are: BUS COUPLER : 2403869 BK PN TPS Module carrier slot 1 : 1088127 AXL SE DI16/1 Module carrier slot 2 : 1088062 AXL SE AI4 | 4-20 Module carrier slot 3 : 1088129 AXL SE DO16/1 Module carrier slot 4 : 1088123 AXL SE AO4 | 4-20 -->Start a New Project Type: Standard Project Device: CODESYS Control Win V3 x64 Language: Structured Text -->Install GSDML File Navigate to: Tools > Device Repository > Install Select the GSDML file path (downloaded from Phoenix Contact for device coupler Part ID: BK PN TPS 2403869) Click Renew Device Repository Close the dialog -->Add Device to Project -->Right-click on Devices > Add Device Issue: Devices from the repository are not available to select or call into the project! I’d really appreciate any guidance or suggestions you can offer. Best Regards Ranadheer Reddy
Last updated: 2025-09-09
Post by ranadheer on Codesys Control for PLCnext (PLC - AXL F 2152)
CODESYS Forge
talk
(Post)
Hello Jaco Pretorius, I came across your post regarding CodeSys control for PLCnext. I’m currently working on a similar setup and had a quick question. Here am using the CODESYS V3.5 SP21 PATCH2 ,VERSION 3.5.21.20 , and Downloaded extension package 4.16.0.0 (old versions are not available in the extension CodeSys installer) Devices used here are: BUS COUPLER : 2403869 BK PN TPS Module carrier slot 1 : 1088127 AXL SE DI16/1 Module carrier slot 2 : 1088062 AXL SE AI4 | 4-20 Module carrier slot 3 : 1088129 AXL SE DO16/1 Module carrier slot 4 : 1088123 AXL SE AO4 | 4-20 -->Start a New Project Type: Standard Project Device: CODESYS Control Win V3 x64 Language: Structured Text -->Install GSDML File Navigate to: Tools > Device Repository > Install Select the GSDML file path (downloaded from Phoenix Contact for device coupler Part ID: BK PN TPS 2403869) Click Renew Device Repository Close the dialog -->Add Device to Project -->Right-click on Devices > Add Device Issue: Devices from the repository are not available to select or call into the project! I’d really appreciate any guidance or suggestions you can offer. Best Regards Ranadheer Reddy
Last updated: 2025-09-09
Post by ranadheer on PHOENIX CONTACT Axioline PLCnext project in CodeSys SodftPLC
CODESYS Forge
talk
(Post)
Hello Everyone, I'm working on a CODESYS Standard Project using CODESYS Control Win V3 x64 with Structured Text. The goal is to integrate a Phoenix Contact device coupler (Part ID: BK PN TPS 2403869) via PROFINET. Here am using the CODESYS V3.5 SP21 PATCH2 ,VERSION 3.5.21.20 , and Downloaded extension package 4.16.0.0 (old versions are not available in the extension CodeSys installer) Devices used here are: BUS COUPLER : 2403869 BK PN TPS Module carrier slot 1 : 1088127 AXL SE DI16/1 Module carrier slot 2 : 1088062 AXL SE AI4 | 4-20 Module carrier slot 3 : 1088129 AXL SE DO16/1 Module carrier slot 4 : 1088123 AXL SE AO4 | 4-20 -->Start a New Project Type: Standard Project Device: CODESYS Control Win V3 x64 Language: Structured Text -->Install GSDML File Navigate to: Tools > Device Repository > Install Select the GSDML file path (downloaded from Phoenix Contact for device coupler Part ID: BK PN TPS 2403869) Click Renew Device Repository Close the dialog -->Add Device to Project -->Right-click on Devices > Add Device Issue: Devices from the repository are not available to select or call into the project! I’d really appreciate any guidance or suggestions you can offer. Best Regards Ranadheer Reddy
Last updated: 2025-09-09
Post by user0815 on Kommunikation zwischen ROS2 und CODESYS über Web Sockets
CODESYS Forge
talk
(Post)
Hallo zusammen, ich hoffe ihr könnt mir weiterhelfen. Meine CODESYS Version ist die V3.5 SP19 Patch 4 und die Zielsystemversion ist die 4.10.0.0 . Ich verwende CODESYS ohne Lizenz. Ich probiere eine Verbindung über Web Sockets zwischen ROS und CODESYS aufzubauen. Der Client von CODESYS verbindet sich mit dem Ros Bridge Server aber ich weiß nicht wie ich dem Ros Server sage welches Topic er publishen soll. Über Node-Red habe ich eine Verbindung aufbauen können. Dafür habe ich "node-red-contrib-flowake-ros-nodes" verwendet. Den Daten Austausch habe ich mit mit Wireshark angeschaut und nun probiere ich den mithilfe von CODESYS nachzubauen. NAch dem sich der Client verbunden hat muss folgende Nachricht übermittelt werden:"{"op":"call_service","id":"call_service:/rosapi/topic_type:1","type":"rosapi/TopicType","args":{"topic":"/cmd_vel"}}." Ich vermute es funktioniert über Frames aber ich weiß nicht wie ich es umsetzten soll. Besten Dank für die Hilfe und schöne Grüße
Last updated: 2024-01-03
Post by vipul on Multicast udp
CODESYS Forge
talk
(Post)
Hi, Good afternoon can anybody help me with UDP Multicast code. I am not able to send or recieve data when code is dumped on linux device. Below is my code. Declaration: PROGRAM udp_multicast VAR oneTimeFlag :UINT :=0; state: INT:=0; driver: UDP.UDPDriver; //port : UDP.Port;//moved to GVL src_ipAddr_ud: UDINT; src_ipAddr_st:STRING := '192.168.127.155';//'192.168.1.155';//ipms ip address dst_ipAddr_ud:UDINT; group_ipAddr_st:STRING := '239.1.5.10'; //group_ipAddr_ud:UDINT; result: SysTypes.RTS_IEC_RESULT; //result of recieve function. bind: UDINT; //result of binding. resultCreate:SysTypes.RTS_IEC_RESULT;//result of port creation. timer:BLINK; temFlag :INT:= 0; post:INT :=0; checksumFunc:checksumXor; localStringBuf:STRING[500]; chksum:BYTE; dataBuffer:POINTER TO BYTE; checksumString:ARRAY[0..5] OF BYTE; recvSize:__XINT; errorCode:UDINT; joinGroupErrorCode:UDINT; END_VAR ************8 Implementation: IF oneTimeFlag <> 1 THEN oneTimeFlag:=1; resultCreate := driver.CreatePort(ADR(GVL.port)); src_ipAddr_ud := UDP.IPSTRING_TO_UDINT(sIPAddress:= src_ipAddr_st); GVL.group_ipAddr_ud := UDP.IPSTRING_TO_UDINT(sIpAddress:= group_ipAddr_st); GVL.port.IPAddress := src_ipAddr_ud; GVl.port.ReceivePort:= GVL.src_port;//port on which messages are expected. GVl.port.SendPort := GVL.dest_port; GVl.port.OperatingSystem := 0; //0- any system GVL.port.Socket :=3; //3- socket type is multicast bind := GVL.port.Bind(udiIPAddress:=src_ipAddr_ud,); GVl.port.JoinGroup(udiGroupAddress:= GVL.group_ipAddr_ud,udiInterfaceAddress:= src_ipAddr_ud,eLogCode=>joinGroupErrorCode); END_IF timer(ENABLE:=TRUE,TIMELOW:=T#100MS,TIMEHIGH:=T#100MS); IF timer.OUT = TRUE THEN GVL.port.Send(udiIPTo:=GVL.group_ipAddr_ud,GVL.dest_port,pbyData:=ADR(GVL.writeData),diDataSize:=SIZEOF(GVL.writeData)); ELSE SysMemSet(ADR(GVL.readData[0]),0,SIZEOF(GVL.readData)); result := GVl.port.Receive(ADR(GVL.readData),diDataSize:=SIZEOF(GVL.readData),udiIPFrom=>dst_ipAddr_ud,diRecvSize=>recvSize,eLogCode=>errorCode); SysMemMove(ADR(GVL.readDataBuf[0]),ADR(GVL.readData[0]),SIZEOF(GVL.readData)); END_IF post:=LEN(GVL.readDataBuf);
Last updated: 2024-01-14
Post by alex00 on DCS / Central Engineering with Codesys support
CODESYS Forge
talk
(Post)
Hello together I'm currently investing in possibilities to have a central engineering software / system for Codesys based controllers. Something like a DCS / SCADA depending on where you see the functionality. We plan to use more or less vanilla codesys. The tool should support the following: - Connect to multiple PLC's in a project to see its variables and debug it. - Central Engineering capabilities (for example shared libraries in a project). - Download the new code / binaries to the plc. - Maybe have functionality to combine visualization elements and logic together. - See the live status variables on all the systems (crosscommunication). I see that codesys theoretically supports engineering of multiple PLC's, but I couldnt find to much functionality for a DCS type of operation, but that could be lack of knowledge. Any tips from you? Is Codesys good enough for this and maybe there are some manufacturers which build around it? Or are there good tools on the market with Codesys support (and the engineering is separate, but download to codesys possible). The use case is distributed energy installations like Heating pumps, Photovoltaics, etc. All these installations should have a PLC with codesys installed and run in one larger network, the PLC's are connected via VPN. Thanks for your inputs Greetings
Last updated: 2024-02-19
Post by alex00 on DCS / Central Engineering for Codesys
CODESYS Forge
talk
(Post)
Hello together I'm currently investing in possibilities to have a central engineering software / system for Codesys based controllers. Something like a DCS / SCADA depending on where you see the functionality. We plan to use more or less vanilla codesys. The tool should support the following: - Connect to multiple PLC's in a project to see its variables and debug it. - Central Engineering capabilities (for example shared libraries in a project). - Download the new code / binaries to the plc. - Maybe have functionality to combine visualization elements and logic together. - See the live status variables on all the systems (crosscommunication). I see that codesys theoretically supports engineering of multiple PLC's, but I couldnt find to much functionality for a DCS type of operation, but that could be lack of knowledge. Any tips from you? Is Codesys good enough for this and maybe there are some manufacturers which build around it? Or are there good tools on the market with Codesys support (and the engineering is separate, but download to codesys possible). The use case is distributed energy installations like Heating pumps, Photovoltaics, etc. All these installations should have a PLC with codesys installed and run in one larger network, the PLC's are connected via VPN. Thanks for your inputs Greetings
Last updated: 2024-02-19
Post by umdee on Error when monitoring LAD programs
CODESYS Forge
talk
(Post)
System Information from the computer being used: OS Name Microsoft Windows 11 Pro Version 10.0.22631 Build 22631 Other OS Description Not Available OS Manufacturer Microsoft Corporation System Manufacturer Dell Inc. System Model Latitude 5500 System Type x64-based PC System SKU 08B9 Processor Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz, 2112 Mhz, 4 Core(s), 8 Logical Processor(s) BIOS Version/Date Dell Inc. 1.3.11, 6/11/2019 SMBIOS Version 3.2 Embedded Controller Version 255.255 BIOS Mode UEFI BaseBoard Manufacturer Dell Inc. BaseBoard Product 0M14W7 BaseBoard Version A00 Platform Role Mobile Secure Boot State On PCR7 Configuration Elevation Required to View Windows Directory C:\WINDOWS System Directory C:\WINDOWS\system32 Boot Device \Device\HarddiskVolume1 Locale United States Hardware Abstraction Layer Version = "10.0.22621.2506" User Name CARDASSIA-IX\Engineer Time Zone Eastern Daylight Time Installed Physical Memory (RAM) 16.0 GB Total Physical Memory 15.8 GB Available Physical Memory 4.67 GB Total Virtual Memory 18.5 GB Available Virtual Memory 2.52 GB Page File Space 2.63 GB Page File C:\pagefile.sys Kernel DMA Protection Off Virtualization-based security Not enabled Windows Defender Application Control policy Enforced Windows Defender Application Control user mode policy Off Device Encryption Support Elevation Required to View Hyper-V - VM Monitor Mode Extensions Yes Hyper-V - Second Level Address Translation Extensions Yes Hyper-V - Virtualization Enabled in Firmware Yes Hyper-V - Data Execution Protection Yes
Last updated: 2024-03-19
Post by alexgooi on Modbus writing on value change
CODESYS Forge
talk
(Post)
Hi Duvan, You could make this in 1 single object (FB), Indeed don't use a function for this beacuse you need some memory to keep the old value. For i := 0 TO 200 BY 1 DO //Check if the value has been changed IF Old_Value[i] <> Value[i] THEN //Set the trigger to TRUE Trigger[i] := TRUE; Old_Value[i] := Value[i]; END_IF END_FOR If you define the Value array as an In_Out and the Trigger as an In_Out you arn't claiming any aditional memory to your system. You ofcourse then need to add some code arround it that does something with the trigger and writes it back to FALSE again. If you want more flexability you also could use pointers instead of using the IN_OUT FOR i := 0 TO 200 BY 1 DO address := address_Input + i * SIZEOF(*Put type here); IF Address^ <> Old_Value[i] THEN Trigger[i] := TRUE; Old_Value[i] := Address^; END_IF END_FOR
Last updated: 2024-04-02
Post by timvh on License problem gateway
CODESYS Forge
talk
(Post)
What we are trying to explain is that, yes CODESYS creates the software, but Epis decides how they implement it on their hardware, which runtime version they use and they decide which functionality they support. So it is always a combination of the two. What CODESYS provides is a runtime with options for e.g. visualization or softmotion. Epis could add this softmotion license as default to their controller, but if they don't then CODESYS provides another option with a single license in a "Wibu CodeMeter" container. Eventhough the feature exists, Epis has to add this "CodeMeter" software on their controller to be able to access the licenses in the container. We don't know if they did this. Then finally it depends on what type of runtime is on this controller and which license Epis is using. So if they have an OEM license (not an application based license), then most likely you will need the Softmotion license (not a number of axis). See https://store.codesys.com/en/codesys-softmotion-sl-bundle.html. But to be sure if this is supported by the Epis controller, you must ask Epis.
Last updated: 2024-04-30
Post by caprez95 on Trace Restart Visuelement
CODESYS Forge
talk
(Post)
Hallo zusammen. Ich habe schon länger mit dem Problem zu kämpfen, dass ich einen Trend (Visuelement) nicht resetten (neustarten) kann. Ich habe es jetzt mit dem Beispiel hinbekommen, die Trace-Aufzeichnung über die CmpTraceMgr Bibliothek zu steuern. Aber wie bekomme ich diese Trace-Aufzeichnung in ein Visuelement? Der Code sieht wie folgt aus: // Configure trace IF xInit THEN // Create a trace packet PacketConfig.pszName := ADR('IECTraceConfiguration.Trace1'); // Name of trace PacketConfig.pszApplicationName := ADR('IECTraceConfiguration'); // Name of the application PacketConfig.pszIecTaskName := ADR('Task'); // Name of the task PacketConfig.pszComment := ADR('Demo packet'); PacketConfig.ulEveryNCycles := 1; PacketConfig.ulBufferEntries := 1000; PacketConfig.ulFlags := TRACE_PACKET_FLAGS.TRACE_PACKET_FLAGS_TIMESTAMP_MS AND TRACE_PACKET_FLAGS.TRACE_PACKET_FLAGS_AUTOSTART; IF (NOT fbTraceManager.CreatePacket(PacketConfig := PacketConfig, hPacket=>hPacket1)) THEN xError := TRUE; END_IF // Create a trace record RecordConfig.pszVariable := ADR('iSignal'); // This is the name of variable to record RecordConfig.tcClass := INT_TO_UDINT(TypeClass.TYPE_INT); // Type of the recording variable RecordConfig.ulSize := SIZEOF(iSignal); // Size of the recording variable pApp := AppFindApplicationByName('IECTraceConfiguration', 0); AppGetAreaOffsetByAddress(pApp, ADR(iSignal), ADR(RecordConfig.tvaAddress.taAddress.Area.usArea), ADR(RecordConfig.tvaAddress.taAddress.Area.ulOffset)); // Get and set area offsets RecordConfig.tvaAddress.ulAddressFlags := TRACE_VAR_ADDRESS_FLAGS_IEC OR TRACE_VAR_ADDRESS_FLAGS_AREA_OFFSET; RecordConfig.ulGraphColor := 16#FF00FF00; // green RecordConfig.ulGraphType := 1; // Line with points IF (NOT fbTraceManager.AddRecord(RecordConfig := RecordConfig, hPacket := hPacket1, hRecord => hRecord1)) THEN xError := TRUE; END_IF xInit := FALSE; END_IF // Starts the recording IF xStart THEN IF (NOT fbTraceManager.StartPacket(hPacket := hPacket1)) THEN xError := TRUE; END_IF xStart := FALSE; END_IF // Stop the recording IF xStop THEN IF (NOT fbTraceManager.StopPacket(hPacket := hPacket1)) THEN xError := TRUE; END_IF xStop := FALSE; END_IF // Reset the recording IF xReset THEN IF (NOT fbTraceManager.ResetPacket(hPacket := hPacket1)) THEN xError := TRUE; END_IF xReset := FALSE; END_IF
Last updated: 2024-06-04
Post by caprez95 on Trace Restart Visuelement
CODESYS Forge
talk
(Post)
Hello everyone. I've been struggling with the problem for a long time that I can't reset (restart) a trend (visual element). With the example I have now managed to control the trace recording via the CmpTraceMgr library. But how do I get this trace recording into a visual element? The code looks like this: // Configure trace IF xInit THEN // Create a trace packet PacketConfig.pszName := ADR('IECTraceConfiguration.Trace1'); // Name of trace PacketConfig.pszApplicationName := ADR('IECTraceConfiguration'); // Name of the application PacketConfig.pszIecTaskName := ADR('Task'); // Name of the task PacketConfig.pszComment := ADR('Demo packet'); PacketConfig.ulEveryNCycles := 1; PacketConfig.ulBufferEntries := 1000; PacketConfig.ulFlags := TRACE_PACKET_FLAGS.TRACE_PACKET_FLAGS_TIMESTAMP_MS AND TRACE_PACKET_FLAGS.TRACE_PACKET_FLAGS_AUTOSTART; IF (NOT fbTraceManager.CreatePacket(PacketConfig := PacketConfig, hPacket=>hPacket1)) THEN xError := TRUE; END_IF // Create a trace record RecordConfig.pszVariable := ADR('iSignal'); // This is the name of variable to record RecordConfig.tcClass := INT_TO_UDINT(TypeClass.TYPE_INT); // Type of the recording variable RecordConfig.ulSize := SIZEOF(iSignal); // Size of the recording variable pApp := AppFindApplicationByName('IECTraceConfiguration', 0); AppGetAreaOffsetByAddress(pApp, ADR(iSignal), ADR(RecordConfig.tvaAddress.taAddress.Area.usArea), ADR(RecordConfig.tvaAddress.taAddress.Area.ulOffset)); // Get and set area offsets RecordConfig.tvaAddress.ulAddressFlags := TRACE_VAR_ADDRESS_FLAGS_IEC OR TRACE_VAR_ADDRESS_FLAGS_AREA_OFFSET; RecordConfig.ulGraphColor := 16#FF00FF00; // green RecordConfig.ulGraphType := 1; // Line with points IF (NOT fbTraceManager.AddRecord(RecordConfig := RecordConfig, hPacket := hPacket1, hRecord => hRecord1)) THEN xError := TRUE; END_IF xInit := FALSE; END_IF // Starts the recording IF xStart THEN IF (NOT fbTraceManager.StartPacket(hPacket := hPacket1)) THEN xError := TRUE; END_IF xStart := FALSE; END_IF // Stop the recording IF xStop THEN IF (NOT fbTraceManager.StopPacket(hPacket := hPacket1)) THEN xError := TRUE; END_IF xStop := FALSE; END_IF // Reset the recording IF xReset THEN IF (NOT fbTraceManager.ResetPacket(hPacket := hPacket1)) THEN xError := TRUE; END_IF xReset := FALSE; END_IF
Last updated: 2024-06-04
Post by aris on Modbus write via FB failure
CODESYS Forge
talk
(Post)
Hi all, I am using CoDeSys V3.5 and a soft controller Win V3x64. I am trying to read a modbus slave via Function Blocks and not via the channels of the hardware tree for the Slave. I created some requests of type ModbusRequest and I notice that I can read Input Registers and Coils but I can not write Holding Registers and Coils. I am using the library IoDrvModbusTCP 4.1.0.0. When i just use a single modbus request with FC06 (or FC16), there is no request sent to the slave and although the xExecute takes its true value from a pulse of 2 seconds duration, I take almost every 3 minutes an error "TCP_COMMUNICATION_ERROR - 16#A5 - TCP Port. error. Request was not sent". My code is ok because if i change the function code for reading registers, everything works fine. Did anyone have this issue in the past? Thank you in advance.
Last updated: 2025-11-06
Post by risele on Modbus connection via Qronox PCD3 M6893
CODESYS Forge
talk
(Post)
You are welcome. Also note, that it's valid only if you modbus-device use same real/float value representation (IEEE 754). That's true for most of systems. But some devices may have other representation, such as integer + position of the decimal point, for example 123.456 is integer = 123456 and position = 3 Also note, that, ones again, depending on endianess of each system, you may also need to swap not just words, but bytes. TYPE u_Real : UNION rVal:REAL; wVal:ARRAY[0..1] OF WORD; bVal:ARRAY[0..3] OF BYTE; dwVAL:DWORD; //same as previous, may be easier to specify the MB register END_UNION END_TYPE than swapping may be something as VAR A,B,C,D:BYTE; //Bytes of the real value uIn, uOut:u_Real; rVal:REAL; ModbusReg1,ModbusReg2:WORD; END_VAR uIn.rVal:=rVal; uOut.A:=uIn.D; uOut.B:=uIn.C; uOut.C:=uIn.B; uOut.D:=uIn.A; ModbusReg1:=uOut.wVal[0]; ModbusReg1:=uOut.wVal[2]; Or you even need to reorder bits... Ones again, sending float/real values is not defined by Modbus protocol itself, so it is hardware- and software-dependent. The Modbus Poll (and most of modbus tools) have configuration parameters that will properly swap bytes on their side. Ones again, that's very helpful: https://www.scadacore.com/tools/programming-calculators/online-hex-converter/
Last updated: 2026-02-19
Post by risele on Modbus connection via Qronox PCD3 M6893
CODESYS Forge
talk
(Post)
First, if you don't need to change conversion rules in runtime, take a look at "Unit conversion" module (Application -> add object -> UnitConversion). You can specify there biderectional conversion with different units, limits and so on. Second, since MODBUS don't have "real" types but only general 16-bit registers and Real is 32-bit, generally you need a byte-was conversion Real <> two Words. Note, that depending on the devices on both sides, there are two options: Real-> Word1, Word2 or Real-> Word2, Word1, where Word1 is minor register in Modbus register pair and Word2 is major. You can use simple union: TYPE u_Real : UNION rVal:REAL; wVal:ARRAY[0..1] OF WORD; dwVAL:DWORD; //same as previous, may be easier to specify the MB register END_UNION END_TYPE and convert it as following: VAR myUnion:u_Real; rValue_TO_SEND:REAL; rValue_TO_GET:REAL; END_VAR myUnion.rVal:=rValue_TO_SEND; rValue_TO_GET:=myUnion.rVal; Note, that WORD-order should be properly set in MODBUS registers, otherwise you will get strange values. This tool is helpful: https://www.scadacore.com/tools/programming-calculators/online-hex-converter/ Alternative, you can use functions as REAL_TO_DW and DW_TO_REAL from OSCAT_BASIC, for example.
Last updated: 2026-02-19
Post by alessandro on SysMemCmp SysMemCpy
CODESYS Forge
talk
(Post)
VAR Data1:ARRAY[1..10] OF SINT ; Data2:ARRAY[1..10] OF SINT ; Data3:ARRAY[1..10] OF SINT ; Data4:ARRAY[1..10] OF SINT ; ex_1 : BOOL ; ex_2 : BOOL ; enable : BOOL :=0 ; END_VAR // PROGRAM // The scope of this example is compare and copy the values of two ARRAY only if some value is different using SysMemCmp and SysMemCpy. // In this 2 example we don't use a FOR cicle for do this, and pBuffer1 and pBuffer2 is just a pointer to ARRAY. See details in Library util.SysMem of Codesys // The compare funcion util.SysMem.SysMemCmp is bidirectional if Data1 chanege respect Data2 ex_1 go to 1 and if Data2 change respect Data1 also // but the copy function util.SysMem.SysMemCpy work only from source ARRAY pSrc:=ADR(Data1) to destination ARRAY pDest:=ADR(Data2) // Example 1 Full ARRAY compare and copy // This compare 2 different equal ARRAY and if there is some difference ex_1 go to 1 and if you give enable he copy Data1 in Data2 ex_1 := TO_BOOL(util.SysMem.SysMemCmp(pBuffer1:=ADR(Data1), pBuffer2:=ADR(Data2), udiCount:=SIZEOF(Data1))); IF ex_1 AND enable THEN util.SysMem.SysMemCpy(pDest:=ADR(Data2), pSrc:=ADR(Data1), udiCount:=SIZEOF(Data1)); END_IF // Example 2 Only selected area of the ARRAY compare and copy // This compare 2 different equal ARRAY starting from position number [3] for 4 byte in this case start at position [3] and finish at position number [6] // and if there is some difference only in area [3..6] of the ARRAY ex_2 go to 1 if you give enalbe he copy Data3[3..6] in Data4[3..6] // if something change in other array position[0..2] or [7..10] are ingnored ex_2 := TO_BOOL(util.SysMem.SysMemCmp(pBuffer1:=ADR(Data3[3]), pBuffer2:=ADR(Data4[3]), udiCount:=4)); IF ex_2 AND enable THEN util.SysMem.SysMemCpy(pDest:=ADR(Data4[3]), pSrc:=ADR(Data3[3]), udiCount:=4); END_IF // Attention udiCount input is intended in <byte> in the example 1 I pass to udiCount:=SIZEOF(Data1) for compare and copy the intere ARRAY and // SIZEOF pass the size of intere ARRAY in byte to the function input, in this 2 examples I used variable type SINT each one occupie 1 byte and one position in the ARRAY // and in the example 2 I pass udiCount:=4 for compare and copy only 4 position of Data3/4[3..6] if you want to extend this example and use it for an ARRAY OF WORD // remember that each WORD will occupe 2 byte (16 bit) and you will have to pass udiCount:=SIZEOF(Data1) if you need to compare intere ARRAY example 1 // but need udiCount:=(42) for the example 2 because need to compare and copy 4 word each occupie 2 byte (16 bit). // For REAL (32 bit) need udiCount:=SIZEOF(44) for LREAL or (64 bit) need udiCount:=SIZEOF(416) // a good rule is calculate the dimension of the ARRAY in byte without empty space at the end, multiple of data type number for variable bigger then 8 bit // Example : If you want to create an ARRAY for 5 REAL (32 bit) each occupie 4 byte the correct size is ARRAY[0..19] OF REAL 54=20 position. // NOTE : In the example the position of compare function util.SysMem.SysMemCmp is first and the copy function util.SysMem.SysMemCpy inside the IF is after // in one cycle of the program the two array is compared and if there is some difference and enable are copied. // If you move util.SysMem.SysMemCmp after the IF cycle he will copare the ARRAY in the current cycle but the copy of the value will do in the next cycle.</byte>
Last updated: 2025-10-24
Post by serwis on Dynamic target position tracking
CODESYS Forge
talk
(Post)
Hello, I am trying to control a servo drive and dynamically set its position. I control the drive via EtherCAT with a cycle time of 500us. I use the MC_MoveAbsolute block for this. The problem is that when using a PID controller, I generate the positions I want the drive to move to on an ongoing basis, and I would like the position to be set immediately. The MC_MoveAbsolute block must receive a rising edge to execute, and I would like the movement to be performed without waiting for this edge. I have created a function that generates a rising edge every 1 ms, but I am unable to change this time to 500 µs because the TON function does not support times shorter than 1 ms. Below is the code to call the rising edge: IF Exe = TRUE THEN delay1(IN:=TRUE, PT:=T#1MS); IF delay1.Q = TRUE THEN Exe := FALSE; delay1(IN:=FALSE); END_IF END_IF IF Exe = FALSE THEN delay(IN:=TRUE, PT:=T#1MS); IF delay.Q = TRUE THEN Exe := TRUE; delay(IN:=FALSE); END_IF END_IF END_IF Here is the code for calling the MC_MoveAbsolute function: MoveDegree( Axis:= Tilt, Execute:= Exe, Position:= position_target - (base_angle_real * feedforward_turn), Velocity:= vel, Acceleration:= acc, Deceleration:= dec, Jerk:= jerk, Direction:= MC_DIRECTION.shortest, BufferMode:= MC_BUFFER_MODE.Aborting, Done=> , Busy=> , Active=> , CommandAborted=> , Error=> , ErrorID=> ); I realize that there are probably better methods for performing this type of task. How can I implement motion with a dynamically changing setpoint? THANKS
Last updated: 2025-09-05
Post by gallusrrr on usb2can in Codeysy 3.5 Can Gateway
CODESYS Forge
talk
(Post)
Hallo und guten Morgen, Ich danke für die Rückmeldung. ich habe das oben geschriebene durchgeführt und auch festgestellt das mit die Commandos für die Can befehle noch fehlen. (Google angeschmissen und geschaut auch gefunden) sudo apt-get install can-utils (damit auch jemanden anders der Post hilft) Anschließend habe ich das CAN System komplett aufgebaut so das ich mit einen anderen CAN Adapter schauen konnte ob die Nachricht auch ankommt. die Nachricht kommt an :) danach habe ich follgende Ausgabe: pi@Codesys:~ $ sudo ip -s -d link show can0 3: can0: <noarp,up,lower_up,echo> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10 link/can promiscuity 0 allmulti 0 minmtu 0 maxmtu 0 can state ERROR-ACTIVE restart-ms 0 bitrate 250000 sample-point 0.875 tq 250 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1 brp 12 gs_usb: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..1024 brp_inc 1 clock 48000000 re-started bus-errors arbit-lost error-warn error-pass bus-off 0 0 0 0 0 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 parentbus usb parentdev 1-1.4:1.0 RX: bytes packets errors dropped missed mcast 3549 819 0 0 0 0 TX: bytes packets errors dropped carrier collsns 32 4 0 0 0 0</noarp,up,lower_up,echo> (Sorry habe kein Speicherplatz im Web um Bilder anzuzeigen..) man kan sehen das die Nachricht abgeht und auch 32 Byte Empfangen worden sind. Die nachricht ist auch am anderen CAN Adapter sichtbar gewesen. Wie bekomem ich den einrichteten Adapter in Codesys rein? das ich den Befehl sudo ip link set can0 up type can bitrate 500000 das ich die Einrichtungs des Can Adapters noch in die Rasperry Start rutine nehmen muss ist mir klar. Ich bedanke mich .
Last updated: 2024-01-18
Post by john-robinson on Limiting Memory Access of an Array to Within its Bounds
CODESYS Forge
talk
(Post)
Recently we had an issue regarding some simple code to calculate a rolling average. The code indexes from zero to 199 to properly store the current input into a circular buffer which then allows us to calculate a rolling average: VAR input_5s : REAL; outs_arr : ARRAY[0..199] OF REAL; i : USINT := 0; END_VAR ___ //this code runs every five seconds, calculating a rolling average outs_arr[i] := input_5s; i := i + 1; output := OSCAT_BASIC.ARRAY_AVG(ADR(outs_arr), SIZEOF(outs_arr)); IF i >= SIZEOF(outs_arr) THEN i := 0; END_IF There is a simple bug in this code where the index will be set to 0 when it has surpassed the length of the array in bytes (800 in this case) rather than larger than the number of reals in the array (200). The solution here is simple, replacing i >= SIZEOF(outs_arr) with i >= SIZEOF(outs_arr)/SIZEOF(outs_arr[0]). In this example when the index increased to 201 and the line outs_arr[201] := input_5s was called, codesys arbitrarily wrote to the address in memory that is where outs_arr[201] would be if the array was that long. I would like to find a way to wrap the codesys array inside of a wrapper class that checks if an input is within the bounds of an array before writing to that value. I know how I would implement that for a specific array, I could create a method or class that takes an input of an array of variable length, ie. ARRAY[*] OF REAL, but I don't know how to make this for any data type. I am wondering if anyone has ever done anything similar to this, or has any better suggestions to ensure that none of the programmers on this application accidentally create code that can arbitrarily write to other locations in memory.
Last updated: 2024-03-05
To search for an exact phrase, put it in quotes. Example: "getting started docs"
To exclude a word or phrase, put a dash in front of it. Example: docs -help
To search on specific fields, use these field names instead of a general text search. You can group with AND or OR.