Raspberry Pi PLC

Turn a Raspberry Pi into an IEC 61131-3 controller, with an SVGHMI panel in kiosk mode

The Beremiz snap is published for arm64 as well as amd64, so a Raspberry Pi 4 or 5 is a first-class target — for the runtime, and for the IDE itself. It is strictly confined and built on core24, so it installs the same way on Ubuntu Desktop and on Ubuntu Core.

One thing shapes every choice below: Beremiz compiles your PLC program to C and then to native code for the target. Build on the Pi and you are compiling arm64 on arm64, with no cross toolchain to set up. That is why the workflows here run the IDE or the CLI on the board, and reach them over SSH.

Ubuntu Desktop: the whole toolchain on the board

Good for learning, for a bench setup, or where the Pi is both the controller and the engineering station.

Install Ubuntu Desktop for Raspberry Pi — the step by step tutorial covers flashing the card — then:

sudo snap install beremiz
beremiz.ide

That is the whole install. Edit, build, run and watch the HMI on one board, with the project’s URI_location left at LOCAL://, exactly as in getting started.

Ubuntu Core: the appliance

Ubuntu Core runs nothing but snaps, updates transactionally and rolls back a failed update by itself. That is what you want on a board you ship to someone else.

sudo snap install beremiz
sudo beremiz.runtime -p 3000 -x 0 -a 1 /var/snap/beremiz/common/plc
flag why
-p 3000 eRPC port. Matches the ERPC:// default.
-x 0 No taskbar icon — there is no desktop.
-a 1 Start the PLC automatically, so the board comes up controlling.

The working directory has to be somewhere the confined snap can write — /var/snap/beremiz/common is its own writable area.

Note what is not in that command: -i. It defaults to localhost, and it should stay there.

Do not bind the runtime to the network. The eRPC protocol is neither encrypted nor authenticated. A runtime listening on 0.0.0.0 lets anything that can reach the port load and run arbitrary code on the controller, and stop the machine. Leave it on localhost and reach it over SSH.

Programming a board with no screen

Three ways, all of which keep eRPC on the loopback interface and expose nothing but SSH.

Run the IDE on the Pi, display it on your PC

The IDE runs on the board — so builds are native — while the window appears on your desktop. On Ubuntu Desktop or Ubuntu Server, waypipe forwards Wayland over SSH and needs nothing running on the Pi’s own display:

sudo apt install waypipe          # on the Pi, and on your machine
waypipe ssh ubuntu@raspberrypi.local beremiz.ide

If your own desktop is not Wayland, GTK’s Broadway backend renders the IDE into a browser tab instead. Start the Broadway server on the Pi, run the IDE against it, and forward the port:

# on the Pi
broadwayd --port 8085 :5 &
GDK_BACKEND=broadway BROADWAY_DISPLAY=:5 beremiz.ide

# on your machine
ssh -L 8085:localhost:8085 ubuntu@raspberrypi.local

Then open http://localhost:8085. Broadway is the more fiddly of the two — the snap’s GNOME extension sets up GTK for you, so GDK_BACKEND may need forcing — but it needs no Wayland compositor at either end.

Neither is available on Ubuntu Core, which has no apt: there, use the CLI.

Develop on your PC, build and run on the Pi

Keep the IDE where your screen and your keyboard are, and let the board do the compiling. Copy the project across — rsync, scp, or a git pull on the Pi — then drive it with the command line interface:

beremiz --project-home ~/myproject --uri ERPC://127.0.0.1:3000 \
        build transfer run

The commands chain, so one invocation builds the project, sends it to the runtime listening on loopback, and starts the PLC. stop, clean and flush are there too. This is also what you would call from a deployment script or from CI.

Forward eRPC itself

If you would rather keep the IDE connected from your PC, tunnel the port rather than opening it:

ssh -L 3000:localhost:3000 ubuntu@raspberrypi.local

and set URI_location to ERPC://127.0.0.1:3000. SSH provides the encryption and the authentication that eRPC does not. Note that the IDE will then build on your PC, so this needs a target SDK for arm64 — which is why building on the board is usually simpler.

For a permanent link between two machines you control, Beremiz also speaks ERPCS://, eRPC wrapped in TLS-PSK through stunnel.

Putting SVGHMI on the Pi’s screen, in kiosk mode

An SVGHMI instance serves over HTTP. By default it binds localhost on port 8008, under a path named after the node, so the first one in a project is at http://localhost:8008/svghmi_0. All three are configurable in the SVGHMI node’s settings.

To show that full screen with no desktop, no browser chrome and nothing for an operator to escape into, use Ubuntu Frame with a web kiosk snap:

sudo snap install ubuntu-frame
sudo snap install wpe-webkit-mir-kiosk
sudo snap set wpe-webkit-mir-kiosk url=http://localhost:8008/svghmi_0

Both start on boot, so the panel comes up showing the HMI with no login and no desktop behind it. Canonical’s secure web kiosk tutorial covers the rest — display rotation, touch input and locking the device down.

Keeping the browser on the same board as the PLC is also what lets SVGHMI stay on localhost. If the screen has to be a different device, move that instance off loopback deliberately, and treat the HMI port with the same care as any other exposed service.

Two SVGHMI settings are worth knowing for an unattended panel: OnStart and OnStop run a command when the PLC starts and stops, so SVGHMI can launch and close a browser itself; and the watchdog’s OnWatchdog fires when the HMI stops sending heartbeats, which is how you restart a browser that has crashed. With Ubuntu Frame the kiosk is always up and pointed at a fixed URL, so you usually need neither.

Fieldbuses and I/O

The snap ships the CANopen stack with both the virtual and SocketCAN drivers, so a CAN HAT works — connect the interface once, as it is not automatic:

sudo snap connect beremiz:can-bus

Modbus, OPC-UA, BACnet and MQTT need nothing beyond the network interface, which is connected by default. The GPIO header is reached the usual Linux ways from a Python block or a C extension.