Troubleshooting#

Symptoms, in approximate order of frequency.


The editor cannot find the device#

Search returns nothing.

Discovery is a UDP broadcast on port 33333, and broadcasts do not cross subnets. Check, in order:

  1. Are you on the same subnet? Compare your workstation’s address with the device’s. Different subnets, a VPN, or a segmented VLAN will all defeat discovery while leaving the device perfectly reachable.

  2. Has it finished booting? Give it a minute after power-up.

  3. Is your host firewall dropping the reply? Some endpoint-protection suites block the inbound UDP response. Allow OpenPLC Editor through.

  4. Wireless client isolation? Many guest and corporate Wi-Fi networks block station-to-station traffic. Use a wired connection.

The workaround is always the same: find the address another way and type it in manually.

# From the device, over an HDMI display or SSH
hostname -I

# Or sweep the subnet from your workstation
nmap -p 8443 --open 192.168.1.0/24

The device is found but will not connect#

Connection refused or times out. The runtime is not running. Try restarting the device.

Login fails. The credentials are stored on the device, not in any cloud account. If they are lost, see Recovery and Factory Reset.


The SLM-RP4 is not in the Device dropdown#

The support package is not installed, or the editor is too old.

  1. Check the editor version. 4.3.1 or newer is required.

  2. Open the Package Manager and check the Installed tab.

  3. If it is not listed, install it. See Quick Start: OpenPLC.


Backplane Configuration and HAL Settings are missing#

They only appear once SLM-RP4 is selected in Device → Configuration. Select the board first.

If the board is selected and they are still missing, the package did not register its screens. Reinstall it and reopen the project.


No modules found#

No modules found in backplane after 5 retries

The base controller is alive but sees an empty bus. The SPI interface is working, so this is a wiring or seating problem rather than a configuration one. If the interface itself has been lost, the runtime reports a different error instead, covered under The backplane has stopped working entirely below.

  • Is the first module fully seated against the base? This is the usual cause.

  • Is backplane power present?

No base controller activity - check power supply

The base controller is not responding at all. Almost always a power problem rather than a module fault. Check 24 V at the terminal.


The backplane has stopped working entirely#

If no I/O works at all, rather than one module or one channel misbehaving, the SPI interface the backplane runs on has been lost.

The symptoms are:

  • The PLC does not run, and PLC Logs reports:

    [SYNERGY] SPI: failed to open /dev/spidev6.0 at init (errno=2)
    [SYNERGY] SPI init failed
    Native plugin synergy failed to start (returned -1)
    
  • A Python program fails at synergy_logic.Base() with:

    ValueError: No device found for /dev/spidev6.0
    
  • ls /dev/spidev6.0 reports that the file does not exist.

The backplane uses /dev/spidev6.0, which is created by a single overlay line in /boot/firmware/config.txt. Two things remove it.

Enabling SPI in raspi-config. The Interface Options → SPI toggle sets dtparam=spi=on, which enables SPI0 on GPIO 7–11 (CE1, CE0, MISO, MOSI, SCLK). The backplane’s SPI6 overlay uses GPIO 9 and 10 as its chip selects (cs0_pin=9,cs1_pin=10). The two cannot coexist, and the backplane’s overlay is the one that fails to load.

A system update or a reimage that rewrites config.txt and drops the overlay line.

Identify which one it is#

ls /dev/spidev*
pinctrl get 9,10,19,20,21
grep -nE "dtparam=spi|dtoverlay=spi" /boot/firmware/config.txt

Result

Cause

/dev/spidev0.0 and 0.1 present, GPIO 9 and 10 shown as SPI0_*

SPI0 was enabled and is taking the pins

No spidev device at all, GPIO 9, 10, 19, 20, 21 all plain inputs

The overlay line is missing

/dev/spidev6.0 and 6.1 present, GPIO 19, 20, 21 shown as SPI6_*

The interface is correct; the fault is elsewhere

Restore it#

Edit the file:

sudo nano /boot/firmware/config.txt
  1. If a line reads dtparam=spi=on, comment it out with a leading #, or delete it.

  2. If the overlay line is missing, add it exactly as written:

    dtoverlay=spi6-2cs,cs0_pin=9,cs1_pin=10
    
  3. Save the file and reboot:

    sudo reboot
    

If SPI was enabled through raspi-config, turning the same toggle back off has the same effect as commenting the line out by hand. Check afterwards that the dtoverlay line is still present.

To add the overlay line without editing the file, this appends it only when it is absent, and is safe to run more than once:

