A digital notice board using Raspberry Pi hardware is best realized with an e-Paper display rather than a standard LCD. E-Paper requires zero power to maintain an image, eliminates standby glare, and draws roughly 15mA during a refresh cycle. When paired with a Raspberry Pi Zero 2 W, you get a headless, wall-mountable dashboard that can pull calendar events, MQTT office alerts, or local weather via WiFi, running for months on a standard 5V USB power bank.

This guide walks through building a low-power notice board using the Pimoroni Inky wHAT (400x300 resolution). We will cover the exact pin mappings, the Bookworm OS configuration required to bypass recent GPIO library deprecations, and provide a complete, error-handled Python script.

Project Spec Sheet & Difficulty Rating

Parameter Specification
Difficulty Intermediate (Requires CLI comfort and basic SPI knowledge)
Time to Build 90 - 120 minutes
Estimated Cost $65 - $80 USD (Board + Display + PSU)
Target Board Raspberry Pi Zero 2 W (2021 variant, 512MB RAM)
Target OS Raspberry Pi OS Lite (Bookworm, 64-bit, Headless)
Power Draw ~120mA idle (WiFi on), ~15mA peak during display refresh

Hardware Parts List & SPI Pin Mapping

Do not substitute the Pi Zero 2 W with the original Pi Zero W for this build; the original single-core CPU struggles with the Pillow image rendering pipeline in Python 3.11, resulting in refresh prep times exceeding 10 seconds. The Zero 2 W’s quad-core Cortex-A53 handles the rasterization in under 800ms.

Required Components

  • Compute: Raspberry Pi Zero 2 W (with pre-soldered 40-pin GPIO header)
  • Display: Pimoroni Inky wHAT - Black/White/Red (Product Code: PIM324, 400x300)
  • Storage: 16GB or 32GB microSD card (Class 10 / A1 rated)
  • Power: 5V 2.5A USB-C power supply (Official Raspberry Pi PSU recommended to prevent brownouts during WiFi TX spikes)
  • Enclosure (Optional): Pimoroni Inky wHAT picture frame case or custom 3D printed backplate

SPI0 & Control Pin Mapping

The Inky wHAT connects via the primary SPI bus (SPI0) and uses an I2C EEPROM for auto-detection. Below is the physical wiring map using standard BCM numbering. The display’s ribbon cable plugs directly into the Pi’s 40-pin header; no jumper wires are required if using the HAT format.

Display Function Pi BCM Pin Pi Physical Pin Protocol / Notes
MOSI (Data) GPIO 10 19 SPI0 MOSI
SCLK (Clock) GPIO 11 23 SPI0 SCLK
CS (Chip Select) GPIO 8 24 SPI0 CE0
DC (Data/Command) GPIO 22 15 Output (High=Data, Low=Cmd)
RST (Reset) GPIO 27 13 Output (Active Low)
BUSY GPIO 17 11 Input (High when controller busy)
EEPROM SDA GPIO 2 3 I2C1 SDA (For auto-detect)
EEPROM SCL GPIO 3 5 I2C1 SCL (For auto-detect)

OS Configuration & Assembly Steps

