Search talk: 0

 
<< < 1 .. 12 13 14 15 16 17 > >> (Page 14 of 17)

Post by elsmart on Sequential read and triggering of Modbs RTU channels in application CODESYS Forge talk (Post)
Hello I need some help understanding how to use Modbus RTU (COM port) in Codesys enviroment. I defined a Modbus Server device (slave) in device tree and added some channels to read from (function 3). Also I set trigering mode to Application. I have a POU in which I want to trigger each channel one after the other something like this (C code for better visualisation): for (int i = 0; i < channelsCount; i++) { triggerChannel(channelsArray[i]); // Start transmission while(channel.xBusy); // Wait for transmission to complete } I have found ModbusChannel function block documentation but examples are scarce. I don't understand how rising edge triggering works. What would be the best solution for achieving sequntial channel triggering? What is the common way to read multiple Modbus channels once every time a specified POU is executed?
Last updated: 2025-05-16

Post by levih on FbHTTPs_Get how to get data from a website and use it in codesys CODESYS Forge talk (Post)
You get an array of DWORD into your receive buffer. You need to process this into usable data, before you can fit it into your DUT. I've made it work using FbWrite_ToIEC_ByRule in stead of Fb_JSON_ParseAndModify. I've attached images of the code. You receive the data into ARRAY[0..1023] OF DWORD. Then you use that array as the input for fbWrite_ToIEC_ByRule. To get the output from this you define a rule to fit the expected data structure including nesting levels. The you feed the rule into FbWrite_ToIEC_ByRule and then you can set the output to be of your DUT type.
Last updated: 2025-06-16

Post by hclai on Maximum Array Index Issue CODESYS Forge talk (Post)
I was trying to use a table object in visualization. I want to dynamically show the valid rows in the table. However, it does not work when there is 1 row. i put the maximum array index to 1. it does not show the 1st row. when i change to 2, it show the second row only. my project with older visualization profile version is working perfectly fine. I did some test and realized that i must use a Row Selection variable to change from 0 to 1. With this change of Row selection, then the row 1 will show up.
Last updated: 2025-06-19

Post by buczekj on About CPU Loading CODESYS Forge talk (Post)
This is a phenomenon that I have seen myself and with others. Texas instruments wrote an application note with this same issue. They noted with Codesys 3.5.19.10, that selecting CPU 1 as the EtherCAT task showed CPU spiking improvements over the performance of cores 0, 2, and 3. It appears to be linked to EtherCAT, are you configuring for use with distributed clocks? If so, I recommend choosing the 'Based on Input Reference' option. I have found it to reduce the CPU usage spike maximum slightly (see attached). See link to TI (also attached in case link breaks) https://www.ti.com/lit/an/spradh0/spradh0.pdf?ts=1723546111357
Last updated: 2025-07-01

Post by kporter on High-resolution drive with SoftMotion CODESYS Forge talk (Post)
I'm beta-testing a new EtherCAT drive for a rotary (modulo) axis in a system where the encoder resolution is 81920000 counts per rotation. If I enter this in the SoftMotion Scaling/Mapping tab for "increments <=> motor turns", I get the error below on the Commissioning tab. Is SM unable to handle a high-resolution encoder? The bus cycle is currently set to the default of 4 msec (Control Win V3 x64), although I plan to reduce that to reduce latency, possibly by switching to the realtime (RT) master. Is SoftMotion incompatible with high-resolution encoders? SMC_CGR_INVALID_POSPERIOD Invalid modulo period (<= 0 or greater than half the bus bandwidth)
Last updated: 2025-08-25

Post by sumit on Remote Ethernet/ip Adapter communication with scanner running on codesys CODESYS Forge talk (Post)
Hello there, I have my ethernet/ip adapter (from Texas Instrument) running on Texas Instrument Board and I have configured the scanner on codesys. I have mapped the I/Os and I can see (on wireshark) the frames coming from adapter but I don't see my input variables in scanner get updated, they just stay at 0. I wanted to see the real data that has been sent from adapter to scanner on codesys. I am not sure if the problem is in I/O mapping or there is a step/s that I have missed. I have attached the screenshot of my project for your ref. Thank you, Sumit
Last updated: 2023-12-15

Post by sumit on Remote Ethernet/ip Adapter communication with scanner running on codesys CODESYS Forge talk (Post)
Hello there, I have my ethernet/ip adapter (from Texas Instrument) running on Texas Instrument Board and I have configured the scanner on codesys. I have mapped the I/Os and I can see (on wireshark) the frames coming from adapter but I don't see my input variables in scanner get updated, they just stay at 0. I wanted to see the real data that has been sent from adapter to scanner on codesys. I am not sure if the problem is in I/O mapping or there is a step/s that I have missed. I have attached the screenshot of my project for your ref. Thank you, Sumit
Last updated: 2023-12-15

Post by jeroen on Ramp function CODESYS Forge talk (Post)
Hi, Found a nice ramp function in the OSCAT lib (FT_RMP), but is there a nice way to 'set' the output to the current input as form of a reset. The reason for this, is that I want to set up a ramp for a pressure control input that should have x Bar/sec linear rise input. The only option (or code it by hand) I found is this OSCAT FB. Any other options? Just need to increase a value by x Bar/sec from let's say 250Bar (as start) to end 1500Bar. The Oscat ramp will always start at 0 when enable is off (FT_RMP.Rmp := FALSE)
Last updated: 2024-01-09

Post by matt-s on HMI Pushbutton/Move Instruction CODESYS Forge talk (Post)
I am having an issue where the manual start/stop push buttons on the HMI are supposed to take the pumps/blowers out of auto. The logic I have attached works for the pumps, but not the blower. From what I can tell it is the exact same logic, but it is not writing a 0 to the Auto PB variable. Attached is the logic, cross reference list to show nothing else is writing to it, and the HMI screen. Any help? Am I missing something? I am using a Groov Epic PR1, my software version is 3.5 SP19 Patch 5 32 Bit.
Last updated: 2024-01-25

Post by alexgooi on Is it possible in the log to see previous shutdown CODESYS Forge talk (Post)
Hi DavidBo, In general Codesys is used to control equipment and an exception is the worst thing that can happen in your installation. If you cannot prevent the exception from triggering, you could implement a Try catch statement, with this solution your controller keeps on running and you are able to handle the exception. __TRY //This statement will trigger an exception Result := 4/0; __CATCH(exc) //Handle the exception HandleException(exc, strExceptionText => strExceptionText); // From the Codesys help file //Create a log file //-------------------------------------------------------- __ENDTRY What you also could do is implement implicit checks, these functions cover most of the exceptions (like dividing by zero) See picture But in general avoid a complete controller shutdown!
Last updated: 2024-02-09

Post by comingback4u on Memory Address Overlap CODESYS Forge talk (Post)
Hello, We use a controller that comes with a bunch of predefined faults. These faults are considered active and historic. They are a 32 byte array but only take up 26 bytes of data. Because of this the historic faults start at address 26 instead of 31. Active faults variable take up address location 0 to 31. Historic faults variable take up address location 26 to 57. Because of this overlap I get an error that these overlap and it wont allow me to download to my controller. This isn't an issue in 3.5.5.4 but becomes an issue in newer version. Is there a way to turn this off? If I change the address location, the historic faults then become broken without doing some manipulation in the code. The software will build just fine. Thank you for your time.
Last updated: 2024-03-07

Post by wollvieh on Raspi Pi Bullseye Webvisu Autostart CODESYS Forge talk (Post)
Anbei meine Lösung zum Autostart der Webvisu, vllt. hilft es jemandem... =============================== Raspberry Pi Bullseye 11 Autostart Codesys Webvisu im Kiosk Mode 1)Datei erstellen: sudo nano/etc/xdg/autostart/Visustart.desktop 2)Inhalt der Datei: [Desktop Entry] Type=Application Name=Visustart Exec=bash -c "sleep 30 && /home/pi/Desktop/Visu" 3)Visu Datei erstellen sudo nano /home/pi/Desktop/Visu 4) Inhalt der Datei: #!/bin/sh xset -dpms xset s off xset s noblank matchbox-window-manager -use_titlebar no & unclutter & chromium-browser -display=:0 --kiosk --incognito --window-positon=0,0 5) Datei ausführbar machen sudo chmod+x /home/pi/Desktop/Visu ... nach Neustart Raspi startet die Codesys Webvisu automatisch im Kiosk Mode ===============================
Last updated: 2024-03-24

