HotLoop Transmitter
HotLoop Transmitter puts a PLC’s values on the network as OPC UA PubSub, the way Part 14 of the OPC UA spec says to, from a library you drop into the CODESYS project. It is a transmitter in the instrument-loop sense: the part that puts the process value on the wire so something else can read it.
It is written in Structured Text over SysSocket UDP, and it needs no other library, no extra license, and no
configurator. You add the library, call one function block once per cycle, and a UADP NetworkMessage goes out every
publishing interval to a unicast address or a multicast group.
What that means for you: a PLC that has no PubSub library can still feed anything that subscribes to OPC UA PubSub,
including HotLoop itself, with a few lines of Structured Text. Every message carries a timestamp from the PLC’s clock
unless you switch it off with bTimestamp.
Why this is Structured Text and not Go
Section titled “Why this is Structured Text and not Go”Every new HotLoop tool is written in Go unless there is a real reason. This is the real reason: the thing has to run inside the PLC’s own scan, in the IEC 61131-3 runtime, as a library the programmer references from their project. A CODESYS runtime runs Structured Text, not Go. The tests and tools around the library (the capture tool, the verifier) are Go.
Use it
Section titled “Use it”- Install
HotLoopTransmitter-1.1.0.libraryinto the CODESYS library repository (Tools, Library Repository, Install), or installHotLoopTransmitter-1.1.0.packagewith the CODESYS Installer, then add it to the project’s Library Manager. The install page has the downloads and the details. - Declare a publisher, add the variables you want to publish once at start, and call it every cycle:
PROGRAM PLC_PRGVAR pub : HLTX.FB_HLTX_Publisher; bInit : BOOL;END_VAR
IF NOT bInit THEN bInit := TRUE; pub.sDestination := '239.0.0.22'; // a unicast host or a multicast group pub.uiPort := 4840; pub.uiPublisherId := 1; pub.uiWriterGroupId := 1; pub.uiDataSetWriterId := 1; pub.tPublishingInterval := T#100MS; pub.AddReal(ADR(GVL.rTemperature)); pub.AddBool(ADR(GVL.bRunning)); pub.AddArray(ADR(GVL.aValues), HLTX.E_HLTX_Type.REAL_T, 250);END_IFpub.bEnable := TRUE;pub();The API page lists every input, output and method. The wire format page is the packet, byte by byte, with the sections of the spec that define each byte.
What it will and won’t do to your scan
Section titled “What it will and won’t do to your scan”- It never blocks. The socket is non-blocking and the message is built in a fixed buffer.
- The cost of a call is the cost of building one message, and it is only paid on the cycles where a message goes out. Measured on a 20 ms task with two publishers and timestamps on: about 9.6 us added per cycle on average, 10 to 100 us on the cycles that send, and the longest cycle in the run 81 us. A busy host has stretched a single send to milliseconds. The measured numbers and their limits are in the timing page.
- A socket error, a bad address or an oversized field list never faults the application. The block reports an
eStateand aneError, counts the failure, and the program keeps scanning. - It does not fragment. A message is at most 1472 bytes. A field list that does not fit puts the block in
ConfigErrorand sends nothing.
Tested against
Section titled “Tested against”The CODESYS Control for Linux SL 4.22.0.0 runtime, in a container. See the timing page and the proof page for what was run and what was read back. Not run on physical hardware.
License
Section titled “License”HotLoop’s Business Source License 1.1, the same as every HotLoop product. The license page has the text.