Post by westcountryewe on ac_persistence not working when creating a Boot Application but works with a Direct Download to the PLC
CODESYS Forge
talk
(Post)
I am using V3.5 SP18 Patch 5. I have noticed that when I Create a Boot Application from CODESYS, and upload this to my PLC via a USB stick the AC_Persistence does not work and none of my values that are in my PersistenceChannel are retained. However, if I connect direct to my PLC and I perform a direct download of my CODESYS program, my values that are in my PersistenceChannel are retained and work as they should. This makes me wonder if there are files that are missing when a Boot Application is created. I have tried taking a backup of my configuration files after performing a direct download, which gives me the plclog.zip folder, and appears to have the ac_persistence folder present within the file structure, however when I replace the plclogic.zip with the same folder that was created when I created a Boot Application, it still does not work but I wonder whether this is because the ac_persistence folder isn't stored in the correct location for reading. The .app and .crc files are embedded within the plclogic.zip folder, which obviously when uploading need to be standalone files in the root directory of the USB, so the intention there is clearly to extract the .app and .crc files and put them into the correct location within the USB. I wonder if it could be the same for the ac_persistence folder? I have tried moving it to different locations but none have worked. Has anybody else discovered a fix for this? I know the short-term solution is to do a direct download to the PLC but there are some logistical reasons why this isn't neccesarily the best solution for us.
Last updated: 2024-02-27
Post by testlogic on Sending Sequential Modbus TCP Packets
CODESYS Forge
talk
(Post)
I have a Modbus TCP slave device where I need to do sequential writes to the same register. The register I'm writing to is kind of like a command line, each packet is a command word encoded in Hexadecimal. I am having difficulty implementing this system in CoDeSys 3.5 SP19. I feel like the structure of the program should be something along the lines of (Pseudocode): ModbusTCPSend(Command Register, Command1) ModbusTCPSend(Command Register, Command2) ModbusTCPSend(Command Register, Command3) I have tried to implement this with a rising edge trigger wMot1OPCode := 16#E1; //Stop Motor & Kill Program xMot1SendOP := TRUE; //Send OP on rising edge xMot1SendOP := FALSE; //Reset wMot1OPCode := 16#9E; //Disable Motor xMot1SendOP :=TRUE; //Send OP on rising edge xMot1SendOP := FALSE; //Reset Where "wMot1OPCode" is the IO map for writing to the command register, and "xMot1SendOP" is the rising edge trigger for that modbus channel. However, this doesn't work. The device never responds to the modbus commands. It seems like the trigger variable is switched too quickly for modbus to send the packet. I know the modbus register is working, because I can set the channel to cyclic and the device will respond. However, I can't use this reliably because I need each command to be sent once, in order. Cyclic keeps re-sending the commands and seems like it could miss a command as well if one was sent in-between cycle time. I have also trying using the Application trigger as described by https://faq.codesys.com/pages/viewpage.action?pageId=24510480, but this is also not working for me. See attached picture for my FBD code. This seems like a simple function, I can't tell what I'm doing wrong here. Thanks for the help.
Last updated: 2024-03-06
Post by thysonfury on OPTO22 Groov Epic PR2 Modbus Comms Dropping out every 2 hours and 4 Mins
CODESYS Forge
talk
(Post)
Hi after some assistance with an error on a Groov PR2 PLC. We have a few different communications set up as shown below: One Modbus TCP Slave Connection - ( Sending / Receiving Data from a PC ) Two Modbus TCP Master Connection - ( Reading Data from a UPS Panel and Reading Data Gas Chromatograph) One Modbus RTU Slave Connection 485 - (Reading Data from a fire and gas panel) One Modbus RTU Master Connection 485 - (Sending Data to a Telemetry Unit) All Licenses have been installed as per OPTO22 suggestions of the order below: Modbus TCP Master Modbus TCP Slave Modbus RTU Master Modbus RTU Slave When I check on License manager the RTU Master license seems to disappear on installing the RTU. (What ever reason I’ve been told this is “normal”). If I use Device License Read It will successfully read all the licenses correctly. Now the issue is every 2 hours and between 4. For what ever reason the communications seems to end and lock up for about 20 seconds. During this time even if I was logged into the PLC it would kick me off and I’d have to re type the password to enter. Most of the devices can handle this however the RTU flags up a communications failure at the SCADA and is raising alarms every 2 hours and 4 mins. We’ve had multiple people go through the code to check for anything obvious. Does anyone have any ideas?
Last updated: 2024-04-15
Post by thysonfury on OPTO22 Groov Epic PR2 Modbus Comms Dropping out every 2 hours and 4 Mins
CODESYS Forge
talk
(Post)
Hi after some assistance with an error on a Groov PR2 PLC. We have a few different communications set up as shown below: One Modbus TCP Slave Connection - ( Sending / Receiving Data from a PC ) Two Modbus TCP Master Connection - ( Reading Data from a UPS Panel and Reading Data Gas Chromatograph) One Modbus RTU Slave Connection 485 - (Reading Data from a fire and gas panel) One Modbus RTU Master Connection 485 - (Sending Data to a Telemetry Unit) All Licenses have been installed as per OPTO22 suggestions of the order below: Modbus TCP Master Modbus TCP Slave Modbus RTU Master Modbus RTU Slave When I check on License manager the RTU Master license seems to disappear on installing the RTU. (What ever reason I’ve been told this is “normal”). If I use Device License Read It will successfully read all the licenses correctly. Now the issue is every 2 hours and between 4. For what ever reason the communications seems to end and lock up for about 20 seconds. During this time even if I was logged into the PLC it would kick me off and I’d have to re type the password to enter. Most of the devices can handle this however the RTU flags up a communications failure at the SCADA and is raising alarms every 2 hours and 4 mins. We’ve had multiple people go through the code to check for anything obvious. Does anyone have any ideas?
Last updated: 2024-04-15
Post by thysonfury on OPTO22 Groov Epic PR2 Modbus Comms Dropping out every 2 hours and 4 Mins
CODESYS Forge
talk
(Post)
Hi after some assistance with an error on a Groov PR2 PLC. We have a few different communications set up as shown below: One Modbus TCP Slave Connection - ( Sending / Receiving Data from a PC ) Two Modbus TCP Master Connection - ( Reading Data from a UPS Panel and Reading Data Gas Chromatograph) One Modbus RTU Slave Connection 485 - (Reading Data from a fire and gas panel) One Modbus RTU Master Connection 485 - (Sending Data to a Telemetry Unit) All Licenses have been installed as per OPTO22 suggestions of the order below: Modbus TCP Master Modbus TCP Slave Modbus RTU Master Modbus RTU Slave When I check on License manager the RTU Master license seems to disappear on installing the RTU. (What ever reason I’ve been told this is “normal”). If I use Device License Read It will successfully read all the licenses correctly. Now the issue is every 2 hours and between 4. For what ever reason the communications seems to end and lock up for about 20 seconds. During this time even if I was logged into the PLC it would kick me off and I’d have to re type the password to enter. Most of the devices can handle this however the RTU flags up a communications failure at the SCADA and is raising alarms every 2 hours and 4 mins. We’ve had multiple people go through the code to check for anything obvious. Does anyone have any ideas?
Last updated: 2024-04-15
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 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 paulg on RasPi CAA Serial example - unexpected behavior during debug
CODESYS Forge
talk
(Post)
I've trimmed down the CAA Serial Codesys example to only listen on one port but, when stepping through the Case structure in debug mode, it jumps out of the structure during a specific point in every scan (I'll point it out below after describing the setup and listing the code). I'm using a Pi 4 Model B, and I have an Arduino Nano Every plugged in via USB which is streaming the following serial message at 1 Hz: Time since opening connection: 1 s Time since opening connection: 2 s ...and so on. The Pi shows the Nano at /dev/ttyACM0 so I edited CODESYSControl_User.cfg to read: Linux.Devicefile=/dev/ttyACM The code in my PLC_PRG is (ignore some of the comments, I hadn't deleted them out from the original example): PROGRAM PLC_PRG VAR xStartTest : BOOL:= TRUE; iState : INT; xTestDone : BOOL;(* True, when the test was done succesfully *) (* Settings to communicate with the COM Port *) aCom1Params : ARRAY [1..7] OF COM.PARAMETER; como1 : COM.Open; comc1 : COM.Close; comw1 : COM.Write; comr1 : COM.Read; //sWrite : STRING := 'Test String!'; sRead : STRING(25); szRead : CAA.SIZE; xCom1OpenError : BOOL; xCom1CloseError : BOOL; xCom1WriteError : BOOL; xCom1ReadError : BOOL; END_VAR //This example shows the communication of two COM Ports with each other. //The first one writes a string of characters, which is read by the second one. //After successful execution, the two COM Ports are closed and the test is done. IF xStartTest THEN CASE iState OF 0: //The parameters are set for the COM Port aCom1Params[1].udiParameterId := COM.CAA_Parameter_Constants.udiPort; aCom1Params[1].udiValue := 1; // the correct Port should be adapted aCom1Params[2].udiParameterId := COM.CAA_Parameter_Constants.udiBaudrate; aCom1Params[2].udiValue := 115200; aCom1Params[3].udiParameterId := COM.CAA_Parameter_Constants.udiParity; aCom1Params[3].udiValue := INT_TO_UDINT(COM.PARITY.NONE); aCom1Params[4].udiParameterId := COM.CAA_Parameter_Constants.udiStopBits; aCom1Params[4].udiValue := INT_TO_UDINT(COM.STOPBIT.ONESTOPBIT); aCom1Params[5].udiParameterId := COM.CAA_Parameter_Constants.udiTimeout; aCom1Params[5].udiValue := 0; aCom1Params[6].udiParameterId := COM.CAA_Parameter_Constants.udiByteSize; aCom1Params[6].udiValue := 8; aCom1Params[7].udiParameterId := COM.CAA_Parameter_Constants.udiBinary; aCom1Params[7].udiValue := 0; //The first Port is opened with the given parameters como1(xExecute := TRUE, usiListLength:=SIZEOF(aCom1Params)/SIZEOF(COM.PARAMETER),pParameterList:= ADR(aCom1Params)); IF como1.xError THEN xCom1OpenError := TRUE; iState := 1000; END_IF //After a successful opening, the next state is reached IF como1.xDone THEN iState := 15; END_IF 15: // the reading process is started comr1(xExecute := TRUE,hCom:= como1.hCom, pBuffer:= ADR(sRead), szBuffer:= SIZEOF(sRead)); IF comr1.xError THEN xCom1ReadError := TRUE; END_IF //After completion the size of the written bytes are saved IF comr1.xDone OR comr1.xError THEN szRead := comr1.szSize; iState := 20; END_IF 20: // If everything was successful the ports are closed and the handles are released comc1(xExecute := TRUE,hCom:= como1.hCom); IF comc1.xError THEN xCom1CloseError := TRUE; END_IF IF comc1.xDone OR comc1.xError THEN iState := 25; END_IF 25: // The first port is closed and the used handle released xTestDone := TRUE; xStartTest := FALSE; iState := 0; como1(xExecute := FALSE); comw1(xExecute := FALSE); comc1(xExecute := FALSE); ELSE iState := 0; END_CASE END_IF I realize as I write this that the .udiPort should be 0 and not 1, but that shouldn't be causing the issue I'm seeing. I'm forcing xStartTest:=TRUE every scan so that I can step into each line and observe what's happening. What I see is that the port parameters are set and the port is opened with no errors, but the code jumps out of the case structure to the last line every time it reaches (and I step into) the iState:=15 line (at the end of the iState:=0 block). So every scan cycle it goes through the block for iState=0 and jumps out at the same spot. I'm a little new to PLC programming so I may be misunderstanding the flow, but shouldn't this case structure keep moving down in the same scan? If it only handles one case per scan, why doesn't the value of iState persist? Thanks! Update: I restarted the Codesys control today and I was then able to see an error for como1.eError of "WRONG_PARAMETER". I tried doing some digging and another post made me think I should add another line to CODESYSControl_User.cfg, so I now have: [SysCom] Linux.Devicefile=/dev/ttyACM portnum := COM.SysCom.SYS_COMPORT1 So now when I set .udiPort to 1, I get "NO_ERROR" but I also don't read anything from the port (i.e. szRead = 0 always). If I try setting the port to 0 (which I'm confused about, because I added a COMPORT1 line but the device shows on the Pi as ACM0), I get the "WRONG_PARAMETER" error again. Is there an easier way to troubleshoot the Pi and view what ports the Codesys runtime is actually able to see while the Pi is running?
Last updated: 2024-06-06
Post by dwpessoa on CNC Jumps G20 - SMC_NCInterpreter and long time to process
CODESYS Forge
talk
(Post)
I am studying and developing a Softmotion+CNC system for a machine that executes multiple pieces. The G code program is written by the machine operator and each cycle execute 1 piece. The programs are large, exceeding 1000 lines and using up to 8 axes (X, Y, Z, A, B, C, P and Q). The machine needs to run cyclically, executing N pieces (selected by the Operator)... so I tested it using Looping and counters (G36 G37 and G20) and it worked, but it takes a long time to process, and the more pieces I need, the longer the processing time and this is totally impracticable. I found this solution which was very good, and for a few cycles it works well, but for 99999 pieces of a program with 1000 lines, it doesn't work very well... Another solution I tested is to maintain the interpolator with an automatic restart, that is, I load the program without looping (without G20) and give it another start as soon as it finishes. This partially resolved it, but there is still a delay in processing SMC_NCInterpreter in each restart :(. Another solution I thought of is to manually create the SMC_GEOINFO structure and then reuse it, avoinding the Interpreter, but reading the documentation and checking the structure filled by standard blocks, I noticed that there doesn't seem to be a "JUMP" function in the structure! In other words, the SMC_NCInterpreter actually keeps copying and copying the program section for each jump (G20)... If I repeat a 10-line program 1000 times, I will have a structure with more than 10000 lines... possibly this is the cause of take so long to process. Has anyone ever had a problem like this? I believe the same thing happens with typical applications with manipulator robots using Codesys in continuous cycles, and I would like to know if there is any solution, or even if I am misinterpreting the G20 question in SMC_GEOINFO. Thanks!
Last updated: 2023-09-20
Post by mgabryel on Problems with CAN 2.0 comunication on Wago PLC (Codesys 3.5)
CODESYS Forge
talk
(Post)
Hello, I am trying to program CAN Bus comunication on WAGO PLC (more precisely on WAGO Touch Monitor model TP600). I am using for this purpose library "WagoAppCanLayer2" from Wago company. My IDE for programming this device is CODESYS V3.5 SP19 Patch 2 + (64-bit). My program is written in Structured text using function blocks from previously mentioned library. Here is code of this program: 1) Variables declarations: PROGRAM PLC_PRG VAR oOpenInterface : WagoAppCanLayer2.FbCanL2Open :=( udiBaudrate := 125000 ); xInterfaceIsOpen : BOOL; sInterfaceInfo : STRING; oReceive : WagoAppCanLayer2.FbCanRx29BitFrame :=( xBufferMode := FALSE, wCanId := 16#181 ); xRecv : BOOL; sReceiveInfo : STRING; oSend : WagoAppCanLayer2.FbCanTx29BitFrame :=( dwCanId := 16#100, //was 16#201 xRtrFrame := FALSE ); xSend : BOOL; sSendInfo : STRING; oCanDiag : WagoAppCanLayer2.FbCanErrorInfo; xRst : BOOL; aSendData : ARRAY [1..8] OF BYTE; bSendLen : BYTE; TON_0 : TON; TON_1 : TON; END_VAR 2) Program body: oOpenInterface( xEnable := NOT xInterfaceIsOpen, I_Port := IoConfig_Globals.WAGO_CAN_LAYER2_DEVICE ); sInterfaceInfo := oOpenInterface.oStatus.GetDescription(); xInterfaceIsOpen S= oOpenInterface.xValid AND NOT oOpenInterface.xError; oReceive( xEnable := xInterfaceIsOpen, I_Port := IoConfig_Globals.WAGO_CAN_LAYER2_DEVICE, xRxTrigger := xRecv ); sReceiveInfo := oReceive.oStatus.GetDescription(); IF NOT xRecv THEN IF oReceive.bRxNBytes > 0 THEN oReceive.aRxBuffer[1]; oReceive.aRxBuffer[2]; oReceive.aRxBuffer[3]; oReceive.aRxBuffer[4]; oReceive.aRxBuffer[5]; oReceive.aRxBuffer[6]; oReceive.aRxBuffer[7]; oReceive.aRxBuffer[8]; END_IF xRecv := TRUE; END_IF aSendData[1] := 224; aSendData[2] := 13; aSendData[3] := 14; aSendData[4] := 15; aSendData[5] := 222; aSendData[6] := 13; aSendData[7] := 14; aSendData[8] := 15; bSendLen := 8; TON_0(IN:= NOT TON_1.Q, PT:= T#2S , Q=>xSend, ET=> ); TON_1(IN:= TON_0.Q, PT:= T#2S , Q=>, ET=> ); oSend( xEnable := xInterfaceIsOpen, I_Port := IoConfig_Globals.WAGO_CAN_LAYER2_DEVICE, aTxBuffer := aSendData, bTxNBytes := bSendLen, xTxTrigger := xSend ); sSendInfo := oSend.oStatus.GetDescription(); oCanDiag( xEnable := TRUE, I_Port := IoConfig_Globals.WAGO_CAN_LAYER2_DEVICE, xTriggerResetCounter := xRst, xValid=> , xError=> , oStatus=> , wBusState=> , wBusDiag=> , uiRxOverflowsL2=> , uiTxOverflowsL2=> , uiRxOverflows=> , uiMsgTimeouts=> , uiBusOffs=> , uiBusWarnings=> ); Program first opens comunication on CAN 2 device and then periodically try send one CAN data frame. After starting program CAN 2 interface is properly open. The xSend variable is toggling with period 2s. When program sends data an "Tx overflow" error appears. When I am watching CAN_H line on DSub 9 socket i am not able to see proper CAN frames - see screenshot attached to this message. Could somebody help me determine what is wrong with this program. Best regards
Last updated: 2024-08-02
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
Post by patrik on Wish: CODESYSControl.cfg - again
CODESYS Forge
talk
(Post)
Really good post. I hope that it gets seen by CoDeSys staff. I often find the documentation lacking when it comes to using CoDeSys in more complex ways. If using standard "basic PLC functionality", then it's fine and functions are documented in a sufficient way. Once you go outside of that bubble then I find the documentation not enough. CODESYSControl.cfg is a good example of this. And why isn't more of this integrated in the IDE. like changing port of the webserver. Why is it hidden in this file and not accessible through the IDE. It feels like a layer of complexity purposely left in so you don't change it if you don't know what you are doing. Like the argument is if you have the know-how to find the file you have the know-how to edit it. I find the documentation lacking when it comes to more complex libraries too. Like the element collections library. there is parameters I still don't quite know what they do. I can't find any documentation about them. There is an example project to download from CoDeSys so you can see how you are supposed to set your factories up. I leave some parameters like it is in the example. Should I? I don't know. Does it work. Yes. But I could perhaps create memory leaks if I get something wrong and I don't see that until way later. In the create method of your element factory you have a function called __vfinit and you just have to accept that it works. Why can't I get insight in what it does through documentation? Don't CoDeSys want us to know how these work so we can't use them to accidentally break something? I find the error logging lacking too. I've had the CoDeSys service crash but it doesn't say why. I've seen windows noticing the crash but no error code was sent or error message. Also in my current issue where the application fails to start after power outage. I can see in the log that it fails to load retain in the application as one log entry and application failing to start as another. But why? Why does loading the retain fail? give me more information! Is it just a skill issue with me? I don't know. If it is then I'd still want CoDeSys to step up their game when it comes to documentation. I'm sorry if a lot of frustration comes though in this post. I really like the product and what I can do with it compared to other PLC brands.
Last updated: 2024-11-21
Post by eoahe on Problem Reading Registers via Modbus from non Codesys device
CODESYS Forge
talk
(Post)
Hey Guys :) I have the following Problem using Modbus via Codesys: I'm trying to implement a Modbus Device into my codesys project. The device is a Router from Teltonika (RUT956) and it can communicate via Modbus. Currently I'm trying to implement it into my codesys prject as a slave and I'm using my windows computer as master. As it is not a codesys device (the codesys application is not uploaded to device as it has its own software) I'm having problems requesting and reading registers from the router. I've set up my windows computer as Master and implemented the router as slave. When I go online on my master device it sais that it has established a connection to the slave (router)(So I'm thinking this could work as there is a connection?). The goal is to read the GPS (latitude and longitude) data and on the homepage of teltonika you can find the register address and number of registers (adress 143 for latitude and 145 for longitude; both have a number of two registers). I've found tutorials how to read specific registers via their register address with other modbus programs (like modbus-cli), but as my entire project is established in codesys I was hoping to read these specific registers via codesys so that I can show the GPS data on my dashboard. I've tried establishing slave channels but that hasn't been working. I tried read input register channels of the length 4 but it's not possible to define specific register addresses to read via codesys so that didn't work (I jsut get a slaves device failure) and I've also tried establishing 516 (total number of registers the router sends I think?) read inputregister channels but that has the samle failure... So i guess the problem I'm having is establishing slave channels to read these specific registers. Does anyone know how to tackle this problem and has maybe had the same problem? Or maybe someone knows a workaround? I'm quite new to codesys so maybe I'm also lacking expertise...
Last updated: 2025-03-01
Post by clarenced on ERROR: Calling the program "AlarmStorage_Prg" is not allowed from multiple tasks
CODESYS Forge
talk
(Post)
Using codesys v3.5 SP21 Patch 1. We are using Visualization to display alarms. Other then the automatically created AlarmManagerTask, there is no code written to call AlarmStorage_Prg. Any ideas why we would be seeing this error in the log? The runtime actually shutdown. Not sure if that was caused by this error or not. 2025-08-03T02:45:35.444Z, 0x00001012, 4, 0, 0, * ERROR: Calling the program "AlarmStorage_Prg" is not allowed from multiple tasks. 2025-08-03T03:48:15.294Z, 0x00001012, 4, 0, 0, * ERROR: Calling the program "AlarmStorage_Prg" is not allowed from multiple tasks. 2025-08-03T04:38:11.557Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state * We recommend a reboot of the controller now! * 2025-08-03T04:38:11.576Z, 0x0000010f, 8, 1, 0, #### Exception: SysSemEnter - Semaphore deadlock detected - owner thread died [tid:726740] - system may be in an inconsistent state. 2025-08-03T04:38:11.576Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state * We recommend a reboot of the controller now! 2025-08-03T04:38:11.576Z, 0x00000001, 8, 260, 3, #### Exception: HANDLED EXCPT* <excpt>NonContinuable</excpt> in CH_COMM_CYCLE 2025-08-03T04:40:12.308Z, 0x00000001, 1, 0, 35, CODESYS Control shutdown... 2025-08-03T04:40:13.436Z, 0x00000071, 1, 0, 13, Webserver stopped 2025-08-03T04:40:13.437Z, 0x00000114, 2, 1, 0, !!!! Warning: task_signalhandler_exit [MainTask] lost cycles: 14809 2025-08-03T04:40:13.497Z, 0x00000001, 1, 0, 10, [UNLOADED] IEC|Dynamic: <cmp>IecVarAccess</cmp>, <id>0x00001007</id> <ver>3.5.3.64</ver> 2025-08-03T04:40:13.506Z, 0x00000001, 1, 0, 10, [UNLOADED] IEC|Dynamic: <cmp>AlarmMgr</cmp>, <id>0x00001012</id> <ver>4.7.0.0</ver> 2025-08-03T04:40:13.513Z, 0x00000071, 2, 0, 14, !!!! Warning: Unbalanced calls to WebServerRequestRunning/WebServerReleaseRunning 2025-08-03T04:40:13.513Z, 0x00000001, 1, 0, 10, [UNLOADED] IEC|Dynamic: <cmp>IECVisualization</cmp>, <id>0x0000100c</id> <ver>4.7.0.0</ver> 2025-08-03T04:40:13.611Z, 0x00000124, 1, 0, 0, Provider 'AddressSpaceFragment Provider' (version 0x3051500) unregisterd at the OPC UA server. 2025-08-03T04:40:13.611Z, 0x00000124, 1, 0, 0, Provider 'OPC UA for IEC-61131-3' (version 0x3051500) unregisterd at the OPC UA server. 2025-08-03T04:50:17.708Z, 0x00000001, 1, 0, 36, CODESYS Control shutdown done
Last updated: 2025-08-04
Post by gmau on Station 'xyz': AR aborted by device (alarm.ind): AR consumer DHT expired
CODESYS Forge
talk
(Post)
Hello, I am writing to You with the problem of Profinet communication in my Codesys V2.5 SP21 project working on Codesys Control RTE V3 x64 device. I have implemented multiple Profinet devices in the network, the Profinet itself is configured properly, based on the hardware and software parameters of the industrial PC (Windows 10 IoT). My Profinet network contains such Profinet devices as a robot, IO-Link master with some devices on it, IO modules, safety, vision sensor (the configuration is attached to this topic). Once every few hours, sometimes more often, sometimes not even once a day, the error show up at one, two or a few random modules at the same time, every one is the same: "Station 'xyz': AR aborted by device (alarm.ind): AR consumer DHT expired". The communication is then lost with that module, but it is up instantly. It is not such a problem when it comes to regular IOs, but with safety or rotation table, it causes errors and machine stops. I have tried multiple solution based on any forum suggestions, manuals, etc., but it is still happening. Mabye when I turned on the Watchdog for this communication, it is happening less times, but still, I could not turning up the Watchdog parameters at the expense of cycle time of the process. The same is with Send Clock, Reduction and DHT. I have one of the ethernet port on the PC configured with CmpEt1000Drv driver. The card itself is Intel Ethernet Connection I219-LM. These devices are connected to one EKI-2728-NI-A Profinet switch (it was changed from the standard non Profinet one, but still nothing has changed). As I said ealier, I am attaching all the configurations for each device and the communication itself - if any of You had the same problems or have any ideas what could be the cause, I would be much gratefull for any help. For now I am out of ideas, if You have any additional question, please ask. Sincerely, PF
Last updated: 2025-09-04
Post by kurtk on SysProcess Execute Command unable to run commands with special characters
CODESYS Forge
talk
(Post)
Thank you for this additional information. Could you please provide the references to the official documentation where you found this information ? I got as far as: Then insert this: [SysProcess] BasePriority=Realtime Command=AllowAll devoid of references of where the CodesysContol.cfg file was located or of the need to run codesys as root I incrementally located bits of information with perplexity searches but remained mired at error 25 ERR_NO_ACCESS I am curious whether root access is MANDATORY to run SysProcessExecuteCommand (- and/or any other SysProcess functions) or if a more access-constrained User=quasiroot could suffice without the security concerns ? Apparently codesys runs fine without User=root for almost everything... That raises the question: What IS the default codesys user ? I notice in the prototypes: VAR sCommand : STRING := '/usr/bin/whoami'; sOutput : STRING(255); refCommand : REFERENCE TO STRING; refOutput : REFERENCE TO STRING; resultCmd : UDINT; END_VAR whenever I attempt to build this Codesys v3.5 SP2 whines that "cannot convert type REFERENCE TO STRING to STRING" don't remember the exact message... Apparently this happens whenever a fixed-length string is involved. if I get rid of (255) and just set the string := ' '; that is sufficient to make the compiler happy. Is this a recently enforced constraint ? Why does this compile for you and not for me ? There are references to functions / utilities which are used/needed to massage the string references - but I see no specific details... I also notice you specify: Make sure the lib SysProcessImplementation, SysTypes, and CmpErrors is on the project. I don't comprehend why all of the dependent libraries are not automatically referenced, added ? I don't recall seeing anywhere but here that SysProcessImplementation must be included... It just seems odd that the default is to exclude essential libraries, or require alchemical conjuring to assemble all the ingredients for gnat soup ;-) Thanks a lot... I'm still a codesys newby getting my wheels on - or sometimes just partially on
Last updated: 2025-09-12
Post by rkohser on Scripted Git clone / checkout being blocked by "Project Environment" popup
CODESYS Forge
talk
(Post)
Hi, I am trying to build a CI/CD pipeline around our codesys projects. The only entry point if the git url and branch, as we do not put our project file under source control, so we needed to find a way to git clone from the python scripting engine. This is currently how we do this : system.commands["Git", "Clone"].execute( "ProjectLocation=" + project_dir, "ProjectName=" + project_file_name, "RemoteUrl=" + project_git_remote_url, "GitProjectStoragePath=" + project_git_local_dir, ) system.commands["Git", "Checkout", "Branch"].execute( "PrimaryProjectHandle=0", "BranchName=origin/" + project_git_branch ) This works fine, except that, depending on the environment and the project, the "Project Environment" popup gets displayed to suggest for some updates, and waits for a user interaction, even with the "--noUI" flag injected as parameter. I investigated the VersionUpdateFlags, but the problem is that the git clone is an atomic operation that clones and directly opens the generated project without the possibility to inject any updateFlags argument (only used in the ScripProjects.open() function. I also tried to simulate some keyboard events acknowledge the window from script but I did not find the right location for the SendKeys statement, I think before the git clone call is too early and after is too late. So I am wondering if there would be some other way to do that. Is there some more proper scripting api for the git add on ? Is there a global configuration of the VersionUpdateFlags that would allow the popup to be disabled outside from any project context ? Is there some way to automatically acknowledge this kind of messages in a "--noUI" mode ? What do you suggest ? Thanks for your help, Roland Edit : I managed to solve my problem by following these steps in my pipeline : - create a template of a project and opt file preconfigured not to open the popup - open this project - initialize an empty git repo - add the remote, fetch and checkout the needed branch -> no popup is displayed, hourra Edit2 : The initial question was raised on a CODESYS V3.5 SP18 Patch 2 profile. Since CODESYS 3.5.19.30 a scripting API is available for Codesys Git that allows cloning a project with the support of VersionUpdateFlags https://content.helpme-codesys.com/en/CODESYS%20Git/_git_using_scripting.html
Last updated: 2024-01-19
Post by dandyk on Dynamic Images
CODESYS Forge
talk
(Post)
Hello, I have very similar problem, but it seems that your solution does not work for me. I am using TwinCAT XAE Shell v3.1.4024.55 and TwinCAT Runtime. Sorry for writing here on codesys forge, but since I found the only relevant topic here and since TwinCAT is almost the same with CODESYS in many applications, I chose to write here. I simply need to dynamically update image in visualization based on camera trigger (I am doing a machine vision application). Camera triggers an image, my program processes it (applies thresholding, draws contours etc...) and saves the processed image in the runtime location (the same one you were mentioning). This was done successfully. I need to make it work at runtime, while the program is executing and I need to refresh the image in the visualization each time camera triggers a new image and program processes it. When I create image element in the visualization and define the bitmap ID variable as STRING which contains the image ID defined in the image pool, then it displays the image in the image pool, but does not work at runtime, while the program is executing. I also used the Bitmap Version. I declared it in Global variable list as integer with initial value of 0 and wrote the variable in the bitmap version in the image element in visualization. Each time new image is saved to the runtime location, I wrote a program to increment Bitmap Version by 1. It increments and the image does not update in the visualization, unfortunately. I think that bitmap version is working correctly and deletes the cached image as it is supposed to, but the Image Pool does not update the image ID with the new image... the path to the image is always the same... only the actual image changes with the same file name. Image Pool is not dynamic and cannot refresh the image in the path to the actual one at runtime. How can I refresh the image ID in the image pool at runtime? Bitmap version only deletes cached image and reloads the image from the image ID, but the image ID has the same image, because image pool won't update at runtime. Do you know any solution to this problem?
Last updated: 2024-04-06
Post by elizaduke92 on Temu Gutscheincode [acu639380] 40% Rabatt Deutschland
CODESYS Forge
talk
(Post)
Wenn Sie auf der Suche nach einem großartigen Schnäppchen sind, dann haben wir das Richtige für Sie! Mit dem Temu Gutschein-Code 40% Rabatt können Sie beim Einkaufen im Temu-Shop bares Geld sparen. Der Gutscheincode acu639380 bietet Ihnen die besten Vorteile, insbesondere für Menschen in Deutschland. Nutzen Sie diese Gelegenheit, um Ihre Lieblingsartikel zu einem reduzierten Preis zu erwerben. Um mehr zu erfahren, schauen Sie sich die aktuellen Temu Gutschein-Codes 2024 für bestehende Kunden und den Temu 40% Rabatt Gutschein an. Es gibt zahlreiche Möglichkeiten, von diesen Angeboten zu profitieren! Was ist der Temu Gutscheincode 40% Rabatt? Der Temu Gutschein 40% Rabatt ermöglicht es sowohl neuen als auch bestehenden Kunden, fantastische Vorteile zu genießen. Wenn Sie unseren Gutschein auf der Temu-App oder der Website verwenden, profitieren Sie von einem 40% Rabatt Temu Gutschein. Hier sind einige Vorteile, die Sie mit dem acu639380 Gutscheincode erhalten: 40% Rabatt für neue Nutzer: Genießen Sie einen großzügigen Rabatt auf Ihren ersten Einkauf. 40% Rabatt für bestehende Nutzer: Auch treue Kunden können von diesem Rabatt profitieren. $100 Gutschein-Paket für mehrfachen Gebrauch: Verwenden Sie den Gutschein für mehrere Einkäufe. $100 flacher Rabatt für neue Kunden: Ein zusätzlicher Vorteil für Neulinge auf der Plattform. Zusätzliche $100 Rabatt-Aktion für bestehende Kunden: Belohnung für Loyalität und wiederholte Käufe. Temu Gutscheincode 40% Rabatt für neue Nutzer Neue Nutzer können mit unserem Gutscheincode auf der Temu-App die besten Vorteile genießen. Nutzen Sie den Temu Gutschein 40% Rabatt und den Temu Gutschein-Code 40 Rabatt für bestehende Nutzer, um maximal zu sparen. Hier sind einige Vorteile, die Sie mit dem acu639380 Gutscheincode erhalten: 40% Rabatt für neue Nutzer: Sparen Sie beim ersten Einkauf kräftig. $100 Gutschein-Paket für neue Kunden: Ideal für Ihre ersten Käufe. Bis zu $100 Gutschein-Paket für mehrfachen Gebrauch: Nutzen Sie es mehrmals für zusätzliche Ersparnisse. Kostenloser Versand nach Deutschland: Genießen Sie eine stressfreie Lieferung. Zusätzliche 30% Rabatt auf jeden Einkauf für Erstkäufer: Ein attraktives Angebot für neue Kunden. Wie löse ich den Temu 40% Rabatt Gutschein für neue Kunden ein? Um den Temu 40% Rabatt und den Temu 40 Rabatt Gutschein-Code erfolgreich einzulösen, befolgen Sie diese einfachen Schritte: Besuchen Sie die Temu-Website oder öffnen Sie die App. Wählen Sie Ihre gewünschten Produkte aus und legen Sie sie in den Warenkorb. Gehen Sie zur Kasse und geben Sie den Gutscheincode acu639380 im entsprechenden Feld ein. Klicken Sie auf "Einlösen" und überprüfen Sie den Rabatt. Schließen Sie Ihre Bestellung ab! Temu Gutscheincode 40% Rabatt für bestehende Nutzer Auch bestehende Nutzer können von unserem Gutscheincode auf der Temu-App profitieren. Verwenden Sie den Temu 40 Rabatt Gutschein-Code und den Temu Gutschein-Code für bestehende Kunden, um von tollen Rabatten zu profitieren. Hier sind einige Vorteile, die Sie mit dem acu639380 Gutscheincode erhalten: 40% zusätzlicher Rabatt für bestehende Temu-Nutzer: Profitieren Sie von einem exklusiven Angebot. $100 Gutschein-Paket für mehrere Käufe: Nutzen Sie es für weitere Einkäufe. Kostenloses Geschenk mit Expressversand in ganz Deutschland: Ideal für schnelle Lieferungen. Zusätzliche 30% Rabatt auf den bestehenden Rabatt: Maximieren Sie Ihre Ersparnisse. Kostenloser Versand nach Deutschland: Genießen Sie eine sorgenfreie Bestellung. Wie verwende ich den Temu Gutscheincode 40% Rabatt für bestehende Kunden? Um den Temu Gutschein-Code 40 Rabatt und den Temu Rabatt-Code für bestehende Nutzer zu verwenden, befolgen Sie diese Schritte: Melden Sie sich in Ihrem Temu-Konto an oder erstellen Sie ein neues Konto. Wählen Sie die Produkte aus, die Sie kaufen möchten. Gehen Sie zur Kasse und geben Sie den Gutscheincode acu639380 ein. Bestätigen Sie den Rabatt und schließen Sie Ihre Bestellung ab. Wie finde ich den Temu Gutscheincode 40% Rabatt? Um den Temu Gutschein-Code 40% Rabatt für die erste Bestellung und die neuesten Temu Coupons 40 Rabatt zu finden, können Sie sich einfach für den Temu-Newsletter anmelden. So erhalten Sie geprüfte und getestete Gutscheine direkt in Ihr Postfach. Besuchen Sie auch die sozialen Medien von Temu, um die aktuellsten Gutscheine und Angebote zu entdecken. Zudem können Sie vertrauenswürdige Coupon-Websites besuchen, um die neuesten und funktionierenden Temu-Gutscheincodes zu finden. Wie funktionieren Temu 40% Rabatt Coupons? Der Temu Gutschein-Code 40% Rabatt für Erstbenutzer bietet eine direkte Möglichkeit, beim Einkaufen zu sparen. Wenn Sie den Gutschein verwenden, wird der Rabatt direkt auf Ihren Einkauf angewendet, sodass Sie sofortige Ersparnisse genießen können. Der Prozess ist einfach: Sie geben den Gutscheincode an der Kasse ein, und der Rabatt wird von Ihrem Gesamtbetrag abgezogen. Dies macht das Einkaufen nicht nur günstiger, sondern auch einfacher und schneller. Wie kann ich 40% Rabatt Coupons in Temu als neuer Kunde verdienen? Der Temu Gutschein-Code 40% Rabatt und der Temu 40 Rabatt Gutschein-Code für die erste Bestellung bieten eine einfache Möglichkeit, Geld zu sparen. Um die Gutscheine zu verdienen, melden Sie sich einfach bei Temu an und nutzen Sie die speziellen Angebote für neue Kunden. Mit jedem Kauf und durch das Teilen von Temu auf sozialen Medien können Sie zusätzliche Rabatte und Coupons erhalten. So können Sie kontinuierlich sparen und von tollen Angeboten profitieren. Was sind die Vorteile der Nutzung von Temu 40% Rabatt Coupons? Die Verwendung unserer Gutscheincodes auf der Temu-App und der Website hat viele Vorteile. Mit dem Temu 40% Rabatt Gutschein-Code legitim und dem Gutschein-Code für Temu 40 Rabatt können Sie folgende Vorteile genießen: 40% Rabatt auf die erste Bestellung $100 Gutschein-Paket für mehrfachen Gebrauch Bis zu 70% Rabatt auf beliebte Artikel Zusätzliche 30% Rabatt für bestehende Temu-Kunden Bis zu 90% Rabatt auf ausgewählte Artikel Kostenloses Geschenk für neue Nutzer Kostenloser Versand nach Deutschland Temu kostenloses Geschenk und spezielle Rabatte für neue und bestehende Nutzer Die Verwendung unseres Temu 40% Rabatt Gutscheincodes und 40% Rabatt Temu Gutscheincodes bietet viele Vorteile. Mit dem Gutscheincode acu639380 erhalten Sie zahlreiche Vorteile: 40% Rabatt auf die erste Bestellung 40% Rabatt für bestehende Kunden Zusätzliche 30% Rabatt auf jeden Artikel Kostenloses Geschenk für neue Temu-Nutzer Bis zu 70% Rabatt auf Artikel in der Temu-App Kostenloses Geschenk mit kostenlosem Versand nach Deutschland Vor- und Nachteile der Verwendung des Temu Gutscheincodes 40% Rabatt Bei der Nutzung des Temu Gutscheincodes 40% Rabatt und des Temu kostenlosen Gutscheincodes 40 Rabatt gibt es sowohl Vorteile als auch Nachteile. Hier sind einige der wichtigsten Punkte: Vorteile: Hohe Einsparungen auf die erste Bestellung. Verfügbarkeit von Gutscheinen für mehrere Käufe. Zugang zu exklusiven Rabatten und Geschenken. Kostenloser Versand nach Deutschland. Einfache Einlösung der Gutscheincodes. Nachteile: Mögliche Einschränkungen bei bestimmten Produkten. Einige Gutscheine können zeitlich begrenzt sein. Nicht alle Angebote sind für bestehende Kunden verfügbar. Bedingungen und Konditionen des Temu 40% Rabatt Gutscheincodes 2024 Bei der Verwendung des Temu Gutscheincodes 40% Rabatt für kostenlosen Versand und des Temu Gutscheincodes 40% Rabatt Reddit gelten folgende Bedingungen: Unsere Gutscheincodes haben kein Ablaufdatum und können jederzeit verwendet werden. Die Gutscheine sind sowohl für neue als auch bestehende Nutzer in Deutschland gültig. Es gibt keine Mindestkaufanforderungen zur Verwendung der Temu-Gutscheincodes. Abschließende Anmerkung Zusammenfassend lässt sich sagen, dass der Temu Gutschein-Code 40% Rabatt eine hervorragende Möglichkeit ist, beim Einkaufen zu sparen. Nutzen Sie diese Chance, um von den vielen Vorteilen zu profitieren! Mit dem Temu 40% Rabatt Gutschein stehen Ihnen zahlreiche Möglichkeiten offen, um beim Einkaufen in Deutschland Geld zu sparen. FAQs zum Temu 40% Rabatt Gutschein 1. Wie oft kann ich den Temu Gutscheincode verwenden? Sie können den Temu Gutscheincode mehrmals verwenden, solange er gültig ist und Sie die Bedingungen einhalten. Ist der Gutscheincode für internationale Bestellungen gültig? Der Gutscheincode ist in erster Linie für Nutzer in Deutschland gedacht und kann Einschränkungen für internationale Bestellungen haben. Wo finde ich die neuesten Gutscheincodes? Die neuesten Gutscheincodes finden Sie auf der Temu-Website, im Newsletter oder auf vertrauenswürdigen Coupon-Websites. Kann ich den Gutscheincode mit anderen Rabatten kombinieren? In der Regel sind Gutscheincodes nicht mit anderen Angeboten kombinierbar, es sei denn, dies wird ausdrücklich angegeben. Was soll ich tun, wenn mein Gutscheincode nicht funktioniert? Überprüfen Sie, ob der Gutscheincode korrekt eingegeben wurde und ob er noch gültig ist. Wenn das Problem weiterhin besteht, kontaktieren Sie den Kundensupport von Temu.
Last updated: 2024-10-26
Post by mubeta on Some 'pathetic' errors in SoftMotion program
CODESYS Forge
talk
(Post)
Hello everyone, I have a very simple program for the process, but it's driving me crazy and I can't see the problems I'm left with: Short topological description: Dual Core Berghof controller with softmotion runtime version 3.5.19.30; Two axes with servodrive on canopen bus, clocked distributed from master; Ethercat I/O node; 2 ms ethercat task, 2 ms canopen bus cycle time; I/O objects of the canopen master and canopen drives connected to the ethercat task cycle; Problem 1: Two separate programs each manage their own axis and drive, with separate state machines. A first axis moves primarily in velocity, except having to position itself absolutely at a predetermined point at the end of the job; the second axis, on the other hand, is a paper unwinder that changes, for each job cycle, from actions in absolute, relative, and cam displacement with the master axis. Well, the state machine of both axes was written in such a way as to call running the useful FB and change it on state change in this way: CASE i_stateMachine OF 0: o_Power(Enable := TRUE, bRegulatorOn := FALSE, bDriveStart := FALSE, Axis := o_PaperUnwinderAxis); o_MoveAbs(Execute := FALSE, Axis := o_PaperUnwinderAxis); o_MoveRel(Execute := FALSE, Axis := o_PaperUnwinderAxis); o_CamSelect(Execute := FALSE, Master := o_MachineAxis, Slave := o_PaperUnwinderAxis, CamTable := cam_PaperUnwinder); o_CamIn(Execute := FALSE, Master := MachineEncoder, Slave := o_PaperUnwinderAxis); o_CamOut(Execute := FALSE, Slave := o_PaperUnwinderAxis); o_SetPosition(Execute := FALSE, Axis := o_PaperUnwinderAxis); IF ... THEN i_StateMachine := 10; END_IF; 10: o_Power( Enable := TRUE, bRegulatorOn := TRUE, bDriveStart := TRUE, Axis := o_PaperUnwinderAxis ); IF o_Power.Status THEN i_StateMachine := 20; END_IF; 20: (* Avanzamento carta *) o_MoveAbs( Execute := TRUE, Position := o_Somewhere, Velocity := 25.0, Acceleration := 3666.7, Deceleration := 3666.7, Jerk := 48000.0, Direction := MC_DIRECTION.positive, Axis := o_PaperUnwinderAxis ); IF o_MoveAbs.Done THEN o_MoveAbs(Execute := FALSE, Axis := o_PaperUnwinderAxis); i_StateMachine := 30; END_IF 30: d_HomingPosition := ...; o_SetPosition( Execute := TRUE, Position := d_HomingPosition, Mode := FALSE, Axis := o_PaperUnwinderAxis ); (* ... *) IF o_SetPosition.Done = TRUE THEN o_SetPosition(Execute := FALSE, Axis := o_PaperUnwinderAxis ); o_LogServer.Append(sMessage := '...', lscClass := LOGSERVER_CLASS.ALWAYS, sdt := o_CommonsMgrData.systime.sdtLocal); i_StateMachine := 40; END_IF; 50: ... The code above is a sketchy example of what I wanted to write. But it gives me a spot problem: in some, the state change results in a drive error, which is unrecoverable except with a reinitialization via SM3_ReinitDrive(). Things are improved a little if in the program I always run the call of all softmotion blocks in this way: o_Power(Axis := o_PaperUnwinderAxis); o_Jog(Axis := o_PaperUnwinderAxis); o_Halt(Axis := o_PaperUnwinderAxis); o_MoveAbs(Axis := o_PaperUnwinderAxis); o_MoveRel(Axis := o_PaperUnwinderAxis); o_CamIn(Master := MachineEncoder, Slave := o_PaperUnwinderAxis); o_CamOut(Slave := o_PaperUnwinderAxis); If I don't execute all the calls of all the motion FBs used, when exchanging machine state often (but not always), the axis goes into error with event id THE_FB_WASNT_CALL... Done a little diagnostics it seems that the FBs return the bDone, before they are completely terminated. I tried doing the machine state exchange not with the bDone bit of the FBs, but with the 'standstill' state of the axis. It didn't seem to change anything. Problem 2: During the use SM3_ReinitDrive() I get the erro in the log: "NetID 0: SDO read error for object 16#607C..." Assuming that the device involved it's one of the two servodrive, (no others device are present in the network), I don't found any object 0x607C in the 'possible object list in/out' of the two drive, and I don't understand where this object can be listed. So any ideas and suggestions regarding these two issues will be very, very welcome. If you need the source project, I am willing to send it.
Last updated: 2024-07-17
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 lsislsis on SIGABRT Error
CODESYS Forge
talk
(Post)
Please help us. Why we take this errors. We try different versions like 4.12.0 and 4.13.0 with same results. ;*********;<loggername>codesyscontrol.log</loggername>;<logoptions>; <enable>1</enable>; <type>normal</type>; <timestamp>rtc high resolution</timestamp>; <deactivatable>0</deactivatable>; <dump>always</dump>; <filter>0x0000000f<filter>; <maxentries>100000</maxentries>; <maxfiles>1</maxfiles>; <maxfilesize>1000000</maxfilesize>;</filter></filter></logoptions>;<entries>;Timestamp, CmpId, ClassId, ErrorId, InfoId, InfoText;ClassId: LOG_INFO =1;ClassId: LOG_WARNING =2;ClassId: LOG_ERROR =4;ClassId: LOG_EXCEPTION =8;ClassId: LOG_DEBUG =16;ClassId: LOG_PRINTF =32;ClassId: LOG_COM =64;</entries>;*********2024-11-05T08:23:59.728Z, 0x0000100c, 1, 0, 0, VisuFctCheckForUnusedClients: Removing Client with IEC-ID: 1 Time delta: T#33s1ms Locks: Paintbuffer: TRUE 2024-11-05T08:23:59.728Z, 0x0000100c, 1, 0, 0, VisuFctCheckForUnusedClients: Successfully Removed Client at Address: 547195449944, IEC-ID was: 1, EXT-ID: 431000373 2024-11-05T08:28:57.913Z, 0x0000100c, 1, 0, 0, Visu_PRG: Creating Client for Extern-ID: 347055752 2024-11-05T08:28:57.926Z, 0x0000100c, 1, 0, 0, Visu_PRG: Creating Client successful for Extern-ID: 347055752 Returned IEC-ID: 1 2024-11-05T08:30:51.103Z, 0x0000100c, 1, 0, 0, Visu_PRG: Successfully Removed Client with IEC-ID: 1, Extern-ID: 347055752 2024-11-05T08:37:36.517Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state* We recommend a reboot of the controller now! 2024-11-05T08:37:36.517Z, 0x00000111, 8, 260, 3, #### Exception: HANDLED EXCPT <excpt>NonContinuable</excpt> in CH_COMM_CYCLE 2024-11-05T08:47:42.117Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! 2024-11-05T08:47:42.117Z, 0x00000111, 8, 260, 3, #### Exception: HANDLED EXCPT <excpt>NonContinuable</excpt> in CH_COMM_CYCLE 2024-11-05T09:14:41.316Z, 0x00000071, 1, 0, 13, Webserver stopped 2024-11-05T09:14:44.485Z, 0x0000013d, 1, 0, 4, Number of licensed cores for IEC-tasks: 1 from 4 2024-11-05T09:14:44.487Z, 0x0000013d, 1, 0, 4, Number of licensed cores for IEC-tasks: 4 from 4 2024-11-05T09:14:44.540Z, 0x00000002, 1, 0, 2, Application [<app>Application</app>] loaded via [Download] 2024-11-05T09:14:55.894Z, 0x00001012, 1, 0, 0, Opened alarm storage file, version: 6 2024-11-05T09:14:55.951Z, 0x0000100c, 1, 0, 0, Visuinitialization starting. 2024-11-05T09:14:55.983Z, 0x0000100c, 1, 0, 0, Visuinitialization done. 2024-11-05T09:14:55.995Z, 0x00000071, 1, 0, 12, Webserver started 2024-11-05T09:15:01.753Z, 0x0000100c, 1, 0, 0, Visu_PRG: Creating Client for Extern-ID: 2279884529 2024-11-05T09:15:01.753Z, 0x0000100c, 1, 0, 0, Visu_PRG: Creating Client successful for Extern-ID: 2279884529 Returned IEC-ID: 0 2024-11-05T09:34:44.667Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! 2024-11-05T09:34:44.667Z, 0x00000111, 8, 260, 3, #### Exception: More than 2 exceptions in CH_COMM_CYCLE: Stop logging 2024-11-05T10:13:26.867Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! 2024-11-05T10:15:21.966Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! 2024-11-05T10:19:12.167Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! 2024-11-05T10:26:02.566Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! 2024-11-05T10:31:42.866Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! 2024-11-05T11:01:54.468Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! 2024-11-05T11:09:29.868Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! 2024-11-05T11:14:44.540Z, 0x0000100d, 1, 0, 0, Demo mode expired. 2024-11-05T11:27:20.868Z, 0x00000103, 65544, 1, 0, runtime received SIGABRT - system may be in an inconsistent state We recommend a reboot of the controller now! * Regards
Last updated: 2024-11-05
Post by drbuzz on Communication Error (#0) for IFM controller
CODESYS Forge
talk
(Post)
Hi Folks, Every time I use an IFM controller I always seem to run into a problem connecting to it. I get the Communications Error (#0). So I thought I would share some tips and tricks. Once the CANfox Cable (EC2112) cable driver is installed, you can use the yellow app in the sys tray to blink the lights on the cable. Confirm the cable works in the IFM maintenance software by connecting to the controller and reading the information on it. Make sure to download an OS into the controller (the light will go from a fast blink to solid green). In Codesys V2.3, the communication settings for the CR0401 is 250kBaud by default and Node ID 127. What got me, was I needed to reboot the computer after the cable driver install. Also if your application has canbus settings in it which are changed from default, after the controller is power cycled, the new Node ID and Baud will be in effect. I made a handy guide because too much time has been wasted on this. Programming IFM CR0401 Serial/Can Programming Cable • Connect IFM EC2112 CanFox programming cable with connector adapter. • Make sure cable is linked to VM (if using VM). • Install drivers for cable if not installed. o Download from IFM EC2112 site. https://www.ifm.com/ca/en/product/EC2112 • Once Installed, reboot computer. • In system tray, there should be a yellow icon that you can open and check on programming cable. Select the cable in the list and flash the lights to confirm it is working. Maintenance Software • Install IFM Maintenance Tool Software. o Download from IFM Site. https://www.ifm.com/ca/en/download/eco100_MaintenanceTool • Open IFM Maintenance software • Select Basic System • Select CAN cable • It will tell you if you don’t have a cable connected. • Use Wizard if needed. • Read Channel Parameter on the Settings page, or get Identity in the System Information > Identity. • Default Node is 127 on a new unit. Baud is 250kBaud (bits/sec) • Controller information should populate. • Controller green light should be blinking at 5hz (meaning OK but no OS, just bootloader). • Click Software > Load. • Open the OS file. Should match Codesys version selection (for CR0401 this is version 3). o Download OS file from IFM Website. https://www.ifm.com/ca/en/product/CR0401 o It is located at the top of the download under “software for CR0401”. o Select the file and load it… this will take a minute. • Once completed the unit should now have a solid green light o Solid green means the controller has an OS but no application is running. Codesys V2.3 Application • Codesys needs to be downloaded and installed from the IFM website as it has the IFM libraries and license to use the software. o Download from the IFM CR0401 page. o https://www.ifm.com/ca/en/product/CR0401 • Create new application with the correct IFM controller or Open Codesys application. • Keep in mind that the PLC Configuration on the Resources tab can be changed for the CAN communication interface… so changes to node and baud will take effect after the first download and reboot of the controller. • Go to “Online” in the top menu and change “Communication Parameters” o The Local dropdown shows the last configuration used. All other interfaces will show below it and need to be updated when changed or used. o Confirm Node ID is 127 for the first download. The NodeID will change to whatever the program has after (in my case 125). Node Send Offset should be default at 1536 Node Recv Offset should be default at 1408 Can bus Baudrate should be 250 kbaud. Yes to Motorola Byte Order Block Transfer should be false and note used (60 is default setting). Can Card Driver should match the systray item which is Sie_USB. • If the system populated the other one, just update and relay the communication parameters. The software will usually bring up the available cable and driver. • Go to “Online” and Login to download. o Press Yes to Download Application. I hope this helps!
Last updated: 2025-03-21
Post by mondinmr on Direct Pointers in IOMapping for EtherCAT with IoDrvEthercatLib.ETCSlave_Dia
CODESYS Forge
talk
(Post)
I have found a very interesting solution using: IoConfigTaskMap IoConfigConnectorMap IoConfigChannelMap The first is the list of IO tasks. The second is the connector for each IO module in the IOMap. The third is the individual input or output on the IOMap. One of the properties of the connector is another pointer to a connector, which corresponds with the connector of the EtherCAT slave. Through this information, it is possible to understand to which EtherCAT slave an IO connectormap corresponds. I am attaching an FB that allows for the construction of an IO map and finding the pointer to the actual IOs in the IOMap based on the bitoffset. FUNCTION_BLOCK IOExplorer VAR_INPUT END_VAR VAR_OUTPUT END_VAR VAR inputChannels: COL.LinkedList; outputChannels: COL.LinkedList; ulintFactory: COL.UlintElementFactory; END_VAR METHOD inputAtBitOffsetOfConnector : POINTER TO BYTE VAR_INPUT conn: POINTER TO IoConfigConnectorMap; bitOffset: UDINT; END_VAR VAR it: COL.LinkedListIterator; itf: COL.IElement; elem: COL.iUlintElement; channelInfo: POINTER TO ADVChannelInfo; bitOffsetR: UDINT; END_VAR inputChannels.ElementIterator(it); WHILE it.HasNext() DO it.Next(itfElement => itf); __QUERYINTERFACE(itf, elem); {warning disable C0033} channelInfo := TO___UXINT(elem.UlintValue); {warning restire C0033} IF channelInfo^.connectorField = conn THEN IF bitOffsetR = bitOffset THEN inputAtBitOffsetOfConnector := channelInfo^.addr; RETURN; END_IF bitOffsetR := bitOffsetR + channelInfo^.size; ELSE bitOffsetR := 0; END_IF END_WHILE inputAtBitOffsetOfConnector := 0; END_METHOD METHOD outputAtBitOffsetOfConnector : POINTER TO BYTE VAR_INPUT conn: POINTER TO IoConfigConnectorMap; bitOffset: UDINT; END_VAR VAR it: COL.LinkedListIterator; itf: COL.IElement; elem: COL.iUlintElement; channelInfo: POINTER TO ADVChannelInfo; bitOffsetR: UDINT; END_VAR outputChannels.ElementIterator(it); WHILE it.HasNext() DO it.Next(itfElement => itf); __QUERYINTERFACE(itf, elem); {warning disable C0033} channelInfo := TO___UXINT(elem.UlintValue); {warning restire C0033} IF channelInfo^.connectorField = conn THEN IF bitOffsetR = bitOffset THEN outputAtBitOffsetOfConnector := channelInfo^.addr; RETURN; END_IF bitOffsetR := bitOffsetR + channelInfo^.size; ELSE bitOffsetR := 0; END_IF END_WHILE outputAtBitOffsetOfConnector := 0; END_METHOD METHOD scanIO VAR_INPUT END_VAR VAR numTasks: DINT := IoConfig_Globals.nIoConfigTaskMapCount; tType: WORD; ioTask: POINTER TO IoConfigTaskMap; numCon: WORD; connector: POINTER TO IoConfigConnectorMap; numCh: DWORD; channelInfo: POINTER TO ADVChannelInfo; iTsk: DINT; iCon: WORD; iCh: DWORD; i: DINT; _tmpConnList: COL.IList; elem: COL.IUlintElement; itf: COL.IElement; tmpCh: POINTER TO ADVChannelInfo; lastE: DINT; e: COL.COLLECTION_ERROR; e1: Error; END_VAR VAR_INST lF: COL.ListFactory; END_VAR IF outputChannels.CountElements() > 0 OR inputChannels.CountElements() > 0 THEN RETURN; END_IF _tmpConnList := lF.CreateDynamicList(16, 16); //Iterate through all IO tasks FOR iTsk := 0 TO numTasks - 1 DO ioTask := ADR(IoConfig_Globals.pIoConfigTaskMap[iTsk]); //Store the type of the task (Input or Output) tType := ioTask^.wType; numCon := ioTask^.wNumOfConnectorMap; //Iterate through all connectors of the task FOR iCon := 0 TO numCon - 1 DO connector := ADR(ioTask^.pConnectorMapList[iCon]); numCh := connector^.dwNumOfChannels; //Iterate through all channels of the connector FOR iCh := 0 TO numCh - 1 DO //Create a new channel info object and fill it with the address, connector and size of the channel //Connectors is address of field connector in this case like EtherCAT slave //Address is the address of the IOMap //Size is the size of channel data in bits in IOMap channelInfo := __NEW(ADVChannelInfo); channelInfo^.addr := connector^.pChannelMapList[iCh].pbyIecAddress; channelInfo^.connectorField := connector^.pConnector; channelInfo^.size := connector^.pChannelMapList[iCh].wSize; //We put the channel info a temporary ordered list //Order is based on the address of IOMap lastE := TO_DINT(_tmpConnList.CountElements()) - 1; FOR i := 0 TO lastE DO _tmpConnList.GetElementAt(udiPosition := TO_UDINT(i), itfElement => itf); __QUERYINTERFACE(itf, elem); {warning disable C0033} tmpCh := TO___UXINT(elem.UlintValue); {warning restire C0033} //If the address of the channel is smaller than the address of the channel in the list IF tmpCh^.addr > channelInfo^.addr THEN //Insert the channel in the list at the current position _tmpConnList.InsertElementAt(TO_UDINT(i), ulintFactory.Create(TO_ULINT(channelInfo))); //Clear the channel info pointer channelInfo := 0; //Exit the loop i := lastE + 1; END_IF END_FOR //If the channel info is not 0, it means that the channel was not inserted in the list IF channelInfo <> 0 THEN //Add the channel to the end of the list elem := ulintFactory.Create(TO_ULINT(channelInfo)); _tmpConnList.AddElement(elem); END_IF END_FOR //Iterate temporary list and add the channels to the input or output list lastE := TO_DINT(_tmpConnList.CountElements()) - 1; FOR i := 0 TO lastE DO _tmpConnList.GetElementAt(udiPosition := TO_UDINT(i), itfElement => itf); __QUERYINTERFACE(itf, elem); {warning disable C0033} tmpCh := TO___UXINT(elem.UlintValue); {warning restire C0033} //If type is input, add the channel to the input list IF tType = TaskMapTypes.TMT_INPUTS THEN e := inputChannels.AddElement(ulintFactory.Create(TO_ULINT(tmpCh))); //If type is output, add the channel to the output list ELSIF tType = TaskMapTypes.TMT_OUTPUTS THEN e := outputChannels.AddElement(ulintFactory.Create(TO_ULINT(tmpCh))); ELSE __DELETE(tmpCh); END_IF END_FOR //Clear the temporary list _tmpConnList.RemoveAllElements(); END_FOR END_FOR END_METHOD
Last updated: 2024-02-13
Post by mogam on Internal error:System.NullReferenceException: The object reference was not set to an object instance.
CODESYS Forge
talk
(Post)
Hi everyone, I have a my App that reads values from a shared memory than 2 variables x,y were calculated. here as you can see in my code: PROGRAM PLC_PRG VAR szName : STRING := '/SM'; ( Name of the shared memory.) uxiSize : __UXINT := 646 * 2 * SIZEOF(REAL); ( Size of the shared memory. ) hShm : RTS_IEC_HANDLE; ( Handle to the shared memory ) pStart : POINTER TO REAL; ( Pointer to the first element in the memory ) pData : POINTER TO REAL; ( Pointer, which is incremented until the last sign in the memory is reached. ) shared_data :ARRAY[0..645, 0..1] OF REAL; velocity : ARRAY[0..2] OF REAL; ( Velocity array ) position : ARRAY[0..2] OF REAL; ( Position array ) angleDepth : ARRAY[0..645, 0..1] OF REAL; ( Angle and depth array ) xEndOfMemory : BOOL; x : ARRAY[0..645] OF REAL := 1.0; y : ARRAY[0..645] OF REAL := 1.0; (* Result of actions at the memory. *) OpenResult : RTS_IEC_RESULT; ReadResult : RTS_IEC_RESULT; PointerResult : RTS_IEC_RESULT; DeleteResult : RTS_IEC_RESULT; CloseResult : RTS_IEC_RESULT; i : INT; END_VAR ( Open the shared memory ) hShm := SysSharedMemoryOpen2(szName, 0, ADR(uxiSize), ADR(OpenResult)); IF hShm <> RTS_INVALID_HANDLE THEN (* Read the entire shared memory table *) SysSharedMemoryRead(hShm:= hShm, ulOffset:= 0, pbyData:= ADR(shared_data), ulSize:= uxiSize, pResult:= ADR(ReadResult)); (* Fetch the pointer from the shared memory. The pointer is pointing to the first element address *) //pStart := SysSharedMemoryGetPointer(hShm, ADR(PointerResult)); (* Close the shared memory *) //CloseResult := SysSharedMemoryClose(hShm := hShm); (* Read velocity and position data from the shared memory *) FOR i := 0 TO 2 DO velocity[i] := shared_data[i, 0]; position[i] := shared_data[i, 1]; END_FOR; (* Read angle and depth data from the shared memory *) FOR i := 0 TO 645 DO angleDepth[i, 0] := shared_data[(i + 6), 0]; angleDepth[i, 1] := shared_data[(i + 6), 1]; END_FOR; FOR i := 0 TO 645 DO x[i] := angleDepth[i, 1]*COS(angleDepth[i, 0]); y[i] := angleDepth[i, 1]*SIN(angleDepth[i, 0]); END_FOR; END_IF For these values an XY-CHART needs to be done and when i create a visualisation and set the x data and y data when i try to compile, i recieve this error: ------ Übersetzungslauf gestartet: Applikation: Device.Read_App ------- Code typisieren ... [FEHLER] Internal error:System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt. bei _3S.CoDeSys.LanguageModelManager.LDateType.Accept(ITypeVisitor typvis) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IArrayType ) bei ..(_IPointerType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IPointerType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IPointerType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei ..(_ISignature , _IPreCompileContext ) bei ..( ) bei ..(String ) bei ..(String , IVariable[]& , ISignature[]& ) bei ..(String , IVariable[]& , ISignature[]& , IScope& ) bei ..visit(_IVariableExpression , AccessFlag ) bei ..(_IUserdefType ) bei ..(_IVariable , IScope5 , _ICompileContext , _ISignature ) bei ..(_ISignature , IScope5 , _ICompileContext ) bei _3S.CoDeSys.Compiler35140.Compiler.(_ICompileContext , _IPreCompileContext , _ICompileContext , IProgressCallback ) bei _3S.CoDeSys.Compiler35140.Compiler.(_ICompileContext , Boolean , Boolean , _IPreCompileContext , _IPreCompileContext , _ICompileContext , Boolean , Boolean& , IProgressCallback ) bei _3S.CoDeSys.Compiler35140.Compiler.(Guid , Boolean , Boolean , Boolean , Boolean& , _ICompileContext& , _ICompileContext& , IProgressCallback , Boolean , Boolean ) Kompilierung abgeschlossen -- 1 Fehler, 0 Warnungen Übersetzung abgeschlossen -- 1 Fehler, 0 Warnungen : Kein Download möglich!
Last updated: 2024-05-24
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.