grep -q '^dtoverlay=spi6-2cs' /boot/firmware/config.txt \
  || echo 'dtoverlay=spi6-2cs,cs0_pin=9,cs1_pin=10' | sudo tee -a /boot/firmware/config.txt

It does not remove dtparam=spi=on, so check for that separately.

Keep the line outside a conditional section

config.txt can contain conditional filters such as [cm4] or [cm5], which apply only to the hardware they name. The overlay line must sit under [all], or before any filter, so that it always applies.

On a factory image [all] is the last section, so appending to the end of the file is correct.

Verify after the reboot#

ls /dev/spidev*
pinctrl get 9,10,19,20,21

A working device reports both devices and these pin assignments:

/dev/spidev6.0  /dev/spidev6.1

 9: op -- pd | hi // GPIO9 = output
10: op -- pd | hi // GPIO10 = output
19: a3    pd | lo // GPIO19 = SPI6_MISO
20: a3    pd | lo // GPIO20 = SPI6_MOSI
21: a3    pd | hi // GPIO21 = SPI6_SCLK

GPIO 9 and 10 are the chip selects and appear as ordinary outputs. If they instead show SPI0_MISO and SPI0_MOSI, SPI0 is still enabled.

Then start the PLC and confirm the backplane comes up in PLC Logs:

[SYNERGY] SPI: opened /dev/spidev6.0 (mode=2, speed=1000000 Hz)
[SYNERGY] Slot 1: SLM-ACDCI-8NP-RLY8 (0x24A500E1)
[SYNERGY] Base controller initialized (1 module(s); DI=1 DO=1 AI=0 AO=0 bytes)

Never enable SPI through raspi-config on this device

The SPI toggle in raspi-config configures a different bus on different pins, and enabling it disables backplane communication completely until the change is undone and the device is rebooted.

The dtoverlay line is the whole SPI configuration, and it is applied at the factory. Leave the raspi-config toggle off.


Sign-on lists the wrong modules#

The PLC Logs sign-on lines come from the modules themselves and are authoritative:

Slot 1: SLM-DCI-16NP (0x052000E2)
Slot 2: SLM-DCO-15P (0x140800E6)

If they disagree with your Backplane Configuration, the configuration is wrong. Correct it and re-upload.

Running with a mismatched configuration means your program addresses the wrong data.


An output does nothing#

Work down the chain rather than guessing.

  1. Is the PLC running? The RGB LED should be green.

  2. Is the variable being set? Open the debugger and watch it. If it is not changing, the problem is in your logic.

  3. Did the module sign on? Check PLC Logs.

  4. Does the module have field power? Discrete output modules need their own supply to switch a load. The backplane powers the module’s logic, not your load. This is the most common cause.

  5. Sinking or sourcing? A load wired for a PNP module will not work on an NPN one, and vice versa.

  6. Right address? Check the I/O Mapping table. Output numbering starts at %QX0.0 for the first module with outputs, which is not necessarily slot 1.


An input never changes#

  1. Right address? Check the I/O Mapping table.

  2. Is the field wiring correct for the module type? Sinking inputs need the circuit completed to common.

  3. Is the signal actually present? Meter it at the terminal.

  4. Did the module sign on?


An analog channel reads zero, always#

At sign-on, the OpenPLC Runtime sends each analog and temperature module the configuration from the project’s Backplane Configuration, or the module’s factory defaults when the project has none. The Python and C++ libraries send the factory defaults.

Channel not enabled. Channels Enabled restricts which channels are sampled. Disabled channels read zero while still occupying their addresses.

Configuration not applied. Check the PLC Logs for Slot N (MODULE): no config available or a configuration length mismatch warning. Set the module’s Configuration form in Backplane Configuration and re-upload.


Analog readings are wrong by a factor of eight#

You are scaling against the wrong maximum.

The range of a raw analog count depends on the module’s Counts Scaling setting in Backplane Configuration:

  • Module resolution (the default): counts follow the converter, 0-8191 for a 13-bit input and 0-4095 for a 12-bit output.

  • Rescaled to 0 - 65535: every channel spans the full UINT range.

Code written for one setting and run with the other is out by a factor of roughly eight (13-bit) or sixteen (12-bit). Check the setting, then scale against the matching maximum. The Python and C++ libraries always report counts at module resolution. See Configuring the Backplane.


Temperatures are in the wrong unit#

The SLM-THM-4 defaults to degrees Fahrenheit.

Change it in Burnout Detection / Units on the module’s Configuration form and re-upload. See Configuring the Backplane.

