Set up an OPC UA server in CODESYS for HMI clients

8 min read · Published November 2, 2026

The CODESYS runtime includes an OPC UA server. Turn it on, publish the tags the HMI needs through a symbol configuration, and any standard client connects on TCP port 4840. This page walks the whole server side: address, endpoint URL, certificate trust, and subscription rates that keep a small controller responsive.

An HMI for a CODESYS controller does not need a vendor driver. The runtime carries an OPC UA server component. Switch it on, publish tags through a symbol configuration, and any standard client connects over binary TCP on port 4840: a panel HMI, a desktop SCADA package or your own app. The integration job becomes tag selection. This page walks the server side end to end: what the runtime must include, how to publish variables, the endpoint URL, the certificate trade on first contact, update rates that keep a small controller fast, and the checks that prove the path before the HMI project starts.

What does the built-in OPC UA server give you?

The runtime ships with an OPC UA server component. It publishes whatever you tick in a symbol configuration, on binary TCP port 4840 by default, to any standard client. CODESYS includes it as a restricted build in the application-based runtime licenses with no extra license fee. What that buys you is vendor-neutral access. The same endpoint serves a panel on the machine, a SCADA client in the control room and a tablet app during commissioning, each with its own session. The controller stops being the property of one HMI vendor, and swapping the client touches nothing on the PLC side. CODESYS documents the restricted server version as included in every application-based license without an additional fee. Confirm your runtime package carries the component before you freeze the design, and treat the number of simultaneous client sessions as part of that same package question.

What do you need before you start?

You need a CODESYS runtime package that includes the OPC UA server, a fixed IPv4 address for the controller, the CODESYS Development System on your engineering PC, and one generic OPC UA browse client on a separate machine for testing.

  • A controller running a runtime package with the OPC UA server, reachable from the engineering PC.
  • A fixed IPv4 address, static or a DHCP reservation. The address is part of the endpoint URL, so a lease that changes on renewal breaks every client. Verify it survives a power cycle.
  • The CODESYS Development System on the engineering PC, able to scan for the target and log in.
  • One generic OPC UA browse client, installed on a machine other than the final HMI. It separates server problems from HMI configuration problems.
  • A firewall rule allowing TCP 4840 from the client subnet to the controller, open on every hop.
  • A written tag list for the HMI: name, type, access, and which screen uses each tag.

How do you publish PLC variables through a symbol configuration?

Add a symbol configuration object to the application, build the project once so the variable list populates, then tick only what the HMI needs: two structures of 30 and 10 members serve a typical machine better than 40 loose variables.

  1. Fix the controller address. Set the static IP or reservation, power cycle, then ping the controller from the machine that will run the HMI. The engineering PC route can work while the HMI route is blocked.
  2. Activate the OPC UA server in the controller's communication settings in the development system, leave TCP 4840 as the port, and note the endpoint URL the runtime reports.
  3. Add a symbol configuration object to the application. The symbol configuration options rebuild the symbol file at every compilation, so what you tick is what ships.
  4. Build the application once so the list of publishable variables populates. If a global variable list stays empty, reference one of its variables in code and rebuild; unused lists can stay invisible until the compiler sees them.
  5. Tick only the tags the HMI needs and set access per symbol: read-only for indications and process values, read/write for setpoints and commands the HMI is genuinely allowed to change.
  6. Group the tags into structures, for example one status structure and one command structure in a dedicated global list. Two published structures beat 300 loose symbols: the address space stays browsable, and a new tag is one structure member instead of a new engineering round trip.
  7. Download, set the application to run, and store the boot application so the symbols and the server come back after a power cut.

What URL does the client point at?

Point the client at the endpoint URL the runtime reports: opc.tcp:// followed by the controller address and TCP port 4840. On a controller at 192.168.10.24, the client connects to opc.tcp://192.168.10.24:4840. Two details decide whether the first connect works. First, the server may answer discovery with an endpoint that carries a hostname the client cannot resolve; discovery then succeeds and session creation fails. Connect with the same address form, IP or hostname, that the server certificate carries. Second, TCP 4840 must be open end to end, through every VLAN or NAT hop between the client and the controller. A blocked port produces a silent timeout with nothing in the server log.

Why does the first connection fail with a certificate error?

The connection fails because OPC UA secures every session with application certificates and neither side trusts the other on first contact: put the client certificate in the server's trusted store and the server certificate in the client's, then reconnect. Once browsing works, close the easy doors before the cell runs production: disable anonymous login, enable a signed-and-encrypted security policy, and give the HMI its own user account on the server. Certificate checks also fail on a controller with no battery-backed clock, because it boots with a stale date and every certificate reads as invalid. Point the runtime at an NTP server and confirm the date after a cold start. If your client validates against a certificate authority instead of self-signed certificates, resolving CA certificate trust walks that store layout. The service codes you will see are BadCertificateUntrusted, BadCertificateHostNameInvalid, BadCertificateTimeInvalid and BadUserAccessDenied.

How do you check the whole path works?

Connect a generic client from the machine that will run the HMI, browse to your two structures, force one value in the development system, and watch it arrive inside the publishing interval: under 1 second on a 500 ms subscription. Run the check with the HMI software closed, so a failure points at the server side and nowhere else.

