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

2026-02-09 09:34 (20 days 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
Currently unrated
The author runs the application development company Cyberneura.
We look forward to discussing your development needs.

Categories

Archive