Building an IEC 61131-3 PLC on the Raspberry Pi Pico 2
When we started the PicoPLC project, the question was not whether the Raspberry Pi Pico 2 was fast enough to run a PLC — at 250 MHz dual-core Cortex-M33, it obviously is. The harder question was: can you deliver a standards-compliant PLC experience on bare metal, without an RTOS, without dynamic memory allocation, and without ever surprising an industrial user with non-deterministic behaviour?
The answer is yes. Here is how we got there.
Why IEC 61131-3 Matters on a Microcontroller
IEC 61131-3 is the international standard that defines the programming languages for programmable logic controllers: Ladder Diagram (LD), Function Block Diagram (FBD), Structured Text (ST), Instruction List (IL), and Sequential Function Chart (SFC). Nearly every industrial PLC — Siemens, Allen-Bradley, Mitsubishi, Omron — implements at least some subset of this standard.
For a control engineer who has spent twenty years writing ladder logic, the last thing they want when moving to a microcontroller-based system is to learn a new paradigm. The PicoPLC was designed with this in mind: the programmer sees familiar rungs, coils, contacts, timers, and counters. The microcontroller implementation details are invisible.
The VM Architecture
The PicoPLC does not compile ladder logic to native ARM Thumb2 code. Instead, it interprets a compact bytecode representation. This is a deliberate design decision:
- Safe over-the-air (USB) updates. Bytecode programs can be loaded via USB CDC without reflashing firmware. The interpreter validates the bytecode before execution; malformed programs are rejected before they can cause hardware damage.
- Isolation between user logic and system firmware. A bug in user ladder logic cannot corrupt the interrupt handlers, the watchdog management, or the I/O driver layer. The VM's memory map is bounded and checked at every access.
- Portability. The same bytecode compiled for PicoPLC will run on any future hardware revision. Customers do not need to recompile when hardware changes.
The VM memory map is partitioned as follows:
| Region | Symbol | Size | Description |
|---|---|---|---|
| Inputs | I0.0 – I0.9 | 10 bits | Opto-isolated digital inputs, read-only |
| Outputs | Q0.0 – Q0.6 | 7 bits | Relay outputs, write-only |
| Markers | M0.0 – M7.7 | 64 bits | Internal relay memory (SRAM) |
| Timers | T0 – T15 | 16 × 32-bit | On-delay (TON), off-delay (TOF), pulse (TP) |
| Counters | C0 – C7 | 8 × 16-bit | Up/down, preset value, current value, done bit |
The Instruction Set
The bytecode instruction set is deliberately minimal — 12 core opcodes cover the vast majority of industrial control programs:
LD addr ; Load contact (NO) — push bit onto accumulator stack
LDI addr ; Load contact (NC) — push inverted bit
AND addr ; Series (NO)
ANI addr ; Series (NC)
OR addr ; Parallel (NO)
ORI addr ; Parallel (NC)
OUT addr ; Drive coil — write accumulator to output/marker
SET addr ; Latch coil (SET)
RST addr ; Unlatch coil (RESET)
TMR T# preset ; Start/update timer
CTR C# preset ; Increment/decrement counter
END ; End of program, swap I/O, restart scan A simple motor starter rung — "start button latches motor contactor, stop button unlatches, overload trips unlatch" — translates to eight bytecode instructions. The entire program is less than 100 bytes for most simple machines.
Deterministic Scan Cycle
The central requirement for any PLC is a deterministic scan cycle: inputs are read, the user program runs, outputs are written, in a fixed and repeatable sequence. On the PicoPLC, this cycle is:
- Read all 10 opto-isolated inputs into the I-register (single atomic read via GPIO bitfield)
- Execute bytecode program from address 0x000 to END instruction
- Write Q-register to the 7 relay output drivers (single atomic write)
- Update all active timers (1ms tick from SysTick ISR)
- Service USB CDC (non-blocking, background)
- Pet the watchdog
- Goto 1
At 250 MHz with a typical 256-instruction program, the scan cycle completes in under 50 µs — well within the <10 ms requirement for most machine control applications. The SysTick ISR runs at 1 ms and updates timer accumulators independently of scan cycle length.
Hardware: Isolation and Relay Drive
Industrial reliability starts at the hardware boundary. The PicoPLC uses:
- 10 opto-isolated inputs — each input is protected by a PC817 optocoupler. The input circuit accepts 5–30V DC (24V nominal, the industrial standard). The isolation barrier protects the RP2350 from inductive spikes, ground loops, and accidental voltage reversals on the field wiring.
- 7 relay outputs — each output drives a 10A/250V relay via a ULN2003A Darlington driver array. The relay contacts are rated for resistive AC or DC loads up to 10A. Flyback protection is integrated on the driver board.
- 24V DC bus — the board accepts 7–30V DC (24V nominal) and includes an onboard 5V/3.3V switching regulator. No external power supplies are needed beyond the standard 24V DC rail already present in every industrial control panel.
Programming via USB
Programs are loaded over USB CDC (virtual COM port) using a simple text protocol. The programming tool — which runs on any PC without drivers on Linux, and with the standard WinUSB driver on Windows — uploads the compiled bytecode, verifies the checksum, and signals the PLC to hot-load the new program. The PLC finishes its current scan cycle, then switches to the new program on the next cycle.
There is no special downloader hardware. A standard USB A–micro cable is all that is needed for programming, monitoring, and firmware updates.
What Is Coming Next
The current PicoPLC implements the core instruction set. The roadmap includes:
- Structured Text (ST) compiler — for mathematical expressions in control loops
- Function Block Diagram (FBD) editor in the PC software
- Modbus RTU slave — so the PicoPLC can be polled by SCADA systems
- RS-485 multi-drop network for distributed I/O expansion
- Analogue inputs (4–20 mA / 0–10V) via an I2C ADC daughter board
The PicoPLC is available now for industrial OEM customers and system integrators. Contact us to discuss your application, request a sample, or get the full technical documentation.