How to turn Orange Pi Zero 2W into a Web Signage Display

2026-02-09 09:34 (4 months ago)
Vt1 Truce
Play a song themed on this article

Introduction

The Orange Pi Zero 2W is a compact single-board computer with an Allwinner H618 SoC. It has HDMI output and runs Linux, making it suitable as a web signage (digital signage) terminal.

This article covers two goals:

  1. Auto-starting Chromium in kiosk mode to display a web page fullscreen on power-up
  2. Using GPIO-connected tactile switches for physical button control of display power and browser reload

Part 1: Web Signage with Chromium Kiosk Mode

Prerequisites

sudo apt update
sudo apt install -y xserver-xorg xinit chromium x11-xserver-utils xdotool fonts-noto-cjk

kiosk.sh — Chromium Startup Script

#!/bin/bash

export DISPLAY=:0
xhost +local:

# Rotate display (for vertical monitors used horizontally)
xrandr --output HDMI-1 --rotate left

# Disable screen blanking
xset s off -dpms s noblank

sleep 2

# Launch Chromium as non-root user
# dbus-run-session: creates a temporary D-Bus session (not available at boot)
# --disable-gpu: Mali G31 GPU fails Chromium initialization
sudo -u orangepi \
    DISPLAY=:0 \
    HOME=/home/orangepi \
    dbus-run-session \
    chromium --kiosk --noerrdialogs --disable-infobars \
        --disable-session-crashed-bubble \
        --disable-gpu \
        --start-fullscreen \
        --window-size=1920,480 \
        --window-position=0,0 \
        "https://your-dashboard-url.example.com/"

kiosk.service — systemd Service

[Unit]
Description=Kiosk Browser
After=multi-user.target systemd-user-sessions.service
Conflicts=getty@tty1.service
StartLimitIntervalSec=0

[Service]
Type=idle
User=root
Environment=DISPLAY=:0
ExecStartPre=/bin/udevadm settle --timeout=30
ExecStartPre=/bin/bash -c 'for i in $(seq 1 30); do for f in /sys/class/drm/card*-HDMI-A-*/status; do [ -f "$f" ] && grep -q "^connected$" "$f" && exit 0; done; sleep 2; done; echo "HDMI not detected"; exit 1'
ExecStart=/usr/bin/startx /home/orangepi/kiosk.sh -- :0 vt1
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Key settings:

  • Conflicts=getty@tty1.service — Prevents getty from stealing VT1 from X server
  • StartLimitIntervalSec=0 — Unlimited restart attempts
  • udevadm settle — Waits for hardware initialization
  • HDMI connection polling — Waits up to 60 seconds for display connection

Part 2: GPIO Physical Buttons

Hardware Wiring

H618 GPIO operates at 3.3V with built-in pull-up resistors. Connect tactile switches between GPIO pins and GND (Active LOW). No external resistors needed.

GPIO pin ---[tactile switch]--- GND

Linux GPIO numbers are calculated as: (port_number × 32) + pin_number

Button Pin GPIO# Function
Left PI3 259 Display ON/OFF
Center PI16 272 Browser reload (Shift+F5)
Right PI4 260 Unassigned

switch_daemon.py — GPIO Button Daemon

Uses gpiomon (libgpiod) for kernel interrupt-based monitoring with near-zero CPU usage. See the Japanese version for the full source code with detailed comments.

switch-daemon.service

[Unit]
Description=GPIO Switch Daemon
After=multi-user.target systemd-user-sessions.service

[Service]
Type=simple
User=root
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/orangepi/.Xauthority
ExecStartPre=/bin/udevadm settle --timeout=30
ExecStart=/usr/bin/python3 /home/orangepi/switch-server/switch_daemon.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Troubleshooting

  • Screen flashes then shows terminal: Add Conflicts=getty@tty1.service
  • D-Bus errors: Add dbus-run-session before chromium command
  • GPU errors: Add --disable-gpu flag to Chromium
  • Buttons not responding: Ensure udevadm settle in ExecStartPre
Please rate this article (No signup or login required)
Currently unrated
The author runs the application development company Cyberneura.
We look forward to discussing your development needs.

Categories

Archive