Voltrus PLC Documentation

Installation

Voltrus PLC is a native macOS application — an IEC 61131-3 Structured Text editor paired with a built-in softPLC runtime. It runs natively on Apple Silicon and Intel Macs. No Windows VM, no Parallels, no CODESYS, no TIA Portal. One-time purchase with free updates.

Download

System Requirements

RequirementMinimum
macOS12 Monterey or newer (Apple Silicon & Intel)
RAM4 GB (8 GB recommended for large programs)
For live I/ONetwork reachability to the device (Modbus TCP 502, EtherNet/IP 44818, OPC-UA 4840, S7 102, or MQTT 1883/8883)

First Launch

If you downloaded the direct build outside the App Store, macOS Gatekeeper may block the binary on first run. Right-click the app, choose Open, then confirm. This is only required once.

No drivers required to start. The built-in softPLC runtime lets you write, compile, and run Structured Text with simulated I/O — no physical PLC needed. Live I/O drivers (Modbus, OPC-UA, S7, EtherNet/IP, MQTT) activate the moment you bind a variable to a real tag or register.

Quick Start

1. Write your first Structured Text program (2 minutes)

This is the inner loop: write ST, compile, run on the softPLC, watch variables update live.

  1. Create a New Project and add a Program Organisation Unit (POU) of type PROGRAM, language ST.
  2. Declare variables in the VAR ... END_VAR block — inputs, outputs, and locals.
  3. Write logic in the body. A simple timer-based blinker:
PROGRAM Blinker
VAR
  tOn  : TON;          (* on-delay timer *)
  out  : BOOL;         (* output *)