What you see What it points to What to do
Silent timeout, no server log entry TCP 4840 blocked on a hop Open the port end to end and retest
Discovery works, session creation fails Client cannot resolve the hostname in the endpoint Connect with the address the certificate carries, or fix DNS
BadCertificateUntrusted Certificates not yet exchanged Trust the client certificate on the server, the server certificate on the client
BadCertificateTimeInvalid Controller clock wrong after boot Set NTP, verify the date after a cold start
BadUserAccessDenied Client still logging in anonymously Create the user account, configure the client for it
A tag missing from the browse tree Symbol unticked or list not rebuilt Tick it, rebuild, download again

Once values move, the server side is done. The HMI project itself, from operator text in alarms to screen behavior, is separate work that starts from a clean tag list.

How many tags and what update rates can the controller handle?

Size the load as monitored items multiplied by sampling rate: 30 tags sampled at 500 ms generate 60 value updates per second, and the same 30 tags at a 5 s interval generate 6, so tier the rates. Use subscriptions, and never cyclic reads of the whole tag list; the protocol is change-driven and polling defeats it. A working tier set for a machine HMI:

  • Machine state, alarms, interlock bits: 250 to 500 ms. This is where an operator feels lag.
  • Counters, batch identifiers, recipe values, nameplate text: 5 s. Nobody reads a totalizer twice in one second.
  • Commands are writes, and writes are not monitored items. Do not subscribe to a setpoint to read it back; let the echo come through the status structure.
  • One subscription per rate tier, set per screen in the client. A screen with 30 fast tags and 10 slow tags lands in two subscriptions.

No public figure caps monitored items on a small controller; the ceiling moves with the runtime package and the CPU. The lever you control is updates per second, and the arithmetic is short enough to do on the drawing.

Example: how do 40 tags on a filler line reach the panel?

A filler controller at 192.168.10.24 runs the CODESYS runtime with the OPC UA server on default settings, and the panel HMI runs on a panel PC at 192.168.10.77. The symbol configuration publishes two structures: FillerStatus with 30 members, of which 20 are fast states and speeds and 10 are slow counters and batch data, and FillerCommands with 10 writable setpoints. The client connects to opc.tcp://192.168.10.24:4840 and builds two subscriptions:

  • 20 fast members at a 500 ms publishing interval: 20 ÷ 0.5 s = 40 updates per second.
  • 10 slow members at a 5 s interval: 10 ÷ 5 s = 2 updates per second.

Total load: 40 + 2 = 42 value updates per second, plus 10 writes that fire only when an operator changes a setpoint. After the certificate trade and a user account for the panel, force the fault bit in online mode and watch it land on the panel inside the 500 ms interval plus network delay, comfortably under 1 second. The engineer's laptop then connects to the same endpoint with zero changes on the controller.

When should you skip OPC UA for the HMI?

Skip OPC UA when one engineer owns the screens and they will live and die inside the CODESYS project, because the built-in visualization needs no tag plumbing. Choose it whenever the client count, the vendor mix or the machine count grows past one.

The other case to set aside is the shop-floor board. If the ask is a screen the whole aisle reads from 20 ft, nobody touches it and an interactive client is the heavy tool. An offline shop-floor display plays image and video from a card, with no internet and no subscription, and the same units run your own Android app when the board must show live values. The decision between a status board and an operator panel is its own question: read factory status display or operator HMI and live factory data display: signage or dashboard. For a board driven by sensor states, planning an offline sensor status display for your shop floor walks it.

Recommendation: Publish two structures and no loose variables, tier the subscriptions at 500 ms for machine state and 5 s for slow data, hold the controller on a fixed address with both certificates trusted, and choose OPC UA whenever more than one client or vendor will touch the machine; inside a single CODESYS project, use the built-in visualization and keep the server for supervisory access.

Questions

Does the CODESYS OPC UA server expose every variable in the project?

No. Publication is explicit. Only the instances you tick in the symbol configuration enter the address space, and the symbol file is rebuilt at every compilation. Build the application once before selecting tags, and if a global variable list stays empty, reference one of its variables in code and rebuild. Access is set per symbol, so leave indications read-only and grant read/write only to setpoints the HMI may change.

Is the OPC UA server in the CODESYS runtime free?

CODESYS documents the server as included in every application-based runtime license without an extra license fee, as a restricted build. What that restriction means for a given runtime package varies, so confirm the package on your controller carries the server before you freeze the architecture. The client side is separate: a third-party HMI may need its own OPC UA client license.

Which firewall rule does an OPC UA connection need?

Open TCP port 4840 for connections arriving at the controller, on every hop between the client subnet and the controller, including any VLAN or NAT boundary. The binary protocol runs over TCP, and a blocked port shows up as a silent connection timeout with no entry in the server log. Keep the controller address fixed so the rule and the endpoint URL stay valid.

Can several clients connect to the same server at once?

Yes. The same endpoint serves a panel HMI, a desktop engineering client and a dashboard at the same time, each with its own session and subscriptions. The number of accepted sessions is a property of the runtime package, so confirm it against your package before promising a customer a specific client count.

Can an OPC UA tag feed a wall display without a PC?

Not directly. The included player on our shop-floor displays plays image and video files from a card, with no internet and no subscription, so live tags need either your own Android app on the display or a small middleware box that renders values into media the display cycles. For a board that changes once a shift, the card route is the simpler one.

Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.

Keep reading

Build your signAsk for a quote