DIY: Raspberry HMI

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.