
DIY: Raspberry HMI
Building a touch screen HMI with openplc and python/qt6 on Raspberry Pi
Updated: January 4, 2025 at 09:50 AM
Repurposing the remains of one too many unfinished projects, and out of pure spite of not wanting to learn yet another proprietry software to program an off the shelf HMI/PLC, I have decided to DIY a PLC/HMI system and enclosure using a 7" Touch LCD, Raspberry Pi 3B, OpenPLC, and Python/QT.
Bill of Materials
Repurposed Parts
- 1x 7" Touch Screen LCD (XC9026) Jaycar NZ
- 1x Raspberry Pi 3B v1.2 , probably from PBTech.
Cables and Adaptors
- 1x HDMI 90deg Adaptor (33 - Up) Aliexpress
- 1x HDMI Flat Patch (30cm) Aliexpress
- 1x Micro USB Right Angle Cable (25cm - Up) Aliexpress
- 1x Micro USB for powering the lot
Hardware
- 4x M2.5 x 5mm Button Socket (Pi x 4)
- 4x M2.5 x 20mm SHC (Screen/Pi to Case)
- 4x M2.5 Nut (Screen/Pi/Case Stack)
- 4x M4 x 8mm Button Socket (Case Covers)
- 4x M5 Nut (Securing the case to openbuilds 4040)
Printed Bits
- Case (Front/Back/Four Sides)
- Raspberry Pi Mount
- Stand-offs
Other bits
- 1x 24VDC -> 5VDC Converter Aliexpress
- Because the rest of the system is 24VDC.
Operating System
- Image Creation: Raspberry Pi Imager to write Raspberry Pi OS Lite (32-bit) to an SD card with some options preconfigured.
- OS Details: Debian Bookworm, no desktop environment.
- Preconfigured: Added user
steven
with pub/pri SSH keys, set hostname, and TZ.
Configurations
/boot/firmware/config.txt
Configuration for the 7" LCD as noted in the XC9026 manual:
hdmi_group=2
hdmi_mode=87
hdmi_cvt=1024 600 60 6 0 0 0
Disable Bluetooth:
dtoverlay=disable-bt
Comment out unnecessary options:
#dtparam=audio=on
#camera_auto_detect=1
Raspi-config
- Interfaces: Disable unused interfaces: RPi Connect, VNC, SPI, I2C.
- Localization:
en-nz
locale,Pacific/Auckland
timezone,US
keyboard. Change Wi-Fi Country:NZ
- Advanced: Expand filesystem, enable predictable network interface names.
Static IP
nmcli connection show
sudo nmcli con mod "Wired connection 1" ipv4.addresses 192.168.1.100/24 ipv4.method manual
sudo nmcli con mod "Wired connection 1" ipv4.gateway 192.168.1.1
sudo nmcli con mod "Wired connection 1" ipv4.dns "8.8.8.8,8.8.4.4"
sudo nmcli c down "Wired connection 1" && sudo nmcli c up "Wired connection 1"
Enable Password SSH
Uncomment in /etc/ssh/sshd_config
:
PasswordAuthentication yes
Disable Unnecessary Services
- Disable daily updates:
sudo systemctl mask apt-daily-upgrade
sudo systemctl mask apt-daily
sudo systemctl disable apt-daily-upgrade.timer
sudo systemctl disable apt-daily.timer
- Remove Avahi/mDNS:
sudo apt remove --purge avahi-daemon
- Disable Bluetooth, ModemManager, and Wi-Fi:
sudo apt remove --purge modemmanager
sudo systemctl disable bluetooth.service hciuart.service wpa_supplicant.service
sudo apt remove --purge bluez
sudo apt autoremove --purge
Software
Update package repositories
sudo apt-get update sudo apt upgrade
Git
sudo apt-get install git
OpenPLC Runtime
cd ~
git clone https://github.com/thiagoralves/OpenPLC_v3.git
cd OpenPLC_v3
./install.sh rpi
Once built, access it at 192.168.1.100:8080.
HMI Setup
Create HMI User
sudo adduser hmi
sudo usermod -aG sudo,tty,video hmi
su hmi
Enable auto-login via raspi-config
: System Options -> Boot / Auto Login -> Console Autologin.
Clone GitLab Repo
ssh-keygen
cat ~/.ssh/id_rsa.pub
# Add key to GitLab
git clone [email protected]:dripr/hardware/diverter/hmipythonqt.git
mv hmipythonqt/ hmi
cd hmi
Python Environment
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Install QT Libraries
There's a weird break with an upstream lib, so we will install this globally via apt and then copy it into our venv.
sudo apt-get install python3-pyqt6
# Copy library to venv
cp -R /usr/lib/python3/dist-packages/PyQt6 ./.venv/lib/python3.11/site-packages/PyQt6
Install X
sudo apt install xserver-xorg xinit x11-xserver-utils
Side-quest for later: Hasn't raspberry OS desktop version moved to wayland?
Allow hmi user (and therefore python via os.process) to run sudo shutdown without a password
Add the following to sudoers file after user/group rules
sudo visudo
# Allow HMI to trigger shutdown without password
hmi ALL=(ALL) NOPASSWD: /usr/sbin/shutdown
Auto-start Configuration
Start Script
Create ~/.bash_profile
:
if [[ $(tty) == "/dev/tty1" ]]; then
~/start_hmi.sh
fi
Create ~/start_hmi.sh
:
Silence stdout and stderr from Xorg.
#!/bin/bash
exec startx -- vt1 -nocursor >/dev/null 2>&1
Make it executable:
chmod +x ~/start_hmi.sh
X Server Configuration
Create ~/.xinitrc
:
#!/bin/bash
# Disable screen blanking
xset s off
xset s noblank
xset -dpms
# Set QT environment
export QT_QPA_PLATFORM=xcb
# Perform a git pull to ensure the latest code
if ping -c 1 8.8.8.8 &> /dev/null; then
echo "Network is up. Pulling latest changes..."
cd ./hmi || exit
git pull || echo "Git pull failed. Continuing with existing code."
cd - || exit
else
echo "Network is down. Skipping git pull."
fi
# Activate venv and run app
source ./hmi/.venv/bin/activate
python ./hmi/app/app.py
Make it executable:
chmod +x ~/.xinitrc
Splash Screen
This was a bit of a pointless excersize because by the time the display bit is ready, we're already loged in and about to fire up the HMI interface.
Install Plymouth (Boot Splash Manager)
sudo apt-get install plymouth plymouth-themes
Create a Custom Splash Theme
sudo mkdir /usr/share/plymouth/themes/mylogo
sudo cp ./hmi/splash.png /usr/share/plymouth/themes/mylogo/
Create a mylogo.plymouth
configuration file:
sudo nano /usr/share/plymouth/themes/mylogo/mylogo.plymouth
[Plymouth Theme]
Name=MyLogo
Description=Custom Splash Screen with Company Logo
ModuleName=script
[script]
ImageDir=/usr/share/plymouth/themes/mylogo
ScriptFile=/usr/share/plymouth/themes/mylogo/mylogo.script
Create a mylogo.script
file:
sudo nano /usr/share/plymouth/themes/mylogo/mylogo.script
wallpaper_image = Image("splash.png");
wallpaper_image.SetZ(100);
wallpaper_image.Show();
Enable the Custom Theme (and rebuild the init image)
sudo plymouth-set-default-theme -R mylogo
Hide Boot Messages
sudo nano /boot/firmware/cmdline.txt
Add the following to the cmdline
splash quiet plymouth.ignore-serial-consoles
Quiet down the login and xorg messages
Remove MOTD
sudo chmod -x /etc/update-motd.d/*
sudo rm /etc/motd /var/run/motd.dynamic
Todo/Improvements
- GPIO Adjustment: Current mounting of RPI requires bending GPIO pins to fit the overly chonky HDMI connector. If we revise the design, we could either redice the height of the standoffs or adjustthe Raspberry Pi mounting position for better clearance.
- Case Rigidity: Case sides tend to warp at the top and bottom edges. But, i haven't screwed it together yet.
- OpenPLC Runtime Build: Building the runtime on the Pi is slow. Like not 90's dial-up slow, but go make a cup of coffee slow. We could pre-compile for faster setup.