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 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 husarz17 on How change Unity-ID in TCP Modbus Slave
CODESYS Forge
talk
(Post)
My codesys is 3.5.21.30. I am using function ModbusServer from library ModbusTCP_Slave. The reason is that I need share 9000 Holding registers. By standard configuration it is only 4096. fbMbTcpDevice: ModbusTCP_Slave.ModbusServer; fbMbTcpDevice( wPort := 502, pInputData := ADR(awInputReg), pOutputData := ADR(awHoldingReg), uiInputDataSize := 10, uiOutputDataSize := 9000, xEnable := TRUE, tTimeout := 10000, InterfaceName := "eth0", xBusy => xBusy, xError => xError, byClientConnections => byConnections ); Ethernet port is cofigured: Network interface: eth0 IP address: 10.10.22.55 Subnet maskL 255.255.255.0 Default gateway: 0.0.0.0 And it only works when I am reading registers with ID 255 by Modbus Poll. Any other IDs don't work. The actual TCP client device try to read registers with ID 1 and I can't change it... Thanks in advance for your help!
Last updated: 2026-04-01
Post by egr99 on Modbus TCP Server connection is ESTABLISHED but all holding registers are value 0?
CODESYS Forge
talk
(Post)
You're absolutely right. Sorry for that. In the meantime I wrote a Function block to handle the reads and writes to the different attached RTU-devices. It processes the parameter like (str_Modbus:=(usiSlave:=1, uiFC:=5, uiLEN:=1, uiOFFSET:=0, uiInterval:=500)) and the corresponding output, waits for the response and processes next request in a 5-state procedure. It's working for 2 gateways (stable without errors, although error recovery is included). But nevertheless it should be possible with the Channel definitions of Codesys. Much easier to maintain :)
Last updated: 2026-04-08
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 ihatemaryfisher on Sorting array of any-sized structure
CODESYS Forge
talk
(Post)
In my machine's operation, I need to display multiples tables containing arrays of structured variables. The arrays change during operation, and my supervisor has advised me to write a new bubble-sort for each array. I think I can make a function to sort an array of any data type. This was my own project, and I'm a relatively new coder. I want to know the weaknesses in my approach, and a better method, if one exists. As far as I can test, the function accepts an array of a structured variable of any size, and sort it by any VAR in that structure. But it relies heavily on pointers, which I've heard are bad practice? Function call: // SORT BY BYTE-SIZED VAR IF xDoIt[6] THEN FUNBubbleSortSansBuffer( IN_pbySourcePointer := ADR(astArray[1]), // address of first byte in first element of array IN_pbyComparePointer:= ADR(astArray[1].byCompByte), // points to first byte of the comparing variable (variable you sort by) IN_uiStructureSize := SIZEOF(TYPE_STRUCTURE), // size, in bytes, of the structured variable IN_uiCompareSize := SIZEOF(astArray[1].byCompByte), // size, in bytes, of the comparing variable (variable you sort by) diArrayElements := UPPER_BOUND(astArray,1), // number of elements in array IN_xSmallToLarge := xSortOrder // whether to sort by small2large or large2small ); END_IF Function: FUNCTION FUNBubbleSortSansBuffer : BOOL VAR_INPUT IN_pbySourcePointer : POINTER TO BYTE; // points to beginning of array (first byte of first element) IN_pbyComparePointer: POINTER TO BYTE; // points to first byte of the comparing variable (variable you sort by) IN_uiStructureSize : UINT; // size, in bytes, of the structured variable IN_uiCompareSize : UINT; // size, in bytes, of the comparing variable (variable you sort by) diArrayElements : DINT; // number of elements in array IN_xSmallToLarge : BOOL; // whether to sort by small2large or large2small END_VAR VAR j : DINT; // repeat iteration over array until array ends i : DINT; // iterarte over array, swapping when necesary k : DINT; // iterator from 1 to size of structure (stepping 'through' a single element in array) dwSize : DWORD; // internal var for use in MEMUtils.MemCpy(<size>) // FOR SORTING BY BYTE VAR pbySourcePointer : POINTER TO BYTE; pbySourcePointer2 : POINTER TO BYTE; pbyComparePointer : POINTER TO BYTE; pbyComparePointer2 : POINTER TO BYTE; pbyPointerToBuffer : POINTER TO BYTE; // pointer to single byte buffer byBufferByte : BYTE; // single byte buffer END_VAR dwSize := UINT_TO_DWORD(IN_uiStructureSize); // get structure size (number of bytes) pbyPointerToBuffer := ADR(byBufferByte); // assign pointer to address of buffer byte (because MEMUtils.MemCpy requires a pointer input) CASE IN_uiCompareSize OF // depending on the size of the VAR to sort by (current functionality for BYTE and WORD/INT 1: // BYTE (8 BIT) FOR j := 1 TO diArrayElements DO // for number of elements in array FOR i := 1 TO (diArrayElements-1) DO // same thing, but row[i+1] row is included in swap logic pbySourcePointer := IN_pbySourcePointer + dwSize*(i-1); // point at #1 byte in array element[i] pbySourcePointer2 := pbySourcePointer + dwSize; // point at #1 byte in array element[i+1] // NOTE: because of memory locations, each array element is offset from one another by a number of bytes equal to the size of the structure // We can "walk" from array[i] to array[i+1] via steps equal to the size of the structure // e.g., ADR(array[i+1]) == ADR(array[i]) + SIZEOF([array datatype]) pbyComparePointer := IN_pbyComparePointer + dwSize*(i-1); // point to sorting variable in array element[i] pbyComparePointer2 := pbyComparePointer + dwSize; // point to sorting variable in array element[i+1] // using sort order (small -> large/large -> small) IF SEL(IN_xSmallToLarge, (pbyComparePointer2^ > pbyComparePointer^),(pbyComparePointer2^ < pbyComparePointer^)) THEN // This is where it gets tricky. We've identified pointers for the starting bytes of aArray[i] and aArray[i+1] // and we know the size of aArray[i]. We are going to swap individual bytes, one at a time, from aArray[i] and aArray[i+1] // this allows us to use only a single byte var as a buffer or temporary data storage // e.g., consider a structure consisting of a word, a byte, and a string. it is stored like this // |------WORD-------| |--BYTE-| |STRING------...| // astArray[1] == 1000 0100 0010 0001 1100 0011 1010 1010.... etc // astArray[2] == 0001 0010 0100 1000 0011 1100 0101 0101.... etc // performing a single swap (copy into a buffer, etc.) of the first byte of each array element creates this // astArray[1] == 0001 0100 0010 0001 1100 0011 1010 1010.... etc // astArray[2] == 1000 0010 0100 1000 0011 1100 0101 0101.... etc // incrementing the pointer adresses for the swap by 1 and swapping again swaps the next byte in each array element // astArray[1] == 0001 0010 0010 0001 1100 0011 1010 1010.... etc // astArray[2] == 1000 0100 0100 1000 0011 1100 0101 0101.... etc // continuing this from k to SIZEOF(TYPE_STRUCTURE) results in a toally swapped row FOR k := 1 TO IN_uiStructureSize DO // copy single byte[k] of array element 1 to buffer MEMUtils.MemCpy(pbyDest := (pbyPointerToBuffer), pbySrc := (pbySourcePointer+k-1), dwSize := 1); // copy single byte[k] of array element 2 to 1 MEMUtils.MemCpy(pbyDest := pbySourcePointer+k-1, pbySrc := (pbySourcePointer2+k-1), dwSize := 1); // copy buffer to byte[k] array element 2 MEMUtils.MemCpy(pbyDest := (pbySourcePointer2+k-1), pbySrc := pbyPointerToBuffer, dwSize := 1); END_FOR END_IF END_FOR END_FOR
Last updated: 2023-08-17
Post by jst69 on Python script: Launch Codesys, Execute Script, Exit Codesys
CODESYS Forge
talk
(Post)
Dear all: Question about scripting: I am creating a .NET program that is supposed to Open codesys, open template project, export a bunch of pou, then exit codesys. Launch works, Open project works, Export works, But how do i tell codesys to close itself? I can tell windows to terminate codesys, but i would prefer to do it properly. from __future__ import print_function import sys import System proj = projects.primary # We're interested in POU nodes: POUGuid = Guid("6f9dac99-8de1-4efc-8465-68ac443b7d08") # We collect all POU nodes in that list. pous = [] # From the parent node on, we recursively add POU nodes: def CollectPous(node): if node.type == POUGuid: pous.append(node) else: for child in node.get_children(): CollectPous(child) # Now we collect all the leaf nodes. for node in proj.get_children(): CollectPous(node) # We print everything just to know what's going on. for i in pous: print("found: ", i.type, i.guid, i.get_name()) # And now we export the files. for candidate in pous: # We create a list of objects to export: # The object itsself objects = [candidate] # And sub-objects (POUs can have actions, properties, ...) objects.extend(candidate.get_children()) # And the parent folders. parent = candidate.parent while ((not parent.is_root) and parent.is_folder): objects.append(parent) parent = parent.parent # Create an unique file name: if len(sys.argv) == 1: filename = "parent\\%s.export" % (candidate.get_name()) else: filename = "%s\\%s.export" % (sys.argv[1],candidate.get_name()) # print some user information print("exporting ", len(objects), " objects to: ", filename) # and actually export the project. proj.export_xml(objects, filename) proj.close() print ("script finished.") System.exit(0) // Dont work .NET: public static void Export(string path,string proj) { if (checkSettings()) { var p = new System.Diagnostics.Process(); p.StartInfo.FileName = Properties.Settings.Default.CSVersion +"\\CODESYS\\Common\\CODESYS.exe"; p.StartInfo.Arguments = " --Profile=" + qoute(Properties.Settings.Default.CSProfile) + " --culture=en" + " --project=" + qoute(path + "\\" + proj) + " --runscript=" + Properties.Settings.Default.LastOpenProjectPath + "\\INPUT_DATA\\SCRIPT\\Export.py" + " --scriptargs:" + qoute(path) ; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = false; p.Start(); p.StandardOutput.ReadToEnd(); p.CloseMainWindow(); p.Close(); } }
Last updated: 2024-01-16
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
Post by george32 on CSV file and string manipulation.
CODESYS Forge
talk
(Post)
Dear folks, I think I have a rather simple question but I could not find the right answer to my question: I have made with Excel a CSV file where I would like to have some general data regarding my program variables. I have made an program what let me read the file. The string I am currently get is at follows: 'IP_Adres;192.168.45.12$R$NPort_number;2000$R$NCycle_time;43$R$NStart_Standard_IO;20$R$N' Now I want to split the string in multiple part, which I later would connect to the right variable. By Google and experimenting I have reached to the following code for the first part of the splitting proces: // Splitting the BOM of the string: Received_string := FileReadString; IF LEFT(STR:=New_string,3)= '' THEN Received_string_without_BOM :=RIGHT(STR:= Received_string,SIZE:= (LEN(STR:= Received_string))-3); END_IF //Splitting the remaining string in part for later declaration. WHILE index = 0 DO index_split_part := FIND(STR1:= Received_string_without_BOM,STR2:= '$R$N'); Part_of_String[index]:=LEFT(STR:=Received_string_without_BOM, SIZE:= index_split_part); index := index + 1; END_WHILE However in the splitting proces I could not understand what is really happening. I understand that the Find() function returns the first value the $R$N in the Received_string_without_BOM. This would mean that the index_split_part := 23 I|P| _ |A |d|r|e|s|;|1_|9 |2 |. |1 |6 |8 |. |4 |5 |. |1 |2 |$ |R |$ |N |P | 1|2| 3 |4 |5|6|7|0|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27| So the next part is to read the first 23 characters of the Received_string_without_BOM with the LEFT() function. I expected that the outcome the following was: 'IP_Adres;192.168.45.12$'. However the outcome is: 'IP_Adres;192.168.45.12$R'. I do not understand where the R after the $ sign comes from, because its place is 24 so it would not be added to the part_of the_string[index]. If I hard coded value 24 for the size it gives me the following return: 'IP_Adres;192.168.45.12$R$N'. I would expect everything till the R but the code adds the $N also to the string. I hope someone could explain to my what I am seeing wrong in my point of view? With kind regards, George
Last updated: 2024-09-27
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.