Post by fajean on Issues with "Add all instance path"
CODESYS Forge
talk
(Post)
In the past, we have routinely used the "add all instance paths" function to automatically add variables to VAR_CONFIG lists. My recollection is that compiling a project did not require VAR_CONFIG to be fully populated, and, once successfully compiled, instance paths could be added. Errors related to missing declarations, if I recall correctly, were thrown when downloading to the PLC, they did not prevent a successful compile. At some point, it stopped working. Missing declarations in a VAR_CONFIG now cause a compile error, so the application is never "current", the only reason I can see being the missing VAR_CONFIG declarations themselves (no other error). We observe the same behavior across all our projects. This is really aggravating, and I must be missing something simple. We use 3.5 SP17p3, 64 bits. Can anyone help?
Last updated: 2023-12-29
Post by alexgooi on Codesys licensing explanation
CODESYS Forge
talk
(Post)
Dear Forum, We are currently switching to a native Codesys controller, and I'm currently trying to determine the correct license. I have a question regarding the Modbus instances. With the Standard S license this is set to 4 (See picture). In our projects we are using a lot of communications to Modbus servers using a Codesys Controller, for this communication I'm using the ModbusFB library (supplied by 3S) (see picture). In my project I would like to use more than 4 instances of the ClientTCP FB. My question is, is this now capped at 4 possible connections with the standard S license. Or do these function blocks have a different relation with the license? Some clarity on this topic would be very welcome. Thank you in advance
Last updated: 2024-02-15
Post by esave on Stepper Drive with Ethercat
CODESYS Forge
talk
(Post)
Hello everybody I am new into Codesys. I have a stepper driver (EM3E-556E) from Leadshine. I want to controll the stepper driver via EtherCat to a ST programm but I dont have any function block or anything that i can use. I only have the XML-File wich I loaded. With it I implemented the drive as a Ethercat slave and now I see these variables. (See picture) I dont know how to controll the stepper drive. And the manufacturer doesnt provide support for me. Can anybody help me or atleast tell me how they would do it?
Last updated: 2024-03-14
Post by fenicklar on Login problem with FileTransfer on Raspberry Pi 5
CODESYS Forge
talk
(Post)
Hello everyone, I'm currently trying to set up a FileTransfer function from a Webvisu to my Raspberry Pi 5 on Codesys 3.5 SP 19 Patch 6. I went in the files CODESYSControl.cfg and CODESYSControl_User.cfg and added : [CmpWebServerHandlerV3] AllowFileTransferServices=1 And it seems to be working. However, I cannot access my several Webvisu without putting my login. That's a problem because one of my webvisu is in kiosk mode on the raspberry itself and there is nokeyboard attached, it's just an information screen, but I can't view it. Is there a wey to enable the File Transfer without requiring to login ? Thank you for your time
Last updated: 2024-03-18
Post by mani-i4point0 on Issue with WebVisu on Raspberry PI
CODESYS Forge
talk
(Post)
Hi, I am running Codesys Runtime by purchasing 'Codesys control for raspberry pi MC SL', I am trying to use the Variables from my GVL's. Few of the variables used as a Pushbutton form the Visualization. These 'BOOL' Variable getting unlatched automatically even though there is no write function in the Overall project. All of them are 'Read' functions, at the same time few other BOOL variable behaviors are seems to be fine. I have tried, clean all and download, serval time restarted the hardware. Happy to share any any information. Your input to resolve this issue would be highly appriciated. Version Details: codesyscontrol 4.8.0.0, armhf codesyscontrol based on SDK 3.5.19.0
Last updated: 2024-03-20
Post by albzen on EtherCat Slaves diagnosis
CODESYS Forge
talk
(Post)
Hello everybody, I'm working on a RunTime Plc (Codesys 3.5.16/18.20) connected to an EtherCat bus with many devices. The bus has some communication fault but I don't know how understand which is the device or the cable that has the trouble. To understand the cause of the problem I would like to read the WKC (Working counter) of the devices (0x0300...0x030C), how is explained in EtherCat documents, but it seems that the read of the counter is disabled. Attached there is an extract of the Ethercat document. Can anyone give me some advice about how and with function can I read it. Thank you in advance!
Last updated: 2024-03-29
Post by albzen on EtherCat Slaves diagnosis
CODESYS Forge
talk
(Post)
Hello everybody, I'm working on a RunTime Plc (Codesys 3.5.16/18.20) connected to an EtherCat bus with many devices. The bus has some communication fault but I don't know how understand which is the device or the cable that has the trouble. To understand the cause of the problem I would like to read the WKC (Working counter) of the devices (0x0300...0x030C), how is explained in EtherCat documents, but it seems that the read of the counter is disabled. Attached there is an extract of the Ethercat document. Can anyone give me some advice about how and with function can I read it. Thank you in advance!
Last updated: 2024-03-29
Post by alexgooi on Modbus writing on value change
CODESYS Forge
talk
(Post)
The way I usally tackle this is by syncing only words (then you are able to use the FB above). If you then want to write a Boolean simply type it like this. Value[1].0 := Bool1; Value[1].1 := Bool2; Value[1].2 := Bool3; Uints have the same number of bits than a INT/WORD so these ones will work as well (they are only represented diffrently). A Real will work but you will loose some infomration in the conversion. If you want to keep the information you can convert 2 words to a float with a function (for example with the IEEE-754 standard) . In this way the syncing to the server is very simple and in the Codesys Program you decide what part of the word you want to use.
Last updated: 2024-04-03
Post by pethun on Upgrade from codesys 3.5.19 to 3.5.20
CODESYS Forge
talk
(Post)
Hi We upgraded our ptoject from 3.5.19 to 3.5.20 but we get an error message in the latest version. We made our own trend function and its related to this we get error message: Trend_Menu Device: PLC Logic: Application: C0032: Cannot convert type 'RTS_SYSTIMEDATE(systimertc, 3.5.20.0 (system))' to type 'RTS_SYSTIMEDATE(systimertc, 3.5.17.0 (system))' The variables are defined as follow: start : SysTimeRtc.SYSTIMEDATE; end : SysTimeRtc.SYSTIMEDATE; The code that creates the error is the variable start and end IF xAssign THEN xAssign := FALSE; xPanEnable := FALSE; xZoomEnable := FALSE; drs.liFrom := VisuTrendStorageAccess.TrendStorageConvertToTimestamp(start, 0 (us)); drs.liTo := VisuTrendStorageAccess.TrendStorageConvertToTimestamp(end, 0 (us)); drs.m_itfDateRangeSelectorClient.SetCurrentRange(drs.liFrom, drs.liTo); END_IF I cant understand really what the error message means and what can be the cause of the error? It compiles fine in dthe older codesys 3.5.19. If anyone has some experience of this please help us out? We must upgrade due to the new licenses. Thanks
Last updated: 2024-04-20
Post by pethun on Upgrade from codesys 3.5.19 to 3.5.20
CODESYS Forge
talk
(Post)
Hi We upgraded our ptoject from 3.5.19 to 3.5.20 but we get an error message in the latest version. We made our own trend function and its related to this we get error message: Trend_Menu Device: PLC Logic: Application: C0032: Cannot convert type 'RTS_SYSTIMEDATE(systimertc, 3.5.20.0 (system))' to type 'RTS_SYSTIMEDATE(systimertc, 3.5.17.0 (system))' The variables are defined as follow: start : SysTimeRtc.SYSTIMEDATE; end : SysTimeRtc.SYSTIMEDATE; The code that creates the error is the variable start and end IF xAssign THEN xAssign := FALSE; xPanEnable := FALSE; xZoomEnable := FALSE; drs.liFrom := VisuTrendStorageAccess.TrendStorageConvertToTimestamp(start, 0 (us)); drs.liTo := VisuTrendStorageAccess.TrendStorageConvertToTimestamp(end, 0 (us)); drs.m_itfDateRangeSelectorClient.SetCurrentRange(drs.liFrom, drs.liTo); END_IF I cant understand really what the error message means and what can be the cause of the error? It compiles fine in dthe older codesys 3.5.19. If anyone has some experience of this please help us out? We must upgrade due to the new licenses. Thanks
Last updated: 2024-04-20
Post by m83coding on Raspberry Pi Codesys SPI Master
CODESYS Forge
talk
(Post)
Hello, I am trying to control shift registers 74HC596 and 74HC165 via Raspberry PI with SPI interface. So far I did it with a Microcontroller and now I wanna upgrade my Projekt with Raspberry Pi and Codesys Software to be more flexible. I tried to adapt PiFace Function Block to just send or recive a 8 bit via SPI interface of the my Raspberry Pi. With following code (see attached screenshots) * PLC_PRG * PiFaceDigital * PiFaceDigital.write8 * PiFaceDigital.read8 I have a signal at SCK and MOSI pin of the PI, so far so good. But I really struggle with the unterstanding of the code. Is there some detailed description of each line of code? Or is there somebody in the community who can explain each line of code? Or is there a more simple way to send / recive 8 bit via SPI? Manuel
Last updated: 2024-04-23
Post by bjarne-pagaard on Codesys v3.5 Sint to byte
CODESYS Forge
talk
(Post)
Hi A SINT is a short (signed) integer. It is already only 1 byte - so you should have no problem casting it to a byte like so: bMyByte := TO_BYTE(sintMyShortInt); If you have a regular INT you want to put in 2 bytes - there are a lot of ways you can do this. A Union is certainly one of them. You could have a union with 2 memebers: An array of 2 bytes as one member, and an integer value as another member. Another way would be to look at MEMCPY to put the value into your CAN-message. .. or create a function to take your input value as input, and giving you 2 individual bytes as output. This could be handy if you need to change the byte-order. Integer data types: https://help.codesys.com/webapp/_cds_datatype_integer;product=codesys;version=3.5.17.0 -Bjarne
Last updated: 2024-04-24
Post by gseidel on CNC / G01 Speed is very slow (or go-stop motion) in Continuous short segment .
CODESYS Forge
talk
(Post)
Hi k2saki, I would recommend to have a look at SMC_SmoothMerge, followed by SMC_SmoothPath. SmoothMerge will combine the small G1 elements to longer splines, SmoothPath will avoid stops between the splines. https://content.helpme-codesys.com/en/libs/SM3_CNC/Current/SM_CNC_POUs/SoftMotion-CNC/SoftMotion-Function-Blocks/SMC_SmoothMerge.html For SmoothMerge to work, you have to configure a tolerance, i.e. by how much it may deviate from the lines. To graph the output of the interpolator, you can use the trace. (Add a trace object below the application, and add the variables you are interested in to the trace.) Best regards, Georg
Last updated: 2024-04-30
Post by k2saki on CNC / G-Code streaming processing ( to start quickly in long G-Code File )
CODESYS Forge
talk
(Post)
Is it possible like G-Code streaming processing (like FANUC or SIEMENS DNC Function )? Or Does anyone know the tips for CODESYS Motion to start moving long Long G-Code File quickly? I have to wait long time after "Start" button to start moving, I have to wait finishing interpreting whole G-Code file, ( and I have to prepare huge buffer to store. ) Now, I'm working on my CNC Project using SMC_ReadNCFile2, and SMC_NcInterpreter to preprocess G-Code. I tried to set SMC_Interpolator.xExecute to true to Start while after SMC_NcInterpreter processed more 50-line of G-Code, but that not worked, I had to wait SMC_NcInterpreter processed all lines to start SMC_Interpolator. G-Code have about 2000 lines of XY of G01 (or more over.. ) of short segment that a CAM software has exploded from NURBS Curve.
Last updated: 2024-05-03
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 mawaloc on KeyPad Function in Visualization to fill a table
CODESYS Forge
talk
(Post)
Hello Everybody, Hope you're all doing good for this new year. Since a time, I'm looking on how to use the KeyPad in vizualization to fill a textlist or something similar. my application is : In one window, I would need to be able to writte a string linked to an Numeric Values. => I can't use a std text list inside my software, as per this would be custom by customer. then from another windows I would need a "text box" to be able to select any of this String. I hope it's clear enought. thankyou for the help
Last updated: 2026-01-07
Post by konstantin on Lenze i950 Servo and WAGO PFC200
CODESYS Forge
talk
(Post)
Hello, basically the i950 drive support CiA402 Basic and CiA402 Advanced modes. I attached pictures of both mode supported functions. It also support CSP, VL, CSV and CST modes. It seems the homing mode is in CiA402 Advanced mode but how can you not have the homing mode in both modes? It is a vital part of any servo system. If I use the SoftMotion standard demo mode, I can move the servo absolute and relative but cannot home it. But in SoftMotion Light mode, I cannot execute any motion function. Here is the official manual for i950 servo drive - i950 Documentation Best Regards Konstantin Kolev
Last updated: 2026-02-13
Post by imdatatas on The default ramp type selection in SoftMotion V4.18.0.0 is Quadratic
CODESYS Forge
talk
(Post)
Dear @gseidel, Thank you for your clarification. I fully agree that the quadratic ramp type may have certain technical advantages. However, the main problem is backward compatibility and consistency across projects. In many automation projects, application developers rely on the fact that creating a new axis object will behave exactly the same way as in previous versions. With SoftMotion V4.18.0.0 and later, if an application developer adds an axis and overlooks the changed default, the motion function blocks behave differently than expected. In particular, since the Jerk value in SM3_Basic function blocks is ineffective in trapezoid ramp type, users are accustomed to leaving this parameter empty in their projects. In many existing projects, this variable has not even been assigned. When the default is changed to quadratic, the Jerk parameter suddenly becomes relevant, which can cause errors or unexpected behaviour in the field. From a user perspective, a default setting should always be the “safe” and “expected” option, while alternative options (like quadratic) can be selected manually if desired. Keeping the default as trapezoid ensures compatibility with existing projects and prevents unexpected issues, while still allowing users to benefit from quadratic ramps if they explicitly choose so. For these reasons, I kindly ask you to reconsider making trapezoid the default again. This would significantly reduce the risk of unexpected behaviour in future projects while still preserving the advantages of the quadratic ramp type for those who actively select it. Of course, the final decision is entirely at your discretion. Best Regards, imdatatas
Last updated: 2025-09-26
Post by matteodigani on Error using function block "Write alias address"
CODESYS Forge
talk
(Post)
Hi, I've got a problem using the function block "Write alias address" (ETCStack library 4.9.0.0). this is the code: EtherCAT_1(); IF EtherCAT_1.ConfigRead AND enable THEN CASE seq OF 0: exec := FALSE; T.IN := TRUE; T.PT := T#10S; T(); IF T.Q THEN seq := 1; T.IN := FALSE; END_IF ; 1: T.IN := FALSE; T(); //THIS ONE WORK CORRECTLY! WrAliasAdd.xAbort := FALSE; WrAliasAdd.usiCom := DWORD_TO_USINT(EtherCAT_1.InstanceNumber); WrAliasAdd.wSlaveAddress := 1002; WrAliasAdd.xAutoIncAdr := FALSE; WrAliasAdd.uiAliasAddress := 19; WrAliasAdd.udiTimeOut := 3000; IF start THEN exec := TRUE; ELSE IF NOT error THEN start := TRUE; END_IF END_IF IF WrAliasAdd.xDone THEN start := FALSE; done := TRUE; error := FALSE; exec := FALSE; seq := 5; END_IF IF WrAliasAdd.xError THEN start := FALSE; done := FALSE; error := TRUE; exec := FALSE; END_IF ; 5: exec := FALSE; T.IN := TRUE; T.PT := T#1S; T(); IF T.Q THEN seq := 10; END_IF ; 10: T.IN := FALSE; T(); //THIS ONE GIVES ME AN ERROR! WrAliasAdd.xAbort := FALSE; WrAliasAdd.usiCom := DWORD_TO_USINT(EtherCAT_1.InstanceNumber); WrAliasAdd.wSlaveAddress := 1006; WrAliasAdd.xAutoIncAdr := FALSE; WrAliasAdd.uiAliasAddress := 25; WrAliasAdd.udiTimeOut := 1000; IF start THEN exec := TRUE; ELSE IF NOT error THEN start := TRUE; END_IF END_IF IF WrAliasAdd.xDone THEN start := FALSE; done := TRUE; error := FALSE; exec := FALSE; seq := 99; END_IF IF WrAliasAdd.xError THEN start := FALSE; done := FALSE; error := TRUE; exec := FALSE; END_IF ; ELSE ; END_CASE WrAliasAdd(xExecute := exec); END_IF The first one slave ethercat works correctly, but the other one gives me an error. Attached the ethercat configuration of the devices. All the devices are set "Optional". So my idea is to enable only the first one (1002) and the fifth one (1006).
Last updated: 2025-10-01
Post by manuknecht on Maximum dynamic limits of MC_MoveLinearAbsolute and MC_MoveLinearRelative
CODESYS Forge
talk
(Post)
Hello all I use an axis group with two linear axes in a kinematic system. Using MC_MoveLinearAbsolute and MC_MoveLinearRelative, I am trying to realise dynamic movements (set velocity: 1 m/s, set acceleration: 30 m/s^2) with the highest possible jerk, as I want to compare this with a movement with a trapezoidal velocity profile. However, my measurements show that the axes accelerate with a maximum jerk of approx. 800 m/s^3, even if the value in the function block was set to 10,000 m/s^3. I have already increased the dynamic limits of the two axes accordingly (Velocity: 5000 u/s, Acc-/Deceleration: 250'000 u/s^2, Jerk: 100'000'000 u/s^3, where 1 u = 1 mm), but this had no effect. I have checked the input parameters of the function blocks and the VelFactor, AccFactor and JerkFactor factors are all set to the maximum (value 1). Reducing the cycle time has resulted in a higher jerk, but as we are already working with a cycle time of 1 ms, there is nothing more that can be done here. The axes themselves are still a long way from drawing the maximum current, which is why I assume that this should not be a problem either. Are there other factors or parameters that influence the dynamic limits and therefore allow faster movements? The PLC I am using is a Raspberry Pi 4 and Codesys V3.5 SP20 with all libraries up to date. Thanks in advance Manuel
Last updated: 2024-05-08
Post by yannickasselin on Lenze i950 Servo and WAGO PFC200
CODESYS Forge
talk
(Post)
I don't have time to go through the whole manual but as I said earlier, the servo drive does not support any of the modes needed for SoftMotion Light to work. If you want to use the full SoftMotion, you could use SMC_Homing function block to do the homing. This function block does not use the Homing Mode. It still uses the CSP mode and does the logic in Codesys runtime instead of in the servo drive. Read the documentation about it to see if it fits your needs. But if your controller only supports SoftMotion Light, I am afraid you will not be able to use the i950. I do a lot of motion stuff with different servo brands. Some support all the modes needed for SoftMotion Light and some don't. You really need to make sure the modes are supported before choosing a brand over another. I tend not to use brand specific controllers in order not to be limited by their supported features. I usually choose a PC (Linux or Windows) and install the Codesys runtime and licences myself. This is the most flexible way to use Codesys in my opinion. Depending on how many axes are needed in your project, a full SoftMotion license may not be more expensive than SoftMotion Light because SoftMotion is available as Application based license whereas SoftMotion Light is not. But of course, SoftMotion is harder on the CPU than SoftMotion Light.
Last updated: 2026-02-13
Post by struccc on Inheritence of struct,
CODESYS Forge
talk
(Post)
Strangely reminds me to my struggles... Want to do something "Elegant", reusable, universal, practical... In CODESYS??? 🙃 First of all, before you get too deep into this: If you could find a way, to make a "universal" log entry object, containing the variable length data itself, you wouldn't be able to store them in an array, or access them like an array, or pass them by value as a type. (please correct me, if I'm wrong, incorrect, or not precise). Because... Basically you can't declare a type with variable memory footprint. This is a very deeply embedded characteristic of CODESYS, and all IEC 61131-3 systems, and it has many reasons behind. And yes, it is a very common trap / mistake, to forget about. So, with a log entry - I guess - it's pretty much the purpose: store data and metadata together, and then handle it in a uniform way. There are ways to handle this, really depends on what is the purpose. For example: 1. Entries with fixed length (Maybe it is not as evil as it looks for the first time. Depends on the situation, but definitely the fastest and easiest code) You can have your base object, with an internal, fixed length string or byte array variable. I would go with a string, and call it _Data.; And then you can make properties, like As_Bool, As_Int, As_Real... In the 'set' accessors, you can do like: pReal := ADR(_Data); // POINTER TO REAL As_Real := pReal^; In the 'get' accessors, evidently: pReal := ADR(_Data); // POINTER TO REAL pReal^ := AS_Real; Or, can use ANY type, if you are not obsessed with variable / property like access: 2. Fixed length, but nicer First, some disadvantage to any values: - You can only assign values with write access. No literals, constants, etc... - Can only be used as input variable of function or function_block - Therefore, stg you could reach: LogEntry.Initialize (stVariable|rVariable|iVariable|xVariable); Just a quick example (it's funny to play with ANY): Be careful it was not tested. I'm sure can be done better, please feel free to comment FUNCTION_BLOCK FB_LogEntry VAR_INPUT MsgClass : UDINT; // Like DEBUG, WARN, ERR... MsgCode : UDINT; // Like Errors.ERR_FAILED MsgTS : DT; // The timestamp END_VAR VAR _Data : STRING(80); // Our data container... _Descr : __SYSTEM.AnyType; // A standard descriptor for our data, containing TYPE_CLASS, address and size END_VAR METHOD SET_Value : BOOL VAR_INPUT anyValue : ANY; END_VAR VAR I : DINT; diSize : DINT; pStr : POINTER TO STRING; END_VAR // Check what did we receive in anyValue. diSize := anyValue.diSize; // We use constant __SYSTEM.TYPE_CLASS to identify the received data type CASE anyValue.TypeClass OF // Maybe we don't want to store references, pointers... and who knows what else... __SYSTEM.TYPE_CLASS.TYPE_REFERENCE, __SYSTEM.TYPE_CLASS.TYPE_POINTER : SET_Value := FALSE; // For the planned types we will be just fine. TYPE_CLASS.TYPE_BOOL, TYPE_CLASS.TYPE_INT, TYPE_CLASS.TYPE_REAL : SET_Value := TRUE; // Optionally string can be handled separately, maybe we have received STRING(255), but practically it is shorter than 80 bytes... TYPE_CLASS.TYPE_STRING : pStr := anyValue.pValue; diSize := MIN(anyValue.diSize, LEN(pStr^) + 1); // Get the actual size, and rewrite the received structure member diSize := MIN(SIZEOF(_Data), diSize); // Can chop down the received string to our length... SET_Value := TRUE; // Maybe want to play a little bit more here, to narrow down or convert datatypes, etc... // Or just reject any other datatype ELSE SET_Value := FALSE; RETURN; END_CASE // Fail, if the received value is still larger than our container... IF diSize > SIZEOF(_Data) THEN SET_Value := FALSE; END_IF // Here we should be ok, just set up the _DataType structure, and copy store the data IF SET_Value THEN THIS^._Descr.TypeClass := anyValue.TypeClass; // The typeclass is already filtered THIS^._Descr.diSize := diSize; // Set the (adjusted) size THIS^._Descr.pValue := ADR(_Data); // This will not change, just to be sure {IF defined (pou:SysMem.SysMemCpy)} SysMem.SysMemCpy(_DataType.pValue, anyValue.pValue, TO_UDINT(anyValue.diSize)); {ELSE} // An ugly replacement MemCpy FOR I:=0 TO diSize - 1 DO _Descr.pValue[I] := anyValue.pValue[i]; END_FOR {END_IF} // Otherwise, in case of failure maybe better set an empty value (overwrite the former data descriptor) ELSE THIS^._Descr.TypeClass := TYPE_CLASS.TYPE_NONE; THIS^._Descr.pValue := ADR(_Data); THIS^._Descr.diSize := 0; END_IF METHOD GET_Value : BOOL VAR_INPUT anyValue : ANY; END_VAR VAR I : DINT; END_VAR // We just have to serve the data, using the __System.AnyType structure received // Roughly we can say: IF anyValue.TypeClass = _Descr.TypeClass AND anyValue.pValue <> 0 // This should not be possible, already taken care of by Codesys (?) THEN {IF defined (pou:SysMem.SysMemCpy)} SysMem.SysMemCpy(anyValue.pValue, _DataType.pValue, TO_UDINT(MIN(anyValue.diSize, _Descr.diSize))); {ELSE} // An ugly replacement MemCpy FOR I:=0 TO MIN(anyValue.diSize -1, _Descr.diSize - 1) DO anyValue.pValue[I] := _Descr.pValue[I]; END_FOR {END_IF} // Just to make sure, that our string is terminated... IF anyValue.TypeClass = TYPE_CLASS.TYPE_STRING THEN anyValue.pValue[anyValue.diSize -1] := 0; END_IF GET_Value := TRUE; RETURN; END_IF // ... But can play more CASE anyValue.TypeClass OF TYPE_CLASS.TYPE_WSTRING : ; // Could do conversion TYPE_CLASS.TYPE_XSTRING : ; // Wow, I have to figure this out TYPE_CLASS.TYPE_PARAMS : ; // BTW, what is this, how to use? TYPE_CLASS.TYPE_ANYNUM : ; // ... END_CASE Be careful it was not tested. I'm sure can be done better, please feel free to comment 3. If you really want to do entries with variable size In a standard environment, it would be similar to the previous, except you dont have the container variable _Data, just use a pointer, practically _Descr.pValue At Initialize (SET_Value), you have to allocate the memory, would be easy with SysMem.SysMemAlloc - nowadays with SysMem.SysMemAllocData -, and you make sure to release it after use with SysMem.SysMemFreeData... SysMemAlloc was already hidden. The problem with this, that sooner or later your application will totally fragment the dynamic memory, and fail... So should look for some form of dynMaybe MemUtils.MemoryManager (I am not sure what is the status and the future of it). 4. You will end up by a LogEntry Factory ... 5. You could still have a look at this IEC Snippets BTW, Standard Codesys Logger is not a bad choice either. If you are really interested, I share some more code / library.
Last updated: 2025-03-09
Post by mondinmr on Frustration-Fueled Feedback on Project File Management and Git Integration
CODESYS Forge
talk
(Post)
Good day, I’m writing this message out of frustration regarding the current way project files are saved as encrypted XML and single-file format in CODESYS. I find this approach to be quite tedious for several reasons: Limited Access to Structured Text: Not being able to access Structured Text (ST) externally makes it impossible to work with alternative editors like VSCode. Tools like VSCode are incredibly responsive and feature advanced systems such as GitHub Copilot, which would be a real game-changer when working with ST IEC. While CODESYS works well for small code snippets or debugging, when the codebase grows, switching to VSCode to boost productivity becomes essential, and copy-pasting between environments is a cumbersome workaround. Poor Integration with Git: This file format also makes it very difficult to integrate effectively with Git. I have tested the internal demo, but for advanced merges, it is unusable. Without properly formatted plain text, it’s impossible to leverage the vast ecosystem of external tools around Git that allow smooth merges in heterogeneous teams. File Corruption on Network Drives: I often work from multiple locations with shared network drives. When the development environment saves a file and something goes wrong midway (which can occasionally happen when using VPNs and network drives), the entire project becomes irrecoverable. There’s no way to cancel the save process, and the development environment freezes. This has happened to me at least four times over the past two weeks, and one of those incidents cost me an entire day of work. All of this is particularly disappointing because I truly believe that the libraries, runtime, and overall work done by CODESYS are exceptional. I find it fantastic that there is a platform allowing development of PLCs and control systems using OOP, which is a huge advantage in modern control engineering. I apologize for the rant, but this issue has been extremely frustrating. Best regards.
Last updated: 2024-10-15
Post by r-niedermayer on OPC UA subscriber not operational
CODESYS Forge
talk
(Post)
Hi. As far as projects in "old version"s are concerned, these can be upgraded to newer versions at any time. To do this, the device must be updated accordingly and the copilers and library versions must be adapted. You can find instructions on how to proceed in the online help/FAQ: https://content.helpme-codesys.com/en/CODESYS%20Development%20System/_cds_changing_compiler_version.html https://content.helpme-codesys.com/en/CODESYS%20Development%20System/_cds_cmd_update_device.html See also 4.3.22.4 "How to open an Example Project" within the following pdf for more details on the single steps: https://forge.codesys.com/lib/counit/tickets/_discuss/thread/3e991befbc/ca97/attachment/Public%20FAQ-v13-20240610_075228.pdf Regaring your OPCUA connection state always showing just "DISABLED", without knowing both sides of the assembly in detail, one can only approach the problem theoretically. We can give a chekclist on how to proceed: Fist, please recheck the communication settings in the OPC UA connection function block to ensure that the server URL, endpoint URL, and other settings are correct and match the configuration of the OPC UA server. Verify that the OPC UA server is running and accessible. -You can try to connect to the OPC UA server using a separate client, such as UAExpert, to ensure that the issue is not related to the OPC UA server itself. Test the security settings in the OPC UA connection function block to ensure that the correct security policy and certificate are selected. If you are using a dynamic connection to the OPC UA server, probe that the connection settings are correctly configured and that the OPC UA client is able to establish a connection to the OPC UA server. Also, please loock into the log files for any errors related to the OPC UA connection function block, these should be listet there. The log files may also provide additional information about the issue and help you to further troubleshoot the problem. FYI - Please see https://content.helpme-codesys.com/en/CODESYS%20Communication/_cds_obj_data_source_communication_opc_ua_server.html: Her you can finde the Communication settings via OPC UA Server -> layout Browse Live Server: The client connects to the server and detects the existing variables and types. From Information Model The client reads the data structure (layout) of the OPC UA Server from the information model set here and as a result receives the information about available variables and types. A connection to the server is not required. The list contains the information models installed in the OPC UA Information Model Repository. "Read Connection" Settings from IEC Variable (option set): - The connection settings used by the device are not read here from the dialog, but at runtime from the IEC variable specified here. - For this possibility, please see the Using a Dynamic Connection to an OPC UA Server (https://content.helpme-codesys.com/en/CODESYS%20Communication/_comm_use_dynamic_opc_ua_server_comm_settings.html) The settings for the communication of a Client-data source to an OPC UA Server can also be dynamically configured from the IEC code and can also be changed at runtime. For such a purpose, a structure is available in the DatasourceOpcUAServer library (For a description of the OPC UA Server, there is one included in the standard installation of CODESYS, https://content.helpme-codesys.com/en/CODESYS%20Communication/_cds_encrypt_communication_data_sources_opc_ua_client.html)
Last updated: 2024-11-04
Post by mubeta on Strange problem with the ‘MC_SetPosition’ function
CODESYS Forge
talk
(Post)
How are the servo drives controlled? EtherCAT, step/dir pulses, other? CANOpen, 1 Mb/s, bus load 35%, cycle time 2ms. Another thought is that - if it's step/dir pulse based control - the pulses from the PLC to the drive are getting missed/lost at high frequencies? If that's the case then there would be multiple troubleshooting steps/corrections that could be investigated. Here, it seems to me that we are getting completely off track with the observed problem. You could try to create a simplified program I had already written this elsewhere. The program before being brought into machines was exhaustively tested in SW emulation and the problem did not occur. However, in emulation I was interested in checking other aspects of the process, not this specific one which is for real a correction made necessary after the fact. The part of the program that does this correction with the function mentioned in the topic, came up from its origins, but I didn't know or didn't think it was really useful. A scruple that later turned out to be necessary. However, for now I do not think I will spend any more time on this verification, already lacking any to do my normal. I remain amazed, however, that a function intended to correct the axis position with the motor in motion and that it should not interfere with this, in fact instead changes behavior as the motor speed changes. Mah! When you manually control the motor directly from the servo drive software at the speeds you are calling for, does it move precisely to the target position? The drive and motor have been working fine for about 10 years. In replacing the machine control system, I opted for CoDeSys where before there was something else. But this is not the subject of the problem. What I need to resolve is the fact that a clutch specially placed at a certain point can slip and, therefore, I have the undeniable need to phase the 'prime mover' to the mechanical position of the machine, detected by a cam for each turn, in order to properly stop at its optimum point. Which for now I have ruled out doing. In fact, if I really have to say, since we have now gone brutally OT, I originally thought that this clutch should only come into action in cases of extreme necessity, as happens in most trials. But this one, the way it is made, slips more easily than I could estimate and the servo-controlled 'prime mover,' and the machine, get out of phase, maybe by a little, but frequently, and when the machine work at it's high speed, (in fact all of the time), I can't adjust properly the 'prime mover' position at fly.
Last updated: 2025-01-18
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.