Post by wollvieh on Raspi Pi Bullseye Webvisu Autostart CODESYS Forge talk (Post)
Anbei meine Lösung zum Autostart der Webvisu, vllt. hilft es jemandem... =============================== Raspberry Pi Bullseye 11 Autostart Codesys Webvisu im Kiosk Mode 1)Datei erstellen: sudo nano/etc/xdg/autostart/Visustart.desktop 2)Inhalt der Datei: [Desktop Entry] Type=Application Name=Visustart Exec=bash -c "sleep 30 && /home/pi/Desktop/Visu" 3)Visu Datei erstellen sudo nano /home/pi/Desktop/Visu 4) Inhalt der Datei: #!/bin/sh xset -dpms xset s off xset s noblank matchbox-window-manager -use_titlebar no & unclutter & chromium-browser -display=:0 --kiosk --incognito --window-positon=0,0 5) Datei ausführbar machen sudo chmod+x /home/pi/Desktop/Visu ... nach Neustart Raspi startet die Codesys Webvisu automatisch im Kiosk Mode ===============================
Last updated: 2024-03-24

Post by alexgooi on Modbus writing on value change CODESYS Forge talk (Post)
The way I usally tackle this is by syncing only words (then you are able to use the FB above). If you then want to write a Boolean simply type it like this. Value[1].0 := Bool1; Value[1].1 := Bool2; Value[1].2 := Bool3; Uints have the same number of bits than a INT/WORD so these ones will work as well (they are only represented diffrently). A Real will work but you will loose some infomration in the conversion. If you want to keep the information you can convert 2 words to a float with a function (for example with the IEEE-754 standard) . In this way the syncing to the server is very simple and in the Codesys Program you decide what part of the word you want to use.
Last updated: 2024-04-03

