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 gatto on Read codesys version in the codesys application
CODESYS Forge
talk
(Post)
hi, i used another way declaration: pApp : POINTER TO APPLICATION; pAppInfo : POINTER TO APPLICATION_INFO; ProjectName : STRING (24) ; CodesysVersion : STRING (15) ; code: //library : // CmpApp // IoDrvEthernet // // Get Pointer to current application pApp := CmpApp.AppGetCurrent( pResult:= 0 ); // Get Pointer to Application information pAppInfo := CmpApp.AppGetApplicationInfo(pApp:= pApp, pResult:= 0 ); ProjectName := pAppInfo^.pstProjectName^ ; //convert codesys version to string CodesysVersion := IoDrvEthernet.UDINT_TO_IPSTRING ( udiIPAddress := pApp^.udiPSVersion ) ; so i think you need to convert your dwVersion in a UDINT and after convert UDINT_TO_IPSTRING
Last updated: 2025-01-17
Post by dnordenberg on BOOL variable in OPC UA and modbus simultaneously
CODESYS Forge
talk
(Post)
How can I have an BOOL variable that is read/write in both modbus TCP server and from OPC UA at the same time? Variables with %MX.n %QX.n addressing which is used for BOOL/coils in modbus server is not allowed in OPC UA symbol list on Schneider M251 controllers. I have already asked on Schneiders forum but there are not a lot of codesys experts over there :( So OPC symbols can't have a address and the modbus TCP server needs a address. So how should I do it then? It seems like an impossible combination. Since I want read/write access from both ways I can't just simply make a second variable and assign it the value of another since it would be a one way assignment. I also tried using VAR_CONFIG which then makes the address syntax %Q or %M in my main variable list and that fools OPC UA Symbol Configuration to allow it and then I add the complete %MX.n address of it in the VAR_CONFIG list. This semi works, I can toggle the BOOL from modbus but the OPC UA symbol seems to be read only. It displays symbol status but nothing happens when I toogle it. I think I need another way to have the variables and symbols pointing to the same bits in memory... My plan B is to write a BOOL array compare FB that saves a history bit from previous cycle and if that does not match current status at next cycle for either the OPC symbol or the modbus variable then it copies the new status over to the other. Maybe ugly but it's like my last alternative. Kind regards David
Last updated: 2025-07-14
Post by szotyi on Array of Program
CODESYS Forge
talk
(Post)
Hi! What is the proper and the easiest way to call programs through looping of array of programs, or pointer of program? instead of calling the programs one by one: prog1(inputX: 11); prog2(inputY: 12); prog3(inputZ: 13); similar like: VAR programsToCall : ARRAY [1..3] OF PROGRAM; END_VAR programsToCall[1] := prog1(inputX: 11); programsToCall[2] := prog2(inputY: 12); programsToCall[3] := prog3(inputZ: 13); FOR i := 1 TO 3 DO programsToCall[i] (); END_FOR Thanks.
Last updated: 2024-08-28
Post by apurv on Cannot pass array of constant size to a function as a reference
CODESYS Forge
talk
(Post)
I have a Array of constant size defined like this Var Constant MAX_SIZE :UINT := 10; End_var VAR array : ARRAY[0..MAX_SIZE] OF INT; END_VAR Now I want to pass this array to a function by reference, Function fun : INT VAR_IN_OUT CONSTANT MAX_SIZE : UINT; END_VAR VAR_INPUT array : REFERENCE TO ARRAY[0..MAX_SIZE] OF INT; END_VAR but when I run this it gives strange Errors Error : Cannot Convert type 'ARRAY [0..MAX_SIZE] OF INT' to type 'ARRAY[0..MAX_SIZE] OF INT'
Last updated: 2024-01-07
Post by pietrobalint on Retain / Persistent Variables in Codesys for Raspberry Pi
CODESYS Forge
talk
(Post)
Ok, I figured out that I do not call the program in the main task. Thank you for the source code, it works!
Last updated: 2024-08-17
Post by pietrobalint on Retain / Persistent Variables in Codesys for Raspberry Pi
CODESYS Forge
talk
(Post)
Hi, I am very new in Codesys so let me apologize for my dumb question. Could you explain how to impement this code mentioned before? Thank you very much!
Last updated: 2024-08-17
Post by pietrobalint on Persistent variables are not read after initialization
CODESYS Forge
talk
(Post)
Hi, I have Raspberry Pi 5 and I would like to use persistence manager too. But Codesys support said that Application Composer not compatibile with my runtime. Could you recommend a solution?
Last updated: 2024-09-01
Post by chrisdeloglos on Network Variables not updating
CODESYS Forge
talk
(Post)
Thanks for the comment. I'm using Weidmueller UC20-WL2000-AC's and changing the broadcast address to match the current subnet this worked for me as well!
Last updated: 2025-01-27
Post by ojz0r on Multiple applications on one device sharing variables.
CODESYS Forge
talk
(Post)
One thing you could do is create an object with the variable as field with a function and procedure to get the variable (read) and set the variable (write). These are then called from your program and the vizualization.
Last updated: 2025-02-20
Post by bingo on PLC Shell commands via ST Code
CODESYS Forge
talk
(Post)
For a permanent change, you may need to update the PLC configuration file or set the IP at startup using retained variables.
Last updated: 2025-03-02
Post by tvm on Passing properties as VAR_IN_OUT variables.
CODESYS Forge
talk
(Post)
Use a VAR_INPUT for properties. The reason for the error is that you can't get a reference to a property. Using a VAR_INPUT will copy the property to an input variable.
Last updated: 2025-03-06
Post by stribor on Passing properties as VAR_IN_OUT variables.
CODESYS Forge
talk
(Post)
if i only use it as input variable I won't be able to update its state within the visu object. Lets say i have real value as a property, i would like the slider object to display this value and also modify it.
Last updated: 2025-04-30
Post by fleaplc on Symbol Configuration to be Build every time!
CODESYS Forge
talk
(Post)
I'm using Symbol configuration to share PLC variables with SCADA via 3S protocol (Symbol File). All is working fine except every time I open the project.. then I need to rebuild Symbol Configuration! Why?
Last updated: 2025-05-23
Post by davidbo on AC_Datalog DataLogChannel Save Cyclic is not working
CODESYS Forge
talk
(Post)
"Save Cyclic" is set to 30s, but in my log I can see my variables are logged every 500ms which equals the cyclic time for my Task. Why is "Save Cyclic" ignored
Last updated: 2025-07-11
Post by pernockham on Persistence Manager: Config File not found?
CODESYS Forge
talk
(Post)
Ok, think I understand. The reason for the error is I try to include complex variables (FB) in the persistenced data. I will try to use {attribute 'ac_persist_exclude'} to exclude those elements.
Last updated: 2025-08-22
Post by open on How to create a stopwatch?
CODESYS Forge
talk
(Post)
Thanks everyone for your input, I am using persistent variables to retain the timer value after machine shutdown, and main task to be as low as possible for the seconds TON to be accurate.
Last updated: 2023-12-14
Post by matt-s on HMI Pushbutton/Move Instruction
CODESYS Forge
talk
(Post)
I know, that is not the issue though. The issue is the HMI_Blower_Auto_PB variable not changing to false. I do not have the IO modules plugged in yet, that is why there are NaN values for those variables. That should not affect this.
Last updated: 2024-01-25
Post by macros8 on Visualization using methods and cyclic ST-calls
CODESYS Forge
talk
(Post)
Have you found the way how to call any function in case the visu is opened? Like on event when the screen is opened to initialize some variables etc.? I canΒ΄t... :/
Last updated: 2024-03-01
Post by eschwellinger on EtherCAT drive not moving
CODESYS Forge
talk
(Post)
you need to switch to a realtime capable plc. Do not map variables, this will be done by the SoftMotion. And check the Ds402 parameters in the generic parameterview on the Softmotion Connector.
Last updated: 2024-03-05
Post by sumit on Not able to see input data coming from eip adapter on codesys
CODESYS Forge
talk
(Post)
Yes, green icon is there, this time I tried by enabling the device to always update variables but results are the same. I have attached the screenshot and eds file I am using.
Last updated: 2024-03-06
Post by trycyclepower on Only single ehternet ip drive is communicating
CODESYS Forge
talk
(Post)
Hi all, I have two ethernet IP drives not communicating together. If I disable one, then other one starts working. ENIPScnannerIOTak cycle is setup as 20ms. Also, PLC updating variables setting is on.
Last updated: 2024-03-08
Post by nano on Functional block
CODESYS Forge
talk
(Post)
u can use internal variables by passing it thru setter/getter. thats the way to go. for that add it by rightclick on fb and create propertie
Last updated: 2024-04-17
Post by gseidel on Warning C0564 when compiling CNC project with variables program
CODESYS Forge
talk
(Post)
Hi Fless, thanks for your report! We created an issue in our bug tracker (SM-5109) and will have a look at this issue. Best regards, Georg
Last updated: 2024-04-30
Post by tvm on Timer On Vijeo
CODESYS Forge
talk
(Post)
Vijeo doesn't support TIME variables, so the easiest thing to do is convert to a STRING in your program, and use that variable. You could use TimeAsString:= TIME_TO_STRING(TimeVar) to get a string that looks like this: T#5h10m45s200ms
Last updated: 2024-05-07
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.