# Beckhoff ADS

> Connect Beckhoff TwinCAT PLCs over ADS/AMS - the AMS route, runtime port, symbol paths and read lengths.

The **Beckhoff ADS** driver talks to Beckhoff TwinCAT PLCs over ADS, the
TwinCAT automation protocol carried on AMS routes. You address values by their
symbol path in the PLC program, so what you type is what the TwinCAT project
declares. Add a device under the Beckhoff ADS driver in the
[Connector](connector); the panel shows only the fields this protocol uses.

## Connection {#connection}

| Field | Meaning | Default |
| --- | --- | --- |
| **Host** | IP address of the PLC. Its AMS Net Id is derived from this address as `{ip}.1.1`. | empty |
| **Port** | The AMS port of the target runtime. 0 uses 851, the TwinCAT 3 PLC runtime 1; further TwinCAT 3 runtimes count up from there (852, 853, …). | 0 |
| **Local IP (AMS)** | This station's own IP address, from which its AMS Net Id is derived as `{ip}.1.1`. It must match the AMS route configured on the PLC. When left empty the Host value is reused, which only works when both ends share the address, so fill it in practice. | empty |
| **Poll interval (ms)** | Device-wide read period for tags that do not override it. | 1,000 |

The device header shows the assembled endpoint, for example
`ads://192.168.0.1:192.168.0.50:851` (local IP, PLC IP, AMS port). Each tag
may set its own **Poll interval (ms)**; a tag value of 0 falls back to the
device interval.

ADS only answers stations the PLC knows: add a static AMS route on the PLC
(TwinCAT Engineering, SYSTEM → Routes, or the TwinCAT system tray icon) whose
address is this station's IP and whose AMS Net Id is that IP followed by
`.1.1`, matching what the driver derives from **Local IP (AMS)**. Without the
route the connection fails even though the network path is fine.

## Addressing {#addressing}

A Beckhoff tag is addressed by two fields in the tag's Source card:

| Field | Meaning | Accepted values | Default |
| --- | --- | --- | --- |
| **Symbol** | The symbol path of the variable in the PLC program. Required. | free text, e.g. `MAIN.fValue` | empty |
| **Read length (bytes, blank = auto)** | How many bytes to transfer per read. Blank sizes the read from the data type. | 1 and up, blank | blank |

The symbol path is exactly what TwinCAT shows: program variables as
`MAIN.fValue`, global variable lists as `GVL.MachineSpeed` or
`GVL_Settings.rSetpoint`. The driver resolves the symbol by name on the PLC
and reads its raw bytes. The automatic read lengths are:

| Data type | Auto read length |
| --- | --- |
| Boolean | 1 byte |
| Int32 | 4 bytes |
| Float | 4 bytes |
| String | 16 bytes |

For a String longer than 16 characters, set **Read length** to cover the
declared size (a TwinCAT `STRING(80)` needs 80 bytes of text). The Source
card's read-only **Source address (wire)** line shows the assembled address as
you edit.

## Data types {#data-types}

The **Data type** picker offers the four types the driver marshals:

| Data type | PLC counterpart | Notes |
| --- | --- | --- |
| Boolean | BOOL | 1 byte, non-zero is true |
| Int32 | DINT | little-endian, matching the PLC |
| Float | REAL | little-endian, matching the PLC |
| String | STRING | text up to the first NUL of the read buffer |

Byte order is the PLC's own little-endian and is handled automatically; there
is no byte-order option. A String read decodes the returned buffer up to the
first NUL terminator, so the padding behind a short string never leaks into
the value. Other TwinCAT widths (INT, LREAL, WORD, …) are not offered:
expose such a variable in the PLC program as one of the four types above to
read it here.

## Writes {#writes}

Tags whose **Access** is Read and write or Write only can be written. A write
resolves the same symbol and writes the value's bytes: 1 byte for Boolean,
4 bytes for Int32 and Float. A String write lays down the tag's whole **Read
length**: the UTF-8 bytes of the text at the front and zeros behind them, so a
shorter text written over a longer one replaces the whole value and nothing of
the old one survives. A text that does not fit the declared length is refused
with the length named in the journal, never cut down to size. A new tag starts
as Read only.

## Discovery {#discovery}

ADS has no broadcast discovery in this driver, so the Connector shows no
Discover button. Add the device and its symbols by hand.

## Good to know {#good-to-know}

- The AMS route is the usual reason a first connection fails: the route's AMS
  Net Id on the PLC must be exactly the station IP plus `.1.1`.
- Symbols are resolved by name on every read, so a PLC download that renames
  or removes a symbol turns its tag to bad quality until the names match
  again.
- An unreachable PLC costs nothing at startup: the device keeps retrying in
  the background and its tags read as bad quality until the connection lands.
