Files
lmxopcua/docs/drivers/TwinCAT.md
T

6.3 KiB

Beckhoff TwinCAT (ADS) Driver

Getting-started guide for the Beckhoff TwinCAT driver. This is the short path — for the full per-field spec read docs/v2/driver-specs.md §6, for hands-on CLI testing read Driver.TwinCAT.Cli.md, and for the test-harness map read TwinCAT-Test-Fixture.md.

What it talks to

Beckhoff PLC runtimes — TwinCAT 2 and TwinCAT 3 — over the Beckhoff ADS protocol carried by AMS routing. The driver runs in-process in the OtOpcUa server's .NET 10 AnyCPU host. It compiles and runs without a local AMS router, but every wire call returns BadCommunicationError until a router is reachable (the router translates an AMS Net ID to an IP route).

Addressing is symbol-based: tags are referenced by their TwinCAT symbolic name (e.g. MAIN.bStart, GVL.Counter, Motor1.Status.Running) rather than by raw memory offset. One driver instance fans out to N targets, each identified by an AMS Net ID + port.

Project split

Project Target Role
src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/ net10.0 In-process driver — hosts the ADS client, symbol-path parser, and per-device probe loops
src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Contracts/ net10.0 Config records + the TwinCATDataType enum bound from DriverConfig JSON

Minimum deployment

"Drivers": {
  "twincat-cell-1": {
    "Type": "TwinCAT",
    "Config": {
      "Devices": [ { "HostAddress": "ads://5.23.91.23.1.1:851", "DeviceName": "Cell1" } ],
      "Tags": [
        { "Name": "Start",  "DeviceHostAddress": "ads://5.23.91.23.1.1:851",
          "SymbolPath": "MAIN.bStart", "DataType": "Bool", "Writable": true },
        { "Name": "Count",  "DeviceHostAddress": "ads://5.23.91.23.1.1:851",
          "SymbolPath": "GVL.Counter", "DataType": "Int32", "Writable": false }
      ]
    }
  }
}

AMS address form

HostAddress is an ads://{netId}:{port} URI parsed by src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATAmsAddress.cs. The Net ID is six dot-separated octets (NOT an IP — a Beckhoff-specific identifier the router maps to a route); the port is the AMS service port (851 = TC3 PLC runtime 1, 852 = runtime 2, 801 / 811 / 821 = TC2 PLC runtimes). Port defaults to 851 when omitted (ads://5.23.91.23.1.1).

Symbol path form

Symbol paths are parsed by src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATSymbolPath.cs, which mirrors IEC 61131-3 structured-text identifiers: global-variable-list (GVL.Counter), program variable (MAIN.bStart), struct member access (Motor1.Status.Running), array subscripts (Data[5], Matrix[1,2]), and bit-access (Flags.0).

Tag discovery

DiscoverAsync always emits the pre-declared Tags as the authoritative config path, under TwinCAT/{device}/. When EnableControllerBrowse is set, the driver also walks each device's symbol table and surfaces controller-resident globals / program locals under a Discovered/ sub-folder; any symbol-loader error falls back to pre-declared-only so a flaky symbol download never blocks discovery.

Capability surface

TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery, ISubscribable, IHostConnectivityProbe, IPerCallHostResolver, IRediscoverable (src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs).

Capability Path Notes
IReadable ReadAsync → ADS ReadValueAsync Per-device client, lazily connected and serialized per device
IWritable WriteAsync → ADS WriteValueAsync Read-only tags return BadNotWritable
ITagDiscovery DiscoverAsync Pre-declared tags + opt-in controller symbol browse
ISubscribable native ADS notifications (default), poll fallback UseNativeNotifications=true registers device notifications so the PLC pushes changes; false uses the shared PollGroupEngine
IHostConnectivityProbe per-device probe loop One HostConnectivityStatus per configured device; Running/Stopped transitions raise OnHostStatusChanged
IPerCallHostResolver ResolveHost lookup in the tag map Routes each call to the device of the referenced tag; returns an empty-string sentinel when unresolved
IRediscoverable symbol-version-changed callback A PLC re-download fires OnRediscoveryNeeded so the address space is rebuilt

Rediscovery on PLC re-download

IRediscoverable is the distinguishing capability. When the ADS client detects DeviceSymbolVersionInvalid (1809 / 0x0711) — the documented TwinCAT symbol-version-changed signal, raised when a PLC program is re-downloaded — every symbol and notification handle is invalidated. The driver raises OnRediscoveryNeeded with a TwinCAT scope hint so Core rebuilds the address space rather than treating it as a transient connection error.

Native notifications

By default the driver registers native ADS device notifications: the PLC pushes value changes on its own cycle, which is strictly better for latency and CPU than polling. NotificationMaxDelayMs lets TwinCAT coalesce notifications up to a batching delay for high-churn signals. Set UseNativeNotifications=false for deployments where the AMS router has notification limits you can't raise — then the driver falls through to the shared poll engine.

Single-connection-per-device

Each device's ADS client is lazily connected and serialized by a per-device connect gate, so a concurrent read / write / probe can't race a client create-or-dispose. Probe-initiated connects use the probe timeout; reads and writes use the driver-wide Timeout.

Testing

  • Unit teststests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Tests/ cover the AMS / symbol-path parsers, the status mapper, and the driver lifecycle via a fake ADS client factory.
  • Integration fixture — see TwinCAT-Test-Fixture.md for the harness map.
  • CLIDriver.TwinCAT.Cli.md documents the standalone read/write/browse/probe CLI for manual checks.

Further reading