Temperature readings are wrong but plausible#

Check the sensor type. The default is Type J; a Type K thermocouple read as Type J is linearised with the wrong curve. The error is small near ambient and grows with temperature, so it passes a bench test and fails in the process.

A temperature falls as the process heats#

The thermocouple is wired backwards. Swap the leads. Note that under ANSI colour coding the red lead is negative, which is a common source of error.


The PLC keeps stopping#

Bus fault. The HAL has detected repeated failures on a slot and applied the configured fault action. Check PLC Logs for which slot.

  • A module working loose is the usual cause.

  • Electrical noise. Check grounding and cable routing.

Cycle overrun. The driver cannot complete a scan within its configured cycle time. Raise the Bus Scan Cycle rather than the fault threshold. Masking an overrun does not make the I/O any fresher.

See HAL Settings.


Changes have no effect#

Backplane configuration, HAL settings and module configuration all live in the project and are pushed to the device on upload.

Build & Upload after changing any of them. Editing a form does not affect a running device.

If a build behaves inexplicably, try Clean Upload to discard the device’s build cache.


I/O stops working after a package update#

A package update can change the HAL driver. The device keeps running the driver it already has until you upload again.

Rebuild and re-upload. Then confirm that the modules in your backplane configuration are still present in the updated module list. See Configuring the Backplane.


Python or C++: erratic readings#

This is almost always a backplane collision. The OpenPLC Runtime holds the backplane while the PLC is running, and the direct libraries drive the same pins. Running both at once produces interleaved transactions and invalid data, with no error raised.

Stop the PLC with Stop in OpenPLC Editor, or stop the runtime from a terminal:

sudo docker stop openplc-bootloader openplc-runtime

Then power-cycle the base to clear the base controller’s state, and start one side only. See Sharing the Hardware.


Python: ModuleNotFoundError: No module named 'synergy_logic'#

The library is supplied under ~/Desktop/synergy_python and is not installed system-wide, so it is importable only when the interpreter can find it. Run your program from that directory, or set PYTHONPATH:

cd ~/Desktop/synergy_python
python3 my_program.py

# or, from anywhere
export PYTHONPATH=/home/slm-rp4/Desktop/synergy_python

See Getting Started with Python.

Python: permission denied on /dev/spidev6.0#

groups
ls -l /dev/spidev6.0 /dev/gpiochip0

Add the user to the group owning the device node, then log out and back in.

C++: undefined reference to 'Synergy::init()'#

You compiled against the header but did not compile the implementation. Both Synergy.cpp and RPi.cpp must be in the source list:

LIB=~/Desktop/synergy_cpp/lib/synergy
g++ -std=c++17 -O2 -I $LIB $LIB/Synergy.cpp $LIB/RPi.cpp myprogram.cpp -o myprogram

C++: Synergy.h: No such file or directory#

The -I path does not point at the directory containing the headers.

See C++: Building.


A service does not start at boot#

systemctl status my-controller
journalctl -u my-controller -n 100

Common causes:

  • Forgot sudo systemctl enable my-controller.

  • Forgot sudo systemctl daemon-reload after editing the unit file.

  • Relative paths in the program with no WorkingDirectory= set.

  • The program starts before the hardware is ready. Make it retry.

  • Python output buffering hiding the real error. Add Environment=PYTHONUNBUFFERED=1.

See Running on Boot.


Reading the runtime logs#

The PLC Logs tab in OpenPLC Editor is the normal way to read the runtime’s output, and it needs no terminal access.

If the editor cannot connect, or you need more history than the tab shows, read the logs from a terminal instead. The runtime runs as a container, so its output comes from docker logs:

# The last 200 lines
sudo docker logs --tail 200 openplc-runtime

# Follow live
sudo docker logs -f openplc-runtime

# Only the last ten minutes
sudo docker logs --since 10m openplc-runtime

The runtime writes its own timestamps, so there is no need to add -t.

If the runtime is not starting at all, the component that supervises it keeps a separate log, which will say why:

sudo docker logs --tail 50 openplc-bootloader

If the problem persists#

Gather this before asking for help:

  • What the LEDs are doing.

  • The PLC Logs output, especially the sign-on lines.

  • sudo docker logs --tail 200 openplc-runtime from the device.

  • sudo docker logs --tail 50 openplc-bootloader, if the runtime is not starting.

  • Your backplane arrangement, slot by slot.

  • What changed immediately before the problem started.

The last item resolves more cases than any other.

Contact Synergy Logic for hardware, and the OpenPLC documentation for editor and runtime questions.