This is a Raspberry Pi breakout board + DIN rail case to use Pis in PLC-like industrial situations.
The design relies on a Raspberry Pi 4 for all functions to work. Pi 5 does also work but won't fit the 3D printed case, while Pi 3 and below don't allow for all functions to be used.
The PiPLC is intended to be used with Home Assistant, as well as OpenPLC. Obviously, since it's just a breakout board for any Pi, you can run whatever software you want, but Home Assistant and OpenPLC are the ones inspiring the design of this project.
For an example use with your own software, check out Grass!
IO featured on board the PLC are:
All the parts are or will be stocked at Tindie!
If you like my work please consider supporting me!
GPIO Name | PiPLC function | OpenPLC | Home Assistant | Codesys |
---|---|---|---|---|
GPIO_02 |
:blue_square: I²C SDA | :warning: No driver yet | :warning: To be tested | :warning: To be tested |
GPIO_03 |
:blue_square: I²C SCL | :warning: No driver yet | :warning: To be tested | :warning: To be tested |
GPIO_04 |
:blue_square: Modbus TX | /dev/ttyAMA3 |
/dev/ttyAMA3 |
:warning: To be tested |
GPIO_05 |
:blue_square: Modbus RX | /dev/ttyAMA3 |
/dev/ttyAMA3 |
:warning: To be tested |
GPIO_06 |
:blue_square: Modbus RTS | /dev/ttyAMA3 |
/dev/ttyAMA3 |
:warning: To be tested |
GPIO_07 |
:red_square: Q4 | %QX0.3 |
:white_check_mark: | :warning: To be tested |
GPIO_08 |
:red_square: Q3 | %QX0.2 |
:white_check_mark: | :warning: To be tested |
GPIO_09 |
:yellow_square: I5 | %IX0.4 |
:white_check_mark: | :warning: To be tested |
GPIO_10 |
:yellow_square: I4 | %IX0.3 |
:white_check_mark: | :warning: To be tested |
GPIO_11 |
:yellow_square: I6 | %IX1.5 |
:white_check_mark: | :warning: To be tested |
GPIO_12 |
:red_square: Q5 | %QX0.4 |
:white_check_mark: | :warning: To be tested |
GPIO_13 |
:yellow_square: I7 | %IX0.6 |
:white_check_mark: | :warning: To be tested |
GPIO_14 |
:blue_square: KNX TX | :x: | /dev/ttyAMA0 |
:warning: To be tested |
GPIO_15 |
:blue_square: KNX RX | :x: | /dev/ttyAMA0 |
:warning: To be tested |
GPIO_16 |
:red_square: Q6 | %QX0.5 |
:white_check_mark: | :warning: To be tested |
GPIO_17 |
:yellow_square: I1 | %IX0.0 |
:white_check_mark: | :warning: To be tested |
GPIO_18 |
:orange_square: PWM_0 | %QW0 |
:white_check_mark: | :warning: To be tested |
GPIO_19 |
:orange_square: PWM_1 | %QW1 |
:white_check_mark: | :warning: To be tested |
GPIO_20 |
:red_square: Q7 | %QX0.6 |
:white_check_mark: | :warning: To be tested |
GPIO_21 |
:red_square: Q8 | %QX0.7 |
:white_check_mark: | :warning: To be tested |
GPIO_22 |
:yellow_square: I3 | %IX0.2 |
:white_check_mark: | :warning: To be tested |
GPIO_23 |
:blue_square: 1-Wire | :warning: No driver yet | :white_check_mark: | :warning: To be tested |
GPIO_24 |
:red_square: Q1 | %QX0.0 |
:white_check_mark: | :warning: To be tested |
GPIO_25 |
:red_square: Q2 | %QX0.1 |
:white_check_mark: | :warning: To be tested |
GPIO_26 |
:yellow_square: I8 | %IX0.7 |
:white_check_mark: | :warning: To be tested |
GPIO_27 |
:yellow_square: I2 | %IX0.1 |
:white_check_mark: | :warning: To be tested |
Pins marked unusable with OpenPLC are either not broken out, or differ too much from OpenPLC's mapping. As OpenPLC's mapping is immutable, these pins might not be used if PiPLC is used with the OpenPLC runtime and Pi default hardware layer.
1 | 2 | 3 | 4 |
---|---|---|---|
+24 V |
+24 V |
GND |
GND |
The PiPLC is to be supplied with 24 V and requires at least a 1 A power supply under full load.
While it will theoretically work at 12 V, the relays used for Q1-8
require 24V coil voltage to trigger. If you are not placing the relays, feel free to supply your PLC with 12 V though.
Internally, 5V is generated by a TPS54331D
based DC-DC converter.
At J10
12/24V is passed through unprotected from the power input.
At J2
and J8
5 V from the DC-DC can be used to draw up to 500mA (protected through a polyfuse).
At J3
, 3V3 from the RPI can be used to draw up to 500mA (protected through a polyfuse)
1 | 2 | 3 | 4 |
---|---|---|---|
+5 V |
:blue_square: Modbus B |
:blue_square: Modbus A |
GND |
Modbus is an industrial communication protocol often used with PLCs communicating with I/O extensions or other PLCs.
The wire based one used here is called Modbus RTU
and is based on half-duplex RS-485 so the header can also be used for that if you dislike Modbus.
OpenPLC natively supports Modbus to talk to I/O, while Home Assistant has a Modbus integration.
[!NOTE]
To enable Modbus on your Pi, make sure to enableUART3
at GPIO5/06. This UART is not enabled by default and is only present on Raspberry Pi models 4 and up!We do NOT enable the
ctsrts
option as we don't want to run with hardware handshakes. We do however need to set/unset theDE/NRE
pins of the RS485 transceiver IC. How to do this differs based on the chose OS.In
/boot/config.txt
add:
dtoverlay=uart3
and reboot afterwards
After rebooting you should see the new serial port
/dev/ttyAMA3
when executingls /dev/tty*
For OpenPLC, if you followed the installation guide you should have installed my fork that includes
DE/NRE
control viaGPIO_6
so there should be nothing else for you to do
J3
1 | 2 | 3 | 4 |
---|---|---|---|
:red_square: Q1 |
:red_square: Q1 |
:red_square: Q2 |
:red_square: Q2 |
J4
1 | 2 | 3 | 4 |
---|---|---|---|
:red_square: Q3 |
:red_square: Q3 |
:red_square: Q4 |
:red_square: Q4 |
J5
1 | 2 | 3 | 4 |
---|---|---|---|
:red_square: Q5 |
:red_square: Q5 |
:red_square: Q6 |
:red_square: Q6 |
J6
1 | 2 | 3 | 4 |
---|---|---|---|
:red_square: Q7 |
:red_square: Q7 |
:red_square: Q8 |
:red_square: Q8 |
8 digital outputs are found at the pottom of the device. These outputs are driven by G5RL-1A-E-TV8
relays theoretically capable of 16 A at 250 V AC / 16 A at 24 V DC.
As with the digital inputs, each output features a status LED found on the HMI subboard.
[!WARNING] As this the PiPLC is an open source passion project and not externally rated by TÜV or a similar agency, usage of these relays in mains powered systems is at your own risk.
All components chosen are rated for 16 A at 250 V AC and should be capable of driving everything in a home environment.
Only certified electricians should ever be performing mains work, and home-built devices should never be connected to mains power unless you know what you are doing.
1 | 2 | 3 | 4 |
---|---|---|---|
:orange_square: PWM 0 |
:orange_square: PWM 1 |
GND |
GND |
The PWM outputs are intentionally bare, unprotected GPIO connections of GPIO_18
for PWM 0
and GPIO_19
for PWM 1
so take care not to damage the Pi here.
If choosing to use the GPIO as inputs, bear in mind that the Pi's GPIO are only 3.3 V tolerant.
Choosing to actually use the PWM outputs, you have both hardware PWM's available to you here.
[!WARNING] Unprotected access to
GPIO_18
andGPIO_19
. Take care not to damage your Pi!
1 | 2 | 3 | 4 |
---|---|---|---|
+5 V |
GND |
:blue_square: I²C SDA |
:blue_square: I²C SCL |
Here you have a protected, somewhat isolated 5 V tolerant I²C header with integrated pullups. This was at first intended for connecting to extensions, but the Modbus header takes care of that now. You do have the option however, to attach whatever I²C device you want, provided the runtime you are using supports I²C communication.
[!WARNING] The I²C contacts are already pulled up to 5 V so do not connect any 3.3 V only I²C devices directly without isolation!
[!NOTE] To enable I²C, go into
/boot/config.txt
and uncommentdtparam=i2c_arm=on
, or alternatively enable I²C throughsudo raspi-config
You might need to install
i2c-tools
withsudo apt install i2c-tools
to test your I²C connections.
i2cdetect -y 1
should show the adresses of all found I²C devices afterwards
1 | 2 | 3 | 4 |
---|---|---|---|
+ 3.3 V |
GND |
:blue_square: 1-Wire |
:blue_square: 1-Wire |
This header contains GPIO_04
for native 1-Wire capability.
1-Wire is usually used for temperature sensors, like DS18B20
, or battery voltage sensing, but is sometimes also used for access control with iButtons.
[!WARNING] Unprotected access to
GPIO_04
. Take care not to damage your Pi![!NOTE] To enable 1-Wire, add the following to
/boot/config.txt
:
dtoverlay=w1-gpio,gpiopin=23
reboot
You should be able to find any connected 1-Wire devices automatically with
ls /sys/bus/w1/devices/
afterwards
J10
1 | 2 | 3 | 4 |
---|---|---|---|
+24 V |
+24 V |
+24 V |
+24 V |
J11
1 | 2 | 3 | 4 |
---|---|---|---|
:yellow_square: I4 |
:yellow_square: I3 |
:yellow_square: I2 |
:yellow_square: I1 |
J12
1 | 2 | 3 | 4 |
---|---|---|---|
:yellow_square: I8 |
:yellow_square: I7 |
:yellow_square: I6 |
:yellow_square: I5 |
8 digital inputs are found at the top of the device. These inputs are 5-24 V tolerant current sinking inputs through EL817C
optocouplers.
J10 features 24 V outputs to easily supply switches or other sensors feeding back into J11-J12 as inputs.
All inputs feature a status//Order is intentional to match the GPIO mapping table of PiPLC at https://github.com/chrismettal/piplc#gpio-mapping //while having all relays mapped "in order" from left to right LED driven by the optocoupler output, thus not loading the input.
On the Raspberry side, pullups need to be enabled on the GPIOs to enable reading from these input stages.
The inputs require 5mA of input current to reliably trigger at 24 V.
Utilizing knxd to run a NCN5121 KNX transceiver chip the PiPLC can talk to KNX networks natively, without going through an actual KNX-IP gateway first. (Internally, knxd looks like a KNX-IP gateway, but it won't route through your actual LAN)
For Home Assistant, there is an addon for knxd, so Home Assistant sees the internal NCN5121 as a KNX-IP gateway @ localhost.
See the knxd documentation for specifics on how to use the driver if you are not using Home Assistant.
In this board, the NC5121
is NOT supplied through the KNX supply, but through the Pi's 3v3
rail. This means that it doesn't need to be taken into account when calculating the KNX power supply needs.
[!NOTE]
To enable KNX, make sure to disable bluetooth and the serial console on your Pi This is required to enable fullUART0
at GPIO14/15In
/boot/config.txt
add:
dtoverlay=pi3-disable-bt
In
/boot/cmdline.txt
remove:
console=serial0,115200
orconsole=ttyAMA0,115200
if foundreboot
In your OS,
/dev/ttyAMA0
can now be used as your KNX interface
A PCF8523
based realtime clock is present on the board so the PiPLC can keep track of time even when its 24 V input drops.
[!NOTE]
To enable the real time clock on your Pi, add the following to
/boot/config.txt
:
dtoverlay=i2c-rtc,pcf8523
And reboot afterwards.
Enabling RTC in the Pi and setting the time correctly is explained well in Adafruit's RTC guide.
This is the testing "schematic" used for all software examples. It demonstrates all interfaces present on-board and all testing of PiPLC was done in this configuration.
GPIO Name | PiPLC function | Device |
---|---|---|
GPIO_02 - 03 |
:blue_square: I²C | PCA9685 16 Ch. PWM servo driver |
GPIO_04 - 06 |
:blue_square: Modbus | EBYTE MA01-XACX0440 I/O Module |
GPIO_04 - 06 |
:blue_square: Modbus | ARCELI SHT20 Temp + Humidity probe |
GPIO_24 |
:red_square: Q1 | 230 V Light |
GPIO_08 |
:red_square: Q3 | Stacklight Green Channel |
GPIO_07 |
:red_square: Q4 | Stacklight Yellow Channel |
GPIO_12 |
:red_square: Q5 | Stacklight Red Channel |
GPIO_17 |
:yellow_square: I1 | S0 Home power meter |
GPIO_27 |
:yellow_square: I2 | Light switch |
GPIO_22 |
:yellow_square: I3 | Emergency Stop NO |
GPIO_10 |
:yellow_square: I4 | Emergency Stop NC |
GPIO_09 |
:yellow_square: I5 | Toggle Switch left |
GPIO_11 |
:yellow_square: I6 | Toggle Switch right |
GPIO_13 |
:yellow_square: I7 | Green button |
GPIO_26 |
:yellow_square: I8 | Red button |
GPIO_14 - 15 |
:blue_square: KNX | 4 Ch. Relay |
GPIO_18 |
:orange_square: PWM_0 | Dimmable LED |
GPIO_19 |
:orange_square: PWM_1 | Dimmable LED |
GPIO_23 |
:blue_square: 1-Wire | DS18B20 Temperature probe |
USB | USB | Arduino Uno (OpenPLC Slave Firmware) |
RJ45 Jack | EtherCAT | TBD |
Wifi | LAN access | Android Tablet as HMI |
Wifi | LAN access | Programming device (Laptop) |
There is an example chinesium Modbus I/O module on the testing board with the following information:
Parameter | Value |
---|---|
Device Type | Generic Modbus RTU Device |
Slave ID | 32 |
COM Port | /dev/ttyAMA3 |
Baudrate | 9600 |
Parity | None |
Data bits | 8 |
Stop bits | 1 |
Transmission Pause | 0 |
Discrete Inputs | Address 0, Size 0 |
Coils | Address 0, Size 4 |
Input Registers | Address 0, Size 0 |
Holding Registers - Read | Address 0, Size 0 |
Holding Registers - Write | Address 0, Size 0 |
OpenPLC is a Fully IEC 61131-3
compliant, open source, multi-hardware programmable logic controller suite.
Consisting of a separate runtime and editor, it can run on regular PCs as a soft PLC, as well as a multitude of embedded systems. (Think Beckhoff XAR / XAE)
I am currently creating a hardware layer for PiPLC at https://github.com/Chrismettal/OpenPLC_v3. This should allow easy adressing of all IO while enabling native use of Modbus and other interfaces. The regular "Rpi" layer should also be compatible, but I²C, Modbus and KNX might not work, and I1-8 / Q1-8 adressing might be a bit unintuitive (See GPIO mapping table)
Check out /src/OpenPLC
!
Home Assistant is an open source smart-home automation software, that provides logic, visualization and automation in a single place. It allows you to connect practically everything to your home under one interface, awakening your smart home.
Home Assistant seems to move away from local hardware IO a bit, instead focussing on devices in your LAN / WiFi. That doesn't mean though, that it isn't fully capable of running on an actual PLC, giving you control of your devices without a middle man or WiFi shenanigans. This is where the NC5121
KNX interface comes into play, which enables you to talk to a vast variety of off-the-shelf decentralised ACTUAL smart home components (No supplier apps, no accounts, no telemetry) without needing to go through an KNX-IP interface first.
TODO Upload example configuration.yaml
Codesys, like OpenPLC is a IEC 61131-3
compliant PLC runtime, compatible with PiPLC. It is not open source and the license for the RPI runtime costs about 55€. PiPLC was designed for OpenPLC but Codesys (as of 2024-01) is a much more robust runtime with more features.
As Codesys is proprietary, I won't be focussing much on it, but I want to make sure that most functions work well with PiPLC.
Check out /src/CODESYS
!
/boot/config.txt
# PiPLC
dtoverlay=uart3 # Enable UART3 for Modbus
dtoverlay=pi3-disable-bt # Disable Bluetooth so that UART0 is free for KNX
dtoverlay=w1-gpio,gpiopin=23 # Enable the 1-Wire pus on pin 23
dtoverlay=i2c-rtc,pcf8523 # Enable the I²C RTC
gpio=24,25,8,7,12,16,20,21=op,dl # Set all relay pins to outputs and turn them off
gpio=17,27,22,10,9,11,13,26=ip,pu # Set all digital input pins as pulled-up inputs
remove any mention of I²S or SPI if found, otherwise relay GPIOs might be driven HIGH on boot. Sometimes dtparam=spi=on
is set which will ruin your day so comment that one out if found.
/boot/cmdline.txt
remove console=serial0,115200
and/or console=ttyAMA0,115200
if found.
A full PiPLC consists of several subboards that need to be manufactured individually. Theoretically only the mainboard is technically required, as you could use wires to manually connect the Pi to the PLC as well as just not using the HMI as it is only a status display at the moment, but the existing 3D printable case assumes all boards to be used.
Only the main board has SMD parts that need to be assembled, so only one board will need to go through PCBA.
All boards are designed to be manufactured by JLCPCB, with BOMs using LCSC partnumbers attached. ALso all boards are to be manufactured with regular 1.6mm thickness, lead free HASL and 1oz copper weight.
This board houses all logic and is the only one that benefits from a PCBA service. All other boards plug into here, including the Raspberry Pi.
While not strictly required, this board houses frontpanel LEDs for status view of digital inputs and outputs, as well as 5V and 24V power status LEDs.
Additionally, the Wago header to plug into a KNX network is housed on this board.
Purely for decoration / labelling. No electrical connections here. Can theoretically be replaced by a sticker.
Riser board to give the Pi enough clearance to connect face-down to the mainboard. Can theoretically be replaced by a ribbon cable.
Riser board to connect the HMI board to the mainboard. Can theoretically be replaced by a ribbon cable
A 3D printable case is provided in /3d_printing
.
The case just snapfits together, after all boards were installed using M3x5mm screws.
Currently it will only fit a Raspberry Pi 4 and will not work with a Pi 5! You could modify the case to make a Pi 5 fit but I haven't done that yet.
The DIN-Rail mount on the back is not optimal yet so the compliant snap-action might now work, but since all boards I have manufactured are now deployed, I haven't yet gone around to updating the case.
The case is intended to be printed in a isolating and/or flame retardant filament like PC
or PETG VO
.
The following commands can be used to test your hardware configuration without installing PLC code or a full Home Assistant install. These are to be executed on a regular Pi OS install with raspi-gpio
installed.
raspi-gpio set 17,27,22,10,9,11,13,26 pu
raspi-gpio set 24,25,8,7,12,16,20,21 op
raspi-gpio get 17,27,22,10,9,11,13,26
raspi-gpio set 24 dh
/ raspi-gpio set 24 dl
i2cdetect -y 1
If you like my work please consider supporting me!
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.