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
- Direct purchase: buy direct ($29.99 one-time) — you receive a download link by email
- Product page: /voltrus-plc/
System Requirements
| Requirement | Minimum |
|---|---|
| macOS | 12 Monterey or newer (Apple Silicon & Intel) |
| RAM | 4 GB (8 GB recommended for large programs) |
| For live I/O | Network 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.
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.
- Create a New Project and add a Program Organisation Unit (POU) of type
PROGRAM, language ST. - Declare variables in the
VAR ... END_VARblock — inputs, outputs, and locals. - 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
- Click Build (⌘B). The ST compiler type-checks and lowers to softPLC bytecode.
- Click Run (⌘R). The softPLC runtime executes the task cyclically;
outtoggles 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
- Open I/O Configuration and add a Modbus TCP device. Enter the IP and port
502. - Map a holding register to a project variable, e.g.
powerMeter.kW→ Holding Register0, typeREAL(32-bit, big-endian). - Annotate the variable with
AT %IW0(or use the mapping UI) so the runtime polls it each cycle. - 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.
| Parameter | Typical Values |
|---|---|
| Task type | Cyclic, Event-driven (interrupt) |
| Cycle time | 1 ms, 10 ms, 100 ms (default) |
| Priority | 0 (highest) – 31 (lowest) |
| Watchdog | Abort the task if a cycle exceeds this (e.g. 200% of cycle time) |
IEC 61131-3 Data Types
| Type | Size / Notes |
|---|---|
| BOOL | 1 bit |
| INT / UINT | 16-bit signed / unsigned |
| DINT / UDINT | 32-bit signed / unsigned |
| REAL | 32-bit IEEE float (LREAL = 64-bit) |
| TIME | Literally T#500ms, T#2s |
| STRING | ASCII, fixed length |
| FUNCTION_BLOCK | Instantiated: 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.
| Driver | Default Port | Typical Addressing |
|---|---|---|
| Modbus TCP | 502 | Holding/Input register, coil — Unit ID + address |
| OPC-UA | 4840 | NodeId (namespace:index or string path) |
| Siemens S7 | 102 | DB<n>.x (e.g. DB1.DBX0.0, DB1.DBD4) |
| EtherNet/IP (CIP) | 44818 | Allen-Bradley controller tag name |
| MQTT | 1883 / 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
- Email: support@voltrus.id
- Product page: /voltrus-plc/
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.