Post by rau00 on Touch Probe 0x60B8 writting CODESYS Forge talk (Post)
Hi erveyone, Rau here, first time asking on CODESYS Forge: When working with my servodrives, a special behaviour is required on dsp402 0x60B8 object, a control that is not supported by MC_TouchProbe. For this reason, I'd like to ask: Anyone knows if there is any way to bypass or change the softmotion axis writting into 0x60B8 object? My main problem is that MC_TouchProbe.TriggerInput.iTriggerNumber only allows to choose between TP 1 and TP 2 (not both at the same time). iTriggerNumber only allows values [0, 1, 2, 3], other values triggers an error in the FB, wether SMC_TP_COMM_ERROR for values [4, 5, 6, 7] and SMC_TRIGGER_OUT_OF_RANGE with any other value. Best regards, Guillem
Last updated: 2026-04-10

Post by reinier-geers on internal error CODESYS Forge talk (Post)
Hi ive got an internal error. BUt no solution for this. How do i solve this ? ------ Build started: Application: Slave_3.Application ------- [ERROR] Internal error:System.NullReferenceException: De objectverwijzing is niet op een exemplaar van een object ingesteld. bij _3S.CoDeSys.ObjectManager.ExistingPSNode.get_ParentObjectGuid() bij _3S.CoDeSys.ObjectManager.AbstractPSNode.get_ParentNode() bij _3S.CoDeSys.ObjectManager.ProjectStructure.ConsolidateAndClearPendingChanges(LList`1 pendingChanges) bij _3S.CoDeSys.ObjectManager.ProjectStructure.RaisePendingChanges(Boolean bTriggerPendingChanges2) bij _3S.CoDeSys.ObjectManager.Project.HandleUndoMgrAfterEndCompoundAction2(EventArgs e) bij _3S.CoDeSys.ObjectManager.UndoManager.OnAfterEndCompoundAction2(EventArgs e) bij _3S.CoDeSys.ObjectManager.UndoManager.EndCompoundAction() bij _3S.CoDeSys.DeviceEditorSoftMotion.StaticSoftMotionEditor._ehBeforeCompile(Object sender, CompileEventArgs e) bij _3S.CoDeSys.Core.LanguageModel.CompileEventHandler.Invoke(Object sender, CompileEventArgs e) bij _3S.CoDeSys.Core.LanguageModel.CompileEventHandler.Invoke(Object sender, CompileEventArgs e) bij _3S.CoDeSys.LanguageModelManager.LanguageModelManagerConsolidated.OnBeforeCompile(CompileEventArgs e) bij _3S.CoDeSys.LanguageModelManager.LanguageModelManagerConsolidated.RaiseAndCheckBeforeCompile(Guid guidApplication, IMessageCategory cmc) bij ..(Boolean , Boolean , Boolean ) bij _3S.CoDeSys.Compiler35210.CompilerPhases.CompilerPhaseControllerGenerateCode.(Boolean ) bij _3S.CoDeSys.Compiler35210.CompilerPhases.CompilerPhaseControllerGenerateCode.() Build complete -- 1 errors, 0 warnings : No download possible
Last updated: 2026-04-14

Post by polo on 1 Wire und i2c zeitgleich in Betrieb CODESYS Forge talk (Post)
Hallo zusammen, ich habe schon einige Zeit 16 DS18B20 am 1 Wire laufen ... auch die ganze Zeit stabil ... jetzt habe ich ein PWM Signal über i2c für eine Pumpenansteuerung zusätzlich in Betrieb genommen.. nur das Signal für die Pumpe geht über i2C ... 100Hz 10ms. Es läuft auch alles soweit ... nur fallen mir jetzt die Temperaturen in Abständen aus ... Vertragen sich die beiden Systeme zeitlich evtl. nicht so gut ... 1 wire extra task mit 200ms Prio 0 i2c task 10ms ... damit die 100Hz auch übertragen werden Prio 1 (Adafruit_PWM) Main Task 20ms Prio 5 Oder jetzt besser beides über i2c abrufen ... ist aber dann evtl. für die DS18B20 zu schnell ? Oder sind die 5V vom Pi jetzt zu schwach für beide Signale? Vielen Dank euch
Last updated: 2026-04-27

Post by thommy54 on Raspi-Cam: CameraStream.project nicht zum Laufen zu bringen CODESYS Forge talk (Post)
Hallo, Ich bringe das CameraStream.project nicht zum Laufen. Ich sehe die Ursache darin, das das Beispielprogramm sehr sparsam mit Programm-Kommentaren umgeht (von der Hilfe gar nicht zu reden). Ich habe beide Varianten bei der zu ändernden Zielvariable getestet: //copy video.htm to the webserver; //the location of the webserver depends on the used Apache version as mentioned in online help hDirHtmlTest:=SysDirOpen( szDir:='/var/www', pDirInfo:= ADR(dirInfo), diMaxDirEntry:=iMaxDirEntry, szDirEntry:=szDirEntry, pResult:=ADR(iDirHtmlError)); IF (iDirHtmlError = 0) THEN SysDirClose(hDir:=hDirHtmlTest); SysFileCopy('/var/www/video.htm', '$$PlcLogic$$/Application/video.htm', ADR(dwCopySize)); ELSE .... als auch hDirHtmlTest:=SysDirOpen( szDir:='/var/www/html', pDirInfo:= ADR(dirInfo), diMaxDirEntry:=iMaxDirEntry, szDirEntry:=szDirEntry, pResult:=ADR(iDirHtmlError)); IF (iDirHtmlError = 0) THEN SysDirClose(hDir:=hDirHtmlTest); SysFileCopy('/var/www/html/video.htm', '$$PlcLogic$$/Application/video.htm', ADR(dwCopySize)); ELSE .... Die Url-Streams habe ich gelassen wie sie vorgegeben waren: urlStream := CONCAT('http://', CONCAT(sIPAddress, '/video.htm')); urlPicture := CONCAT('http://', CONCAT(sIPAddress, '/cam_pic.php')); In der Webvisu im Browser komme ich maximal dahin wie im Screeshot Video_Visu_1 zu sehen. Also scheint der Link zu video.htm zu klappen. Das der zu cam_pic.php nicht klappt, wundert mich nicht, denn es existiert nicht und wird auch nicht evtl. am rechten Ort angelegt. Ich bin mir vollkommen im Unklaren: muss da was auf dem Raspberry Pi im Hintergrund laufen , z.B. raspivid . Welcher Programmteil bedient die Cam ? Ich erkenne auch nicht, wo ein einzelnes picture entstehen soll. Wäre dankbar, wenn ich hier etwas Hilfe bekommen könnte. Evtl. gibt es Probleme mit der von mir verwendeten Codesys-Version 3.5.20.1 ? Ich benutze einen Raspberry 4 Rev.1.2. Grüße Thomas
Last updated: 2024-07-04

Post by youness on No source code available (cip object) CODESYS Forge talk (Post)
Hi yotaro, hope your problem was resolved. I had the same, but with an other library title. This exception is not detected during compilation, but rather at a given position in the program (when switching to a given visualization). Although the exception is generated at this point, it does not involve the visualization in question. This error is due to one of 3 reasons: 1) A division by zero somewhere: The program is able to detect divisions by zero at compile time. But in the case of a variable, which takes a valid value at init and changes to 0 at a later stage. 2) An invalid pointer: (either because it has a value of 0, or because it points outside the memory reserved for the program) is being dereferenced. Locate any pointers or interfaces you have in the code and check them - you should also be wary of mixing inline modifications and pointers. 3) Array overflow: Generally when a processing operation is executed outside the array's definition range. Example: a write loop with n iterations is executed on an array of dimmension n-1. On the other hand, the error message may not appear. In the latter case, the error may have fatal consequences, as the overflow has induced writing to potentially forbidden memory areas. This problem can be explained by the fact that it's not always the adjacent memory areas of PLC_PRG that are overwritten, but the memory areas that are randomly allocated to the array during compilation. In this case, however, there is no entry in the log, so you need to integrate the "Implicit Check function", which checks the line of code generating the error. To integrate this functions, click on Application --> POU for implicit controls Regards,
Last updated: 2024-07-16

Post by paulpotat on cm4 runtime problem CODESYS Forge talk (Post)
Hello, I have exactly the same issue, with the following configuration : Hardware version >>> cat /proc/cpuinfo processor : 0 model name : ARMv7 Processor rev 3 (v7l) BogoMIPS : 108.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3 processor : 1 model name : ARMv7 Processor rev 3 (v7l) BogoMIPS : 108.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3 processor : 2 model name : ARMv7 Processor rev 3 (v7l) BogoMIPS : 108.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3 processor : 3 model name : ARMv7 Processor rev 3 (v7l) BogoMIPS : 108.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3 Hardware : BCM2711 Revision : a03141 Serial : 10000000d5be5b5f Model : Raspberry Pi Compute Module 4 Rev 1.1 Kernel version >>> uname -a Linux raspberrypi 6.1.21-v7l+ #1642 SMP Mon Apr 3 17:22:30 BST 2023 armv7l GNU/Linux OS Version >>> cat /etc/os-release PRETTY_NAME="Raspbian GNU/Linux 11 (bullseye)" NAME="Raspbian GNU/Linux" VERSION_ID="11" VERSION="11 (bullseye)" VERSION_CODENAME=bullseye ID=raspbian ID_LIKE=debian HOME_URL="http://www.raspbian.org/" SUPPORT_URL="http://www.raspbian.org/RaspbianForums" BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs" /boot/config.txt I added the following line : arm_64bit=0 CodeSys runtime version 4.10 Were you able to solve the issue @michelebianchi ? Any help with this would be appreciated... BR
Last updated: 2024-08-28

Post by elektron785 on GPIO mit Codesys Virtual Control for Linux ARM64 SL CODESYS Forge talk (Post)
Hallo zusammen, ich möchte an einem Entwicklungsboard auf dem der i.MX 8M Plus von NXP aufgesteckt ist die vier zur Verfügung gestellten GPIOs als Ausgänge verwenden. Ich habe mir dazu die Readme-Datei des GPIO-Beispiels von "C:\Program Files\CODESYS 3.5.20.40\CODESYS\CODESYS Control SL Extension Package\4.14.0.0\Examples\GPIO" angeschaut Die Übersicht der verfügbaren GPIOs sieht folgendermaßen aus - wobei ich das auf die reduziert habe, die für mich von Interesse sind: gpiochip0: GPIOs 0-31, parent: platform/30200000.gpio, 30200000.gpio: gpio-0 (SODIMM206 ) gpio-1 (SODIMM208 ) gpio-2 ( ) gpio-3 ( ) gpio-4 ( |sd-vsel ) out hi gpio-5 (SODIMM210 ) gpio-6 (SODIMM212 ) gpio-7 (SODIMM216 ) gpio-8 (SODIMM218 ) gpio-9 ( ) gpio-10 ( ) gpio-11 (SODIMM16 ) gpio-12 (SODIMM155 |regulator-usb1-vbus ) out lo gpio-13 (SODIMM157 ) gpio-14 (SODIMM185 |regulator-usb2-vbus ) out hi gpio-15 (SODIMM91 )** Füge ich nun das GPIO (1 Bit)-Gerät in meinem Codesys-Programm hinzu funktioniert der Bus solange bis ich die Richtung in den GPIO-Parametern von "not used" auf "Output" stelle (siehe Bild gpio_parameter). Dann funktioniert nach Download der Bus nicht mehr. Gibt es noch eine andere Möglichkeit das zu steuern oder muss ich noch Einstellungen tätigen? Für die Zeile mit dem echo (export/unexport) aus dem Beispiel fehlen mir trotz sudo die Zugriffsrechte. "The Kernel Linux has deprecated GPIO user space SysFS. However, the kernel config CONFIGGPIOSYSFS is still enabled on Toradex's BSP to support customers using it in their legacy applications. You can check the configuration by running zcat /proc/config.gz | grep CONFIGGPIOSYSFS. For GPIO access from userspace, the new char device API, also known as libgpiod, must be used." Dies steht in der Verwendung der GPIOs - eine Ausführung des zcat-Kommandos liefert ein =y zurück.
Last updated: 2025-03-17

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 alessandro on SysMemCmp SysMemCpy CODESYS Forge talk (Post)
VAR Data1:ARRAY[1..10] OF SINT ; Data2:ARRAY[1..10] OF SINT ; Data3:ARRAY[1..10] OF SINT ; Data4:ARRAY[1..10] OF SINT ; ex_1 : BOOL ; ex_2 : BOOL ; enable : BOOL :=0 ; END_VAR // PROGRAM // The scope of this example is compare and copy the values of two ARRAY only if some value is different using SysMemCmp and SysMemCpy. // In this 2 example we don't use a FOR cicle for do this, and pBuffer1 and pBuffer2 is just a pointer to ARRAY. See details in Library util.SysMem of Codesys // The compare funcion util.SysMem.SysMemCmp is bidirectional if Data1 chanege respect Data2 ex_1 go to 1 and if Data2 change respect Data1 also // but the copy function util.SysMem.SysMemCpy work only from source ARRAY pSrc:=ADR(Data1) to destination ARRAY pDest:=ADR(Data2) // Example 1 Full ARRAY compare and copy // This compare 2 different equal ARRAY and if there is some difference ex_1 go to 1 and if you give enable he copy Data1 in Data2 ex_1 := TO_BOOL(util.SysMem.SysMemCmp(pBuffer1:=ADR(Data1), pBuffer2:=ADR(Data2), udiCount:=SIZEOF(Data1))); IF ex_1 AND enable THEN util.SysMem.SysMemCpy(pDest:=ADR(Data2), pSrc:=ADR(Data1), udiCount:=SIZEOF(Data1)); END_IF // Example 2 Only selected area of the ARRAY compare and copy // This compare 2 different equal ARRAY starting from position number [3] for 4 byte in this case start at position [3] and finish at position number [6] // and if there is some difference only in area [3..6] of the ARRAY ex_2 go to 1 if you give enalbe he copy Data3[3..6] in Data4[3..6] // if something change in other array position[0..2] or [7..10] are ingnored ex_2 := TO_BOOL(util.SysMem.SysMemCmp(pBuffer1:=ADR(Data3[3]), pBuffer2:=ADR(Data4[3]), udiCount:=4)); IF ex_2 AND enable THEN util.SysMem.SysMemCpy(pDest:=ADR(Data4[3]), pSrc:=ADR(Data3[3]), udiCount:=4); END_IF // Attention udiCount input is intended in <byte> in the example 1 I pass to udiCount:=SIZEOF(Data1) for compare and copy the intere ARRAY and // SIZEOF pass the size of intere ARRAY in byte to the function input, in this 2 examples I used variable type SINT each one occupie 1 byte and one position in the ARRAY // and in the example 2 I pass udiCount:=4 for compare and copy only 4 position of Data3/4[3..6] if you want to extend this example and use it for an ARRAY OF WORD // remember that each WORD will occupe 2 byte (16 bit) and you will have to pass udiCount:=SIZEOF(Data1) if you need to compare intere ARRAY example 1 // but need udiCount:=(42) for the example 2 because need to compare and copy 4 word each occupie 2 byte (16 bit). // For REAL (32 bit) need udiCount:=SIZEOF(44) for LREAL or (64 bit) need udiCount:=SIZEOF(416) // a good rule is calculate the dimension of the ARRAY in byte without empty space at the end, multiple of data type number for variable bigger then 8 bit // Example : If you want to create an ARRAY for 5 REAL (32 bit) each occupie 4 byte the correct size is ARRAY[0..19] OF REAL 54=20 position. // NOTE : In the example the position of compare function util.SysMem.SysMemCmp is first and the copy function util.SysMem.SysMemCpy inside the IF is after // in one cycle of the program the two array is compared and if there is some difference and enable are copied. // If you move util.SysMem.SysMemCmp after the IF cycle he will copare the ARRAY in the current cycle but the copy of the value will do in the next cycle.</byte>
Last updated: 2025-10-24

Post by dantheman on Connecting to SoftPLC Only Works By Turning Off Modbus Ethernet Port CODESYS Forge talk (Post)
I have an IPC with 2 ethernet ports and 1 Wi-Fi. I'm using ModbusTCP with the ethernet port named "enp2s0" connected to my remote I/O. This works fine when testing with Python and also works with CODESYS, but CODESYS is only able to scan for the Linux SoftPLC when I turn off the "enp2s0" interface. In other words, I can't get online with the IDE if I want my ModbusTCP comms to run with CODESYS. I'm using a Linux SoftPLC that has the following entry in CODESYSControl.cfg, hoping that this will allow me to connect with "enp1s0" or "wlp3s0", and leave "enp2s0" for field comms, but this seems to only make the source IP of the ModbusTCP comms to be bound to "enp2s0". That last point is the case only if I don't restart the service, but if I do restart the service after changing the config file, the source IP for the ModbusTCP comms then becomes the one for "enp1s0", which is very confusing to me: [SysSocket] Adapter.0.Name="enp2s0" Adapter.0.EnableSetIpAndMask=1 On the device list, I only have "enp2s0" given as the ethernet device that has the ModbusTCP master & slave beneath it, shown in Screenshot 1. On the IPC, I can ping the ModbusTCP client (remote I/O) from "enp2s0", and I've attached a Wireshark capture of running ModbusTCP from the CODESYS runtime as Screenshot 2, 3 & 4 (again, I can't get online when this is running, I have to turn off "enp2s0" to connect even when it's idle and I don't have an active TCP session with my Python tests). Like I explained above, the source IP is "enp1s0", even though the ethernet device on the project is "enp2s0". I was lucky to catch the red message that showed the source IP that makes sense to me (the one for "enp2s0"), but for some reason that connection was reset and I never saw that packet again. I've also tried this with Auto-reconnect both enabled & disabled, for the ModbusTCP Master device. I also have to turn off "enp1s0" and then turn it on, just so that I can have the ModbusTCP comms running from "enp2s0" (which is not intuitive in any way to me, I'd love some help understanding that phenomenon as well) in the weird manner that I've described above. I would be very appreciative if someone can help me figure out this pickle. I'd love to just connect to CODESYS through my Wi-Fi interface and leave my ethernet ports for field comms.
Last updated: 2024-08-01

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

<< < 1 .. 12 13 14 15 16 17 > >> (Page 14 of 17)

Showing results of 414

Sort by relevance or date