Raspberry Pi OS Bookworm introduced significant changes to GPIO access, deprecating the legacy RPi.GPIO library in favor of lgpio. The Pimoroni inky library has been updated to support this, but you must ensure your system packages are correctly aligned.

  1. Flash the OS: Use Raspberry Pi Imager to flash Raspberry Pi OS Lite (64-bit) to your microSD card. In the OS Customisation menu, enable SSH (password or key), set your WiFi credentials, and set the hostname to noticeboard.local.
  2. Boot and SSH: Insert the SD card, power the Pi, and SSH into it via ssh user@noticeboard.local.
  3. Enable Hardware Interfaces: Run sudo raspi-config. Navigate to Interface Options and enable both SPI and I2C. Reboot when prompted.
  4. Install Dependencies: Bookworm uses PEP 668, which prevents global pip installs to protect system packages. You must use a virtual environment or the --break-system-packages flag. For a dedicated kiosk/notice board, a virtual environment is best practice:
    sudo apt update && sudo apt install -y python3-venv python3-pil i2c-tools
    mkdir ~/noticeboard && cd ~/noticeboard
    python3 -m venv venv
    source venv/bin/activate
    pip install inky pillow
  5. Verify I2C Detection: Run i2cdetect -y 1. You should see a device at address 0x50 (the display's EEPROM). If it is missing, the Pi cannot auto-detect the display color/type.
Callout Tip: If you are mounting the Pi Zero 2 W directly behind the display in a tight enclosure, apply a small copper heatsink to the Pi's SoC. The image rasterization process spikes the CPU to 100% for a few seconds, and thermal throttling in an enclosed space will cause WiFi dropouts.

Python Notice Board Code (Target: Pi Zero 2 W)

The following script initializes the display, draws a formatted text notice using Pillow, and pushes it to the e-Paper matrix. It includes robust error handling for the most common SPI and I2C failure modes encountered on the workbench.

#!/usr/bin/env python3
"""
Digital Notice Board Script
Target: Raspberry Pi Zero 2 W / Pi OS Bookworm (64-bit)
Display: Pimoroni Inky wHAT (Black/White/Red)
"""

import sys
import os
from PIL import Image, ImageDraw, ImageFont

try:
    from inky.auto import auto
except ImportError:
    print("ERROR: 'inky' library not found. Activate your venv and run: pip install inky pillow")
    sys.exit(1)

def render_notice(display, title, body_text):
    # Create a blank image matching the display resolution
    img = Image.new("P", (display.WIDTH, display.HEIGHT))
    draw = ImageDraw.Draw(img)

    # Map colors: 0=Black, 1=White, 2=Red (for 3-color displays)
    BLACK = 0
    WHITE = 1
    RED = 2

    # Load default fonts (Pillow's default bitmap font is used here for zero-dependency reliability)
    # For production, load a TrueType font: ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 24)
    title_font = ImageFont.load_default()
    body_font = ImageFont.load_default()

    # Draw Background and Border
    draw.rectangle((0, 0, display.WIDTH, display.HEIGHT), fill=WHITE)
    draw.rectangle((0, 0, display.WIDTH - 1, display.HEIGHT - 1), outline=BLACK, width=2)

    # Draw Title (Red)
    draw.text((20, 20), title, fill=RED, font=title_font)
    draw.line((20, 40, display.WIDTH - 20, 40), fill=BLACK, width=2)

    # Draw Body Text (Black)
    draw.text((20, 60), body_text, fill=BLACK, font=body_font)

    # Push to display
    display.set_image(img)
    display.show()
    print("Notice successfully rendered to e-Paper.")

def main():
    try:
        # Auto-detect display type and color via I2C EEPROM
        display = auto()
        print(f"Detected Display: {display.colour} {display.resolution}")
        
    except FileNotFoundError as e:
        # Catches disabled SPI interface
        print(f"CRITICAL SPI ERROR: {e}")
        print("FIX: Run 'sudo raspi-config' and enable SPI under Interface Options.")
        sys.exit(1)
        
    except RuntimeError as e:
        # Catches missing EEPROM or loose ribbon cable
        print(f"DETECTION ERROR: {e}")
        print("FIX: Check ribbon cable seating. Run 'i2cdetect -y 1' to verify EEPROM at 0x50.")
        sys.exit(1)

    except PermissionError as e:
        # Catches user not in SPI group
        print(f"PERMISSION ERROR: {e}")
        print("FIX: Run 'sudo usermod -a -G spi,gpio,i2c $USER' and reboot.")
        sys.exit(1)

    # Define Notice Content
    notice_title = "OFFICE NOTICE:"
    notice_body = (
        "1. Kitchen fridge cleaned out Friday at 5 PM.\n"
        "2. Fire drill scheduled for Tuesday 10:00 AM.\n"
        "3. IT Maintenance tonight from 11 PM - 2 AM.\n"
        "\n"
        "System Status: All servers operational."
    )

    render_notice(display, notice_title, notice_body)

if __name__ == "__main__":
    main()

Debugging: First Three Things to Check When It Fails

When building embedded SPI projects, the hardware-software handshake is where 90% of failures occur. If your script crashes, check these three specific failure modes in order.

1. The SPI Device Node is Missing

Exact Error String: FileNotFoundError: [Errno 2] No such file or directory: '/dev/spidev0.0'

Ranked Causes:

  1. SPI is disabled in the kernel: You forgot to enable it in raspi-config, or the dtparam=spi=on line is missing from /boot/firmware/config.txt.
  2. Device Tree Overlay conflict: Another HAT or overlay has claimed SPI0. Check dtoverlay lines in your config.

2. The Auto-Detect Fails

Exact Error String: RuntimeError: No display type was provided and the auto-detect failed.

Ranked Causes:

  1. Loose FPC Ribbon Cable: The 24-pin FPC cable connecting the glass to the PCB is not fully seated or the locking latch is open. Reseat it and lock the latch.
  2. I2C Bus Failure: The display's onboard EEPROM (which tells the Pi what screen is attached) cannot be read. Verify I2C is enabled and run i2cdetect -y 1 to look for address 0x50.
  3. Manual Override Required: If the EEPROM is fried, you can bypass auto-detect by initializing manually: from inky import InkyWHAT; display = InkyWHAT('red').

3. Permission Denied on GPIO/SPI

Exact Error String: PermissionError: [Errno 13] Permission denied: '/dev/spidev0.0'

Ranked Causes:

  1. Missing Group Memberships: In Bookworm, the default pi (or your custom user) is not always automatically added to the hardware groups. Fix with: sudo usermod -a -G spi,gpio,i2c $USER, then log out and back in.
  2. Running via Cron without Environment: If running this script from crontab, ensure you are using the absolute path to the Python executable inside your virtual environment (e.g., /home/user/noticeboard/venv/bin/python3 /home/user/noticeboard/main.py).

Extending or Simplifying the Build

To Simplify: If the 400x300 resolution of the Inky wHAT is overkill and you only need to display a single line of text (like a "Do Not Disturb" sign or a build server status), downgrade to the Inky pHAT (250x122). It uses the exact same Python library and pinout but costs roughly 40% less and renders in under 200ms.

To Extend: To make the board dynamic without SSH-ing into the Pi to edit the Python script, integrate an MQTT client. By adding the paho-mqtt library, the Pi can subscribe to a local Mosquitto broker topic (e.g., office/notices/main). When a message is published to that topic, the script triggers a partial or full display refresh. This allows you to update the notice board from a Home Assistant dashboard or a simple web form on your phone.

Warning: E-Paper displays suffer from "ghosting" if updated too frequently without a full black-white inversion cycle. The Inky wHAT is rated for ~10,000 full refreshes. Do not set your cron job to refresh the screen more than once every 15 minutes, or you will degrade the microcapsule matrix prematurely.

Frequently Asked Questions

Can I use a Raspberry Pi 5 for this digital notice board?

Yes, but it is overkill and introduces a physical compatibility quirk. The Raspberry Pi 5 uses a new RP1 southbridge chip, which changes the PCIe and GPIO addressing. While the inky library supports the Pi 5 via rpi-lgpio, the Pi 5 draws significantly more idle power (~2.5W vs the Zero 2 W's ~0.7W), defeating the low-power advantage of an e-Paper notice board. Furthermore, the Pi 5's physical footprint requires a larger enclosure. Stick to the Zero 2 W unless you need to run local LLM inference or heavy web scraping alongside the display rendering.

How do I update the notice board text without SSH?

The most robust method for a headless setup is to host a lightweight Flask or FastAPI web server on the Pi, or use an MQTT broker. If you want a zero-code solution, mount a shared SMB/NFS folder on the Pi. Have your Python script watch a specific notice.txt file in that directory using the watchdog library. When you edit the text file from your main PC, the Pi detects the file change and triggers a display refresh automatically.

Why is my e-Paper display flashing red and white repeatedly?

This is the display controller's "clear" or "reset" cycle. It happens when the display.show() function is called, but the script immediately exits or the Pi loses power before the BUSY pin goes high (indicating the refresh is complete). E-Paper updates are asynchronous; the Pi sends the data over SPI in milliseconds, but the physical screen takes 15–20 seconds to shift the pigment particles. Ensure your Python script does not terminate or cut power to the GPIO pins until the inky library confirms the BUSY state has cleared.

Is a digital notice board using Raspberry Pi suitable for outdoor use?

E-Paper is excellent for outdoor visibility because it is reflective (like paper) and suffers zero washout in direct sunlight. However, the temperature range is the limiting factor. Standard e-Paper displays (including the Inky wHAT) cannot physically refresh below 0°C (32°F) because the microcapsule fluid freezes, and they degrade rapidly above 50°C (122°F). If your outdoor enclosure experiences freezing winters or direct summer greenhouse heat, the display will fail to update or suffer permanent image retention. For outdoor deployments, you must add a thermostatically controlled heater pad and UV-resistant polycarbonate glazing.