X3:=X3+1; is part of your issue. a FOR loop automatically increments your loop variable. //====================Write Tool Numbers X3 ================= FOR X3:=42 TO 60 DO Base1Index := X3-41; IF DbAutomatic.PosX3.Index = 3 THEN // looks missplaced or missing array reference ? (I would put this ahead of for loop) IF DbAutomatic.PosX3.Status[Base1Index] THEN DbAutomatic.PosX3.ToolNumber[Base1Index]:=X3; DbAutomatic.AllTools[X3].Number:=X3; // This is weird (copying your own index ? I would expect Base1Index)...
Some IO-link master are configured from a webserver. Then they expose a communication table you can define on it (MURR works this way).
Not really a 1:1 feature, but there are those 2 : AT keyword, used to "alias" an I/O or memory (I,Q and M) https://help.codesys.com/webapp/_cds_at_declaration;product=codesys;version=3.5.14.0 UNION datatype, allows you to interpret the same RAW data with different datatypes https://help.codesys.com/webapp/_cds_datatype_union;product=codesys;version=3.5.14.0
I don't know about general purpose variable writing, but you should have a look at the forums. Already saw a post trying to get values from a file (like JSON does) For specific purposes and few variables, you may do it in 2 steps. 1) Get the variable name and test if it match one expected 2) Convert the value to desired datatype https://help.codesys.com/webapp/_cds_operator_string_to;product=codesys;version=3.5.14.0
How about using a simple ROL on send buffer ? (* Assuming this is a word array buffer *) (* And that you only process it once *) FOR i:=0 TO LastWordIndexInBuffer DO SendBuffer[i] := ROL(SendBuffer[i],8); END_FOR;
How about using a simple ROL on send buffer ? // Assuming this is a word array buffer // And that you only process it once FOR i:=0 TO LastWordIndexInBuffer DO SendBuffer[i] := ROL(SendBuffer[i],8); END_FOR;
Both device are codesys plcs ? How are you transfering/recovering data from communication buffers to structures ?
If you want to show a program window, you first have to check which is the user starting the program. Because the interface you see here, is for a user and only this one. Althougt that a user may not have an interface at all (system accounts for instance). So I would look at how to start your program with the proper user first.
What is the result if you use variables from a GVL ? Is your PLC (simulation) in RUN ?
What is the result if you use variables from a GVL ? Is your PLC (simalation) in RUN ?
I'm no part of codesys. C0139 Warning pops up because your pointer value is read only at intitialisation. But the address may change with an online change : (see first hint) https://help.codesys.com/webapp/_cds_cmd_online_change;product=codesys;version=3.5.14.0 Enumerations are a list a values that a variable may take. Meaning that this variable is expected to not take any other value than those defined in the enumeration. Using such a type on an input is weird, because you should handle the other...
Well, I would just use a task for this, triggered every second. That would be more efficient. Anyway, show us your code, and you might be helped.
Unit ID feels wrong also, even if it seems to work. Recall that serial Modbus uses addresses 1 to 247 decimal, and reserves 0 as a broadcast address. Even if some modbus TCP devices just ignore the address and echoes it back, 255 is generally used for a single device. So if this device is a gateway, 1-247 is generally used with a gateway(TCP/SL) to point a device on SL. Exception Code MODBUS name Comments 01 - Illegal Function Code - The function code is unknown by the server 02 - Illegal Data Address...
Well, a good start is to search for some tutorials : https://www.youtube.com/results?search_query=tutorial+codesys+3.5 Just browse a bit, there are specialized content as well as generic content about the interface itself or IEC languages.
I don't get the point on nested FBs and pointers. Just get the address you need on top level FB and forward it. For instance, if you have a car FB, with an accelerator pedal FB inside, reading the analog value of the pedal, just forward the address from car FB to pedal FB. You can also place the address inside a struct, from a first POU and then use the address provided by the struct. The point with dealing with pointers is that your adress may change with online change, so if you don't set the pointer...
I don't get the point on nested FBs and pointers. Just get the address you need on top level FB and forward it. For instance, if you have a car FB, with an accelerator pedal FB inside, reading the analog value of the pedal, just forward the address from car FB to pedal FB. You can also place the address inside a struct, from a first POU and then use the address provided by the struct. The point with dealing with pointers is that your adress may change with online change, so if you don't set the pointer...
For instance, imagine you have an FB to correctly map your com data to a struct, and this FB takes as inputs : pInData : POINTER TO ARRAY [0..5] OF BYTE; pOutData : POINTER TO ARRAY [0..5] OF BYTE; Then to call your FB, you could use : MyFB(pInData:= ADR(%IB0), pOutData:= ADR(%QB0)); Then, inside your FB : var1 := pInData^; var2 := pInData^[1]; var3.0 := pInData^[2].0;
Using %I %Q addressing, you can also map by program using POINTER TO BYTE (and as you know the right size, get all the data to a formated struct or whatever you needs).
Hint Functions have no internal status information, which means that functions do not save the values of their variables until the next call. Calls of a function with the same input variable values always supply the same output value. Therefore, functions may not use global variables and addresses! source : https://help.codesys.com/webapp/_cds_obj_function;product=codesys;version=3.5.14.0
I can't really tell without opening your archive, but I can't do it for now. Just have a look on a disconnected state without requests, and with, and play the 7 differences game with your variables values. Maybe you will find it that way.
Assuming your code is the same you posted earlier, You should fix a bad call issue : You call the ClientSerial Instance twice, and on first call, no parameters were provided, so at first call you run on defauts. And a bad behavior about retries sequencing : when you cycle from retry steps to step 10, this is only one FB instance call with xConnect = FALSE. Keep in mind that some resources are async, especially doing communication. Meaning that it may take more than one cpu cycle for some tasks to...
Please read the documentation about the block you use before asking for help. Inputs: CU : BOOL; With each rising edge at this input the counter value (CV) is incremented by 1. When CV reaches or exceeds PV, QU will be set to TRUE. CD : BOOL; With each rising edge at this input the counter value (CV) is decremented by 1 until 0 is reached.
Pointers are not a big deal. See help For instance, you may have a struct, for the queue elements. Lets say you need to know the type of work (read/write), the data to be written or read. STRUCT ModbusQueueItem TypeOfWork : INT; pData : Pointer TO BOOL; // Data pointer for boolean data szData : INT; // Size of data END_STRUCT So In case of Read, just provide the pData to pData of ClientRequestReadDiscreteInputs, given that your RELAY block did correctly set the item using ADR(YourData). This is only...
You cannot execute 2 functions at the same time on the same port. You have to sequence each request. I would call the read/write inside the MODBUS_CLIENT_SERIAL and then provide a queue for the MODBUS_RELAY FBs. Then just place a request with its parameters in the queue with MODBUS_RELAY, process them in MODBUS_CLIENT_SERIAL, using pointers for in/out data, and also results. This way the asking RELAY FB could be aware his request have been processed. For less modifications of your code, you can also...
You cannot execute 2 functions at the same time on the same port. You have to sequence each request. I would call the read/write inside the MODBUS_CLIENT_SERIAL and then provide a queue for the MODBUS_RELAY FBs. Then just place a request with its parameters in the queue with MODBUS_RELAY, process them in MODBUS_CLIENT_SERIAL, using pointers for in/out data, and also results. This way the asking RELAY FB could be aware his request have been processed.
You can write FB internals signals. Then, on FB call, do the processing of those signals and provide an internal result. And forward the result with some property for exemple. So you would have only to provide the correct structure on the correct FB call, which you should be aware at design time. As your method seems to perform async orders (Jogging), you can forward a result of the order correctly scheduled, and use properties to know the state of your axis (jogging forward, stopped ..)
You can write FB internals signals. Then, on FB call, do the processing of those signals and provide an internal result. And forward the result with the method ouput. So you would have only to provide the correct structure on the correct FB call, which you should be aware at design time.
This question, even related to your first one, should be split in another topic, as it is different from you first one.
even on error of list, you should close it always. by the way, the exemple you use does it almost correctly.
FB_ListerFichier( hDir:=hDir, xExecute:=(uiEtape=1) AND (NOT FB_ListerFichier.xDone OR FB_ListerFichier.eError=5106));
Yes, just make it 1->0->1 once to get the next results. -- Frog eaters mode ON Etant donné que le bloc ne sort qu'un seul résultat à la fois, il faut donc indiquer au bloc de donner le résultat suivant. Dans l'exemple que vous avez adapté, aucune entrée du bloc n'est modifiée, comme si le bloc modifiait ses sorties à chaque appel. Or dans le cadre d'opérations avec un système de fichiers, elles sont asynchrones, donc ce cas est a priori exclu.
Yes, just make it 1->0->1 once to get the next results. Etant donné que le bloc ne sort qu'un seul résultat à la fois, il faut donc indiquer au bloc de donner le résultat suivant. Dans l'exemple que vous avez adapté, aucune entrée du bloc n'est modifiée, comme si le bloc modifiait ses sorties à chaque appel. Or dans le cadre d'opérations avec un système de fichiers, elles sont asynchrones, donc ce cas est a priori exclu.
Did you tried to change execute flag of "FB_ListerFichier" while you are in step 1 ?
Well, on SP12 it is okay at least. Did you done the usual restart of codesys ?
This is the purpose of StringUtils Library Defaults functions are limitated to 255 Chars. More widely, strings are no more than arrays of bytes followed by an empty one. I suppose that wstring is the same, but speaking of words instead.
This is the purpose of StringUtils Library
Sorry for the mistake, {attribute 'qualified_only'} https://help.codesys.com/webapp/_cds_pragma_attribute_qualified_only;product=codesys;version=3.5.14.0
If I remember correctly, just remove the top attribute {attribute 'instance-path'} in text mode on GVL : (see https://help.codesys.com/webapp/_cds_pragma_attribute_instance_path;product=codesys;version=3.5.14.0 )
Feels like end of string detection isn't right. Maybe the lib was testing a byte, where you should test a word to NULL when using WSTRING.
The issue is using string_to function assumes that every char in your string is coded on 8 bits, while UTF8 is on 16 bits. So you are interpreting splitted chars. I don't know why you "need" to use .sContent to parse, but this could be a way to solve it. Also you may also just interpret a byte array (string and wsstring are no more than byte arrays) as a wstring using union for instance.
The issue is using string_to function assumes that every char in your string is coded on 8 bits, while UTF8 is on 16 bits. So you are interpreting splitted chars. I don't know why you "need" to use .sContent to parse, but this could be a way to solve it. Also you may also just interpret a byte array (string and wsstring are no more than byte arrays) as a wstring using union for exemples.
This won't answer the question but may solve your issue : Use a static IP in the DHCP server, so you can use a predefined static IP in UA expert.
Note for future me : do not spam the post button.
FOR Index := 0 TO 7 DO MyBytes[Index] := SHL(HEXinASCII_TO_BYTE(MyStr[Index*2]),4) + HEXinASCII_TO_BYTE(MyStr[Index*2 + 1]); END_FOR FOR Index := 0 TO 7 DO MyStr2[Index*2+1] := TO_BYTE(BYTE_TO_HEXinASCII(MyBytes[Index])); MyStr2[Index*2] := TO_BYTE(BYTE_TO_HEXinASCII(SHR(MyBytes[Index],4))); END_FOR Same lib. Please read a little the help.
FOR Index := 0 TO 7 DO MyBytes[Index] := SHL(HEXinASCII_TO_BYTE(MyStr[Index*2]),4) + HEXinASCII_TO_BYTE(MyStr[Index*2 + 1]); END_FOR FOR Index := 0 TO 7 DO MyStr2[Index*2+1] := TO_BYTE(BYTE_TO_HEXinASCII(MyBytes[Index])); MyStr2[Index*2] := TO_BYTE(BYTE_TO_HEXinASCII(SHR(MyBytes[Index],4))); END_FOR Same lib. Please read a little the help.
FOR Index := 0 TO 9 DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index]); END_FOR OR FOR Index := 0 TO 4 DO MyBytes[Index] := SHL(HEXinASCII_TO_BYTE(MyStr[Index*2]),4) + HEXinASCII_TO_BYTE(MyStr[Index*2 + 1]); END_FOR HEXinASCII_TO_BYTE is part of Util lib. Sometimes things are easier than it first look.
FOR Index := 0 TO 9 DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index]); END_FOR HEXinASCII_TO_BYTE is part of Util lib. Sometimes things are easier than it first look.
FOR Index := 0 TO 9 DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index]); END_FOR OR LastIndexHalved := SIZEOF(MyBytes)/SIZEOF(MyBytes[0])/2; FOR Index := 0 TO LastIndexHalved DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index]) * 16#FF + HEXinASCII_TO_BYTE(MyStr[Index + 1]); END_FOR HEXinASCII_TO_BYTE is part of Util lib. Sometimes things are easier than it first look.
FOR Index := 0 TO 9 DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index]); END_FOR OR LastIndexHalved := SIZEOF(MyBytes)/SIZEOF(MyBytes[0])/2; FOR Index := 0 TO LastIndexHalved DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index] * 16#FF + MyStr[Index + 1]); END_FOR HEXinASCII_TO_BYTE is part of Util lib. Sometimes things are easier than it first look.
FOR Index := 0 TO 9 DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index]); END_FOR OR LastIndexHalved := UPPER_BOUND(MyBytes,0)/2; FOR Index := 0 TO LastIndexHalved DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index] * 16#FF + MyStr[Index + 1]); END_FOR HEXinASCII_TO_BYTE is part of Util lib. Sometimes things are easier than it first look.
FOR Index := 0 TO 9 DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index]); END_FOR HEXinASCII_TO_BYTE is part of Util lib. Sometimes things are easier than it first look.
FOR Index := 0 TO 9 DO MyBytes[Index] := HEXinASCII_TO_BYTE(MyStr[Index]); END_FOR
actually, looping from 0 to 10 is 11 loops on a string of 10 chars. then if you want to get a byte value, don't concatenate 2 chars into a word. just take lower byte once at a time.
Did you had a look at OSCATT lib ? HEX_TO_BYTE seems to apply. Also there is WORD_AS_STRING in utils, but you need the exact opposite.
Did you had a look at OSCATT lib ? HEX_TO_BYTE seems to apply. Also there is WORD_AS_STRING in utils, but you need the exact opposite. Maybe a union of string(30) Byte(31) may do the job ? (string is 1 byte longer than character number, to store the null char which ends the string)
Did you had a look at OSCATT lib ? HEX_TO_BYTE seems to apply. Also there is WORD_AS_STRING, you need the exact opposite. Maybe a union of string(30) Byte(31) may do the job ? (string is 1 byte longer than character number, to store the null char which ends the string)
I would add that oscat is not known for its forum but for its very complete and nicely written library. They provide some function description and exemples in english and german. Actually, what you are asking is totally provided in the software help. You might not find it for some reasons, but it is. Being mad won't help you at all. Take a cold beer and chill :)
Please, have a search in Online Help before posting. The store also contains free code exemples and libs like oscat that suits your needs Codesys store
Maybe you could have a read of Online Help - Task configuration Watchdog is a protection mecanism. I don't know the exact behavior, but scheduling a task shorter than its execution time usually leads to schedule kill by the OS.
I think the issue is that the compiler cannot take a function as a value/variable for a function block input in a declaration. When you do the first and 3rd declaration, you link the input to a variable. But with 2nd one, you link it to the result of a function.
1. Pros Freewheel task length can be increased without much care Gives the fastest treatment and I/O refresh if you only need a task Cons As next scan depends on previous scan time, scan time is inconsistent with jitter, depending on your code and the machine situation Don't use it with any PID/PWM regulator, it's a bad idea (really bad) 2. Pros As scan times are more consistent, the machine tends to react the same, even if you have difference in scanned code from cycle to cycle Tasks can be priorized...
1. Pros Freewheel task length can be increased without much care Gives the fastest treatment and I/O refresh if you only need a task Cons As next scan depends on previous scan time, scan time is inconsistent with jitter, depending on your code and the machine situation Don't use is with any PID/PWM regulator, it's a bad idea (really bad) 2. Pros As scan times are more consistent, the machine tends to react the same, even if you have difference in scanned code from cycle to cycle Tasks can be priorized...
1. Pros Freewheel task length can be increased without much care Gives the fastest treatment and I/O refresh if you only need a task Cons As next scan depends on previous scan time, scan time is inconsistent with jitter, depending on your code and the machine situation Don't use is with any PID/PWM regulator, it's a bad idea (really bad) 2. Pros As scan times are more consistent, the machine tends to react the same, even if you have difference in scanned code from cycle to cycle Tasks can be priorized...
1. Pros Freewheel task length can be increased without much care Gives the fastest treatment and I/O refresh if you only need a task Cons As next scan depends on previous scan time, scan time is inconsistent with jitter, depending on your code and the machine situation Don't use is with any PID/PWM regulator, it's a bad idea (really bad) 2. Pros As scan times are more consistent, the machine tends to react the same, even if you have difference in scanned code from cycle to cycle Tasks can be priorized...
If you don't need access, just uncheck them from the list. If you can't this may be due to an attribute of your GVL : symbol You will have to manually check each variable you want. Edit : Fixed link
If you don't need access, just uncheck them from the list. If you can't this may be due to an attribute of your GVL : symbol Edit : Fixed link
If you don't need access, just uncheck them from the list. If you can't this may be due to an attribute of your GVL : Linkalways
Hi, did you had a look at Symbol Configuration ? Have a good day.
I was worried we went a little too far on this topic, but you clearly went a step further. Just about the real comparaison, real values are stored as IEEE format (see : https://en.wikipedia.org/wiki/Single-precision_floating-point_format#IEEE_754_single-precision_binary_floating-point_format:binary32 ). That's a good exemple why you need to type cast and compare values knowing the datatype you are comparing. great input π Edit : Typo
I was worried we went a little too far on this topic, but you clearly went a step further. Just about the real comparaison, real values are store as IEEE format (see : https://en.wikipedia.org/wiki/Single-precision_floating-point_format#IEEE_754_single-precision_binary_floating-point_format:binary32 ). That's a good exemple why you need to type cast and compare values knowing the datatype you are comparing. great input π
This may also be related : https://forge.codesys.com/forge/talk/search/?q=1561709038%2C+0x00000018&project=0
As you stated : an XML file (or another type of file) So I beg you may use some easier format to read, or just do some string search to the property you need, without using DOM.
You can read a file at first scan, but as file operations are asynchronous (takes more than one task cycle), you need to add some code to block the execution requiring the variable to be correctly initialized.
What is the database size ? Depending on the requests you do, if the database is growing over time, that may explain some not rolled back issue.
Feels like endiantness issue between your 2 systems. Try word swaping and/or byte swaping. With A=15,B=8E,C=41,D=00 Result shown by your screenshot is Little Endian, DCBA. I bet you expect 8.005262, which is Mid-Little Endian, CDAB (just byte swaping, in each words). More tries here : https://www.scadacore.com/tools/programming-calculators/online-hex-converter/
Feels like endiantness issue between your 2 systems. Try word swaping and/or byte swaping. With A=15,B=8E,C=41,D=00 Result shown by your screenshot is Little Endian, DCBA. I bet you expect 8.005262, which is Mid-Little Endian, CDAB. More tries here : https://www.scadacore.com/tools/programming-calculators/online-hex-converter/
I feel like your actual problem has nothing to do with your topic title. It may be better for search purpose to split the topic. Anyway, your problem is more some generic code thinking related issue. If your car is crashed because it went too fast on ice, it shouldn't be "not crashed" because it lowers its speed (feels like it usually happens when you crash your car). So you must decide what is the behavior of the crashed property of your car (does it stays at TRUE forever once a crash occured ?...
What about using the JSON lib ? https://forge.codesys.com/lib/pro-json/home/Home/
As said by the console, it seems that you are calling a "Controller_PID" functionBlock, using an instance of type "Ctrl.Controller_PID". Codesys obviously won't compile because the two types doesn't match. Try setting your type to Controller_PID, or change the type of the functionblock call to Ctrl.Controller_PID. Regards, dFx
What about zeroing your buffer once you copied it (TCPRead2_MessageRX) ?
Though that having a COM port on your hardware was a requirement already met.
Though that having a COM port on your hardware was so requirement already met.
The library is installed with codesys when you install it. There is no need to browse for it, either to install it separatly. Just add it to your library manager, into your project.
Right clic your device in HW tree, then add the modbus master or device. Also, please make your own search before posting : https://help.codesys.com/webapp/_cds_adding_libraries_to_project;product=codesys;version=3.5.17.0
Some help on modbus configuration : https://help.codesys.com/webapp/_mod_f_configurator;product=core_modbus_configuration_editor;version=3.5.14.0 Some libs : Master : https://help.codesys.com/webapp/idx-IoDrvModbus-lib;product=IoDrvModbus;version=3.5.17.0 Slave : https://help.codesys.com/webapp/idx-IoDrvModbusSerialSlave-lib;product=IoDrvModbusSerialSlave;version=3.5.17.0
What is your oscat net lib version ? What is the name of the block returning the error ? DLOG_STORE_FILE_CSV ? What is your hardware ? Network lib is a codesys 2 lib AFAIK. May be the issue is from the port ? OSCAT forum's may be a more suitable place for your request.
Did you had a look at the store ? For instance, there's an SQL framework that may suit well your needs. https://store.codesys.com/sql4codesys.html?___store=en
Just have a look at driver's help inside SCADA Expert. You will have some addressing exemples. Regards, dFx
https://forge.codesys.com/forge/talk/Runtime/thread/fa7a703b16/?limit=250#d388
10ms is quite unusually fast even for a web gif image targeting a standard PC. So I wouldn't expect it to perform great on a panel (that is basically a very low end pc) running with 256MB of RAM on a ARM Cortex-A8 - 600 MHz. With such specs, I would not expect more refresh than twice a second on a very empty page.
Isn't IP address handled by the ethernet adapter rather than the protocol ? Did you had a look at IoDrvEthernet ? https://help.codesys.com/webapp/idx-IoDrvEthernet-lib;product=IoDrvEthernet;version=3.5.14.0
What about https://help.codesys.com/webapp/yePjxWIB36goBg4qOqNVpO-2vmA%2FGetDeviceState;product=IoDrvModbus;version=3.5.16.0 About the behavior, it may be something related with your request rate, but I can't help much.
Feels like some nerdish code writing style. String is no more than a byte array. With this in mind, to get the same length than the word array, you need to double the word array length. You could define string(250) and it would also work. Actually as 125x2 is a constant, it is probable that the compiler will just compile the same.
Feels like some nerdish code writing style. String is no more than a byte array. With this in mind, to get the same length than the word array, you need to double the word array length. You could define string(250) and it would also work.
Real to dword tries to PUT the real value inside a dword value, meaning it is trying to get the same values on your two variables. So, if the real value is outside the dword value range, this will produce an error. Online help states : If the operand value for a type conversion operator is outside of the value range of the target data type, then the result output depends on the processor type and is therefore undefined. This is the case, for example, when a negative operand value is converted from...
I don't know about LENZE, but FESTO is acting in a similar way. They have 2 libs for motion. The first one is using their standard, and does not comply with PLC OPEN blocks. The second, uses PLC OPEN. Maybe LENZE provides the same. If not, then you will have to manage this like the old school way, using control word and status word. Or may be that's already the purpose of their lib. About units and scaling, you should be able to do it in the drive, and if you need it done at runtime, then you really...
Real to dword tries to PUT the real value inside a dword value, meaning it is trying to get the same values on your two variables. So, if the real value is outside the dword value range, this will produce an error. Online help states : If the operand value for a type conversion operator is outside of the value range of the target data type, then the result output depends on the processor type and is therefore undefined. This is the case, for example, when a negative operand value is converted from...
Real to dword tries to PUT the real value inside a dword value, meaning it is trying to get the same values on your two variables. So, if the real value is outside the dword value range, this will produce an error. Online help states : If the operand value for a type conversion operator is outside of the value range of the target data type, then the result output depends on the processor type and is therefore undefined. This is the case, for example, when a negative operand value is converted from...
If you communicate in EIP, then you have a gateway between IO-Link and EIP. The way you should read/write IO-Link data depends on your device. Just download the EIP manual of it, take a comfy chair and start reading.