END_VAR
tOn(IN := NOT out, PT := T#1s);
IF tOn.Q THEN
  out := FALSE;
ELSIF NOT tOn.IN THEN
  out := TRUE;
END_IF;
END_PROGRAM
  1. Click Build (⌘B). The ST compiler type-checks and lowers to softPLC bytecode.
  2. Click Run (⌘R). The softPLC runtime executes the task cyclically; out toggles every second in the watch table.

2. Set a breakpoint and inspect state

Click in the gutter next to a line to set a breakpoint. Start the runtime in Debug mode — execution pauses at the line and the watch table shows live values for every in-scope variable. Step over (F10) or continue (F5). This is the same workflow you'd use in TIA Portal or CODESYS, but native on macOS.

3. Bind a variable to a real Modbus TCP device

  1. Open I/O Configuration and add a Modbus TCP device. Enter the IP and port 502.
  2. Map a holding register to a project variable, e.g. powerMeter.kW → Holding Register 0, type REAL (32-bit, big-endian).
  3. Annotate the variable with AT %IW0 (or use the mapping UI) so the runtime polls it each cycle.
  4. Run — the register value now flows into your ST logic on every scan.

4. Try AI-assisted ST generation

Open the AI assistant panel, describe what you want in plain English ("average the last 4 analog inputs and alarm if above 80"), and insert the generated ST. Review it like any code review — the AI accelerates boilerplate, but you own the logic that ships.

Configuration

Task Configuration

Every POU runs inside a task. The task defines the cyclic execution interval and priority.

ParameterTypical Values
Task typeCyclic, Event-driven (interrupt)
Cycle time1 ms, 10 ms, 100 ms (default)
Priority0 (highest) – 31 (lowest)
WatchdogAbort the task if a cycle exceeds this (e.g. 200% of cycle time)

IEC 61131-3 Data Types

TypeSize / Notes
BOOL1 bit
INT / UINT16-bit signed / unsigned
DINT / UDINT32-bit signed / unsigned
REAL32-bit IEEE float (LREAL = 64-bit)
TIMELiterally T#500ms, T#2s
STRINGASCII, fixed length
FUNCTION_BLOCKInstantiated: myTimer : TON;

I/O Drivers

Voltrus PLC ships with native drivers for the protocols that matter on real floors. Each driver exposes its addresses as bindable I/O.

DriverDefault PortTypical Addressing
Modbus TCP502Holding/Input register, coil — Unit ID + address
OPC-UA4840NodeId (namespace:index or string path)
Siemens S7102DB<n>.x (e.g. DB1.DBX0.0, DB1.DBD4)
EtherNet/IP (CIP)44818Allen-Bradley controller tag name
MQTT1883 / 8883 (TLS)Topic payload → JSON path

Scan Cycle

The runtime reads all physical inputs, executes one task cycle (your ST), then writes all outputs — the classic PLC scan. For a 100 ms cycle, keep total logic execution well under the interval or the watchdog trips. Long-running math (FFT, large array sorts) belongs in a slower task or a function block that yields across scans.

Key Features

IEC 61131-3 Structured Text, native

A text-based ST editor with syntax highlighting, autocomplete on types and function blocks, and real-time error squiggles. ST is the right language for complex math, string handling, and modern control logic — and unlike ladder logic, it diffs cleanly in git.

Built-in softPLC runtime

Compile your program to softPLC bytecode and run it on your Mac with simulated I/O — no PLC hardware required. Perfect for development, unit-testing logic, and demos. The same bytecode path runs against live drivers the moment you bind real I/O.

Multi-vendor I/O drivers

One IDE talks to Siemens (S7), Allen-Bradley (EtherNet/IP), Modbus TCP devices, OPC-UA servers, and MQTT brokers. You're not locked into one PLC vendor's ecosystem — bind the protocol your floor actually uses.

Debugging: breakpoints & watch tables

Set line breakpoints, step through cyclic logic, and watch every variable update in real time. Force values to test branches that are hard to reach with physical inputs. This is the workflow CODESYS and TIA Portal charge four-figure licenses for.

AI-assisted ST generation

Describe the control behavior in plain English and insert idiomatic ST. Useful for boilerplate (moving averages, scaling, alarm debouncing) so you focus on the process logic. Always review generated code before it ships to a machine.

Native macOS, no virtualization

Apple Silicon native (and Intel). No Rosetta translation tax, no Parallels, no Windows license. The editor, compiler, and runtime all run as one cohesive Mac app.

Troubleshooting

Watchdog trips — cycle time exceeded

Symptom: Runtime logs "Task cycle exceeded watchdog" and aborts the task.
Fix: Your logic runs longer than the configured cycle time. Open the task config and either lengthen the cycle (e.g. 100 ms → 250 ms), raise the watchdog tolerance, or move heavy computation into a slower task. Profile with the cycle-time monitor to find the offending POU.

ST compile error — type mismatch on assignment

Symptom: "Cannot assign REAL to INT" on a line that looks correct.
Fix: IEC 61131-3 is strictly typed — there is no implicit narrowing. Use an explicit conversion: myInt := REAL_TO_INT(myReal);. The same applies for INT_TO_REAL, WORD_TO_DINT, etc.

Modbus register reads 0 or a nonsense value

Symptom: A REAL bound to a Modbus holding register shows 0.0 or a huge exponent.
Fix: Byte-order mismatch. A 32-bit REAL spans two 16-bit registers, and every vendor picks a different word/byte order. In the I/O mapping, cycle through Big / Little / Swapped-Big / Swapped-Little until the value is sane. Also confirm Unit ID and 0-based vs 1-based addressing against the device manual.

OPC-UA connection — certificate rejected

Symptom: "BadCertificateInvalid" or the server drops the connection on bind.
Fix: The server doesn't trust the client cert. For development, generate a self-signed cert in the OPC-UA config and push it to the server's trusted store (often a pki/trusted/certs folder on the server). For production, issue a cert signed by the site CA.

S7 connection — "Job failed" / no data from DB

Symptom: Connecting to an S7-1200/1500 succeeds but reads return nothing or "Job failed".
Fix: Put-get (read/write) is disabled by default on newer Siemens firmware. In TIA Portal (once), enable Permit access with PUT/GET communication in the CPU protection settings, and check that the DB is not marked "Optimized block access" for the addresses you read — optimized blocks need symbolic access, not DBX bit offsets.

Breakpoint doesn't pause execution

Symptom: You set a breakpoint but the runtime runs straight past it.
Fix: Breakpoints only fire in Debug run mode, not in plain Run. Stop the runtime, switch to Debug, and restart. Also confirm the POU is actually called by the active task — an unlinked POU never executes, so its breakpoints never hit.

Support

When reporting an issue, attach the failing ST snippet, the compiler error message (or the runtime log line), and the I/O driver + protocol you're targeting. A minimal reproducer compiles to a fix fastest.