Overview
Morse-Pi is a browser-based Morse code trainer built for Raspberry Pi. The project now has a recommended native Rust backend for the fastest, most reliable install, plus an optional legacy Python backend if you want to tinker. A Pi Zero, Zero W, or Zero 2 W makes a great dedicated Morse trainer, but you can also practice from any browser with on-screen controls and keyboard shortcuts.
Hardware Requirements
Raspberry Pi Zero Setup
Raspberry Pi Zero, Zero W, or Zero 2 W; a 16 GB or larger microSD card; and a stable 5 V power supply.
Setup Computer
A Windows, macOS, or Linux computer with an SD card reader and Raspberry Pi Imager installed.
Optional Morse Hardware
Morse key or iambic paddle, jumper wires, and a piezo buzzer or small speaker for GPIO audio output.
Network Access
Wi-Fi is the easiest way to reach the web UI. Ethernet via adapter also works if your Zero setup supports it.
USB HID Mode
For keyboard-emulation mode, use a Pi Zero-family board with a real USB data cable connected to the port labeled USB, not PWR.
Recommended Board
Pi Zero 2 W is the sweet spot: same tiny form factor, but much faster build and better general responsiveness.
Install Raspberry Pi OS on the SD Card
Use Raspberry Pi Imager to write Raspberry Pi OS to your microSD card before you install Morse-Pi.
Install Raspberry Pi Imager
Download and install Raspberry Pi Imager on your Windows, macOS, or Linux computer. It is the official tool for writing Raspberry Pi OS to an SD card.
Insert Your microSD Card
Put the microSD card into your computer's card reader, then launch Raspberry Pi Imager.
Choose Device and OS
Click Choose Device and select your exact Pi Zero model. Then click Choose OS and select Raspberry Pi OS Lite. Use the 32-bit image for Pi Zero / Zero W, or 32-bit/64-bit for Pi Zero 2 W.
Configure Advanced Settings
Before writing the image, open the advanced settings prompt and set a hostname, username, password, Wi-Fi country, Wi-Fi SSID/password, locale, and enable SSH. That saves you from setup headaches later — like tiny keyboards and big sighs.
Write the Image
Select your storage device, confirm the erase/write prompt, and wait for Raspberry Pi Imager to finish. Safely eject the card when it is done.
Boot the Pi Zero
Insert the card into the Pi, power it on, and wait a minute or two for first boot. On a Pi Zero, use the port marked PWR for power and the port marked USB for data accessories or HID mode.
Update Raspberry Pi OS
Once your Pi Zero is online, connect over SSH or use a local terminal and bring the base system up to date before installing Morse-Pi.
sudo apt update
sudo apt upgrade -y
If the upgrade installs a new kernel, firmware, or USB modules, a reboot is a smart move before the Morse-Pi installer:
sudo reboot
curl is missing on a minimal image, install it with sudo apt install curl -y before running the Rust installer.
Install Morse-Pi with the Rust Installer
The Rust backend is the recommended install path. It compiles to a native binary, runs well on dedicated Pi hardware, and is the version the official docs now lead with.
curl -sSL https://raw.githubusercontent.com/Nerd-or-Geek/Morse-Pi/main/install-rust.sh | sudo bash
The installer automatically:
- Configures the USB HID keyboard gadget for supported Pi models
- Installs the Rust toolchain, build tools, and pigpio development packages
- Clones Morse-Pi to
/opt/morse-piand builds the Rust backend with GPIO support - Creates systemd services so Morse-Pi starts on boot
sudo reboot after the installer finishes so the kernel modules are fully active.
When the installer finishes, open the IP address printed on screen in your browser, for example:
http://192.168.1.42:5000
Already Running the Python Version?
You can switch an existing Python install to Rust without wiping your settings:
curl -sSL https://raw.githubusercontent.com/Nerd-or-Geek/Morse-Pi/main/transition-rust.sh | sudo bash
GPIO Wiring
Straight Key (Single-Pin Mode)
| Component | GPIO (BCM) | Physical Pin | Notes |
|---|---|---|---|
| Key signal | 17 |
Pin 11 | Active-low (key shorts pin to GND) |
| Key ground | GND | Pin 9 or 14 | |
| Speaker + | 18 |
Pin 12 | Speaker pin 1 |
| Speaker − | 13 |
Pin 33 | Speaker pin 2 for push-pull audio |
Iambic Paddle (Dual-Pin Mode)
| Component | GPIO (BCM) | Physical Pin | Notes |
|---|---|---|---|
| Dot paddle | 22 |
Pin 15 | Active-low |
| Dash paddle | 27 |
Pin 13 | Active-low |
| Speaker + | 18 |
Pin 12 | Speaker pin 1 |
| Speaker − | 13 |
Pin 33 | Speaker pin 2 for push-pull audio |
Pi GPIO Header Reference
Features
SEND Mode
Key Morse in real time and watch character-by-character decoding as you go.
ENCODE & DECODE
Translate text to Morse or practice decoding dots and dashes with quiz-style feedback.
SPEED Trainer
Practice sending at a target WPM and get scored on timing and accuracy.
Stats Tracking
Track accuracy, longest streak, and session history.
Farnsworth Timing
Stretch gaps between letters and words — great for beginners.
Multi-Pi Networking
Discover other Morse-Pi devices on your LAN and send messages between them.
USB HID Keyboard
Turn decoded Morse into real keystrokes on a connected computer through USB gadget mode.
Keyboard Control
Works without hardware — Space = straight key, Z/X = dot/dash paddles.
GPIO Support
Connect a real Morse key or iambic paddle via Raspberry Pi GPIO pins.
Push-Pull Audio
Drive a speaker from two GPIO pins in anti-phase for louder, cleaner sound.
Live Configuration
Adjust GPIO pins, tones, WPM, Farnsworth timing, theme, and keyboard settings from the browser.
Configuration
All settings are changed live from the CONFIG tab in the browser — no config files to hand-edit and no restart dance required for normal tweaks.
| Setting | Default | Description |
|---|---|---|
| Device Name | Morse Pi |
Name shown to other devices on the network |
| WPM | 20 |
Words per minute; all timing is derived from this |
| Pin mode | single |
single = straight key, dual = iambic paddle |
| Data pin | 17 |
BCM pin for straight key |
| Dot pin | 22 |
BCM pin for dot paddle |
| Dash pin | 27 |
BCM pin for dash paddle |
| Speaker pin | 18 |
Primary speaker GPIO (speaker pin 1) |
| Speaker pin 2 | 13 / null |
Optional second speaker GPIO for push-pull audio |
| Ground output pins | [] |
Optional GPIO pins driven LOW to act as software-configured grounds |
| Output type | speaker |
Use PWM speaker output or LED-style on/off output |
| Dot frequency | 700 Hz |
Tone pitch for dots |
| Dash frequency | 500 Hz |
Tone pitch for dashes |
| Volume | 75% |
PWM duty cycle |
| Farnsworth mode | Off |
Stretch letter/word gaps independently for learners |
| Letter gap mult | 2× |
How much longer the between-letter pause is |
| Word gap mult | 2× |
How much longer the between-word pause is |
| KB mode | letters |
Decoded letters or custom dot/dash key mapping for USB HID mode |
| Theme | dark |
Switch between dark and light UI themes |
/opt/morse-pi/morse-translator/settings.json and are preserved across updates and backend switches.
Keyboard Shortcuts
You can use your computer keyboard as a virtual Morse key — no hardware required!
| Key | Action |
|---|---|
| Space | Straight key (hold = dash, tap = dot) |
| Z | Dot paddle (dual-pin mode) |
| X | Dash paddle (dual-pin mode) |
Z and X together activates squeeze keying so the keyer alternates dots and dashes automatically.
Multi-Pi Networking
Multiple Morse-Pi devices on the same Wi-Fi or wired LAN will automatically discover each other — no configuration required.
Install on Multiple Pis
Install and run Morse-Pi on two or more Raspberry Pis on the same network.
Open Network Tab
Open the NETWORK tab in any browser connected to a Morse-Pi device.
Discover Devices
Discovered devices appear within a few seconds.
Send Messages
Type a message and hit SEND — it arrives at the other Pi and is played as audio.
Give each Pi a human-readable name in CONFIG → Device Name or directly in the NETWORK tab so peers are easier to recognize.
Service Management
Update a Rust Installation
To pull the latest code, rebuild the binary, and restart the service, use the dedicated Rust updater:
curl -sSL https://raw.githubusercontent.com/Nerd-or-Geek/Morse-Pi/main/update-rust.sh | sudo bash
Systemd Services
If you used the installer, Morse-Pi runs as a systemd service. These are the commands you will use most often:
# Check if running
sudo systemctl status morse-pi
# Restart the service
sudo systemctl restart morse-pi
# Stop the service
sudo systemctl stop morse-pi
# Last 50 log lines
sudo journalctl -u morse-pi -n 50
# View live logs
sudo journalctl -u morse-pi -f
# USB HID gadget service
sudo systemctl status morse-pi-hid
sudo systemctl restart morse-pi-hid
# GPIO daemon used by the Rust backend
sudo systemctl status pigpiod
sudo systemctl restart pigpiod
grep ExecStart /etc/systemd/system/morse-pi.service. If it points to morse-pi, you are on Rust. If it runs python3 app.py, you are on the legacy Python backend.
Troubleshooting
If Morse-Pi misbehaves, these are the fastest fixes to try before you start glaring at the Pi like it has personally offended you.
Web UI Won't Load
- Check the service:
sudo systemctl status morse-pi - Review logs:
sudo journalctl -u morse-pi -n 50 - Confirm the IP address with
hostname -I - Make sure port
5000is not blocked by a firewall
Rust Build Fails on Pi Zero
- Add or enlarge swap if the linker runs out of memory
- Install missing build tools:
sudo apt install build-essential -y - Install missing pigpio headers:
sudo apt install libpigpio-dev -y - If
cargois missing, runsource "$HOME/.cargo/env"
sudo dphys-swapfile swapoff
sudo sed -i 's/CONF_SWAPSIZE=.*/CONF_SWAPSIZE=512/' /etc/dphys-swapfile
sudo dphys-swapfile setup
sudo dphys-swapfile swapon
GPIO or Sound Issues
- Check
pigpiod:sudo systemctl status pigpiod - Verify the speaker and key wiring against the BCM pin table above
- Make sure the CONFIG tab matches your actual pin assignments
- Add your user to the
gpiogroup if needed:sudo usermod -aG gpio $USER
USB HID Keyboard Problems
- Reboot after install so
dwc2and gadget modules fully load - Check the HID service:
sudo systemctl status morse-pi-hid - Verify modules:
lsmod | grep dwc2 - If
g_etheris loaded first, it can block HID mode on Pi Zero boards
Networking Problems
- Put both Morse-Pi devices on the same subnet for automatic peer discovery
- Wait at least 5 seconds for UDP beacons to appear
- Test another Pi directly with
curl http://<peer-ip>:5000/status - Check
sudo ufw statusif peers or messages do not arrive
Still Stuck?
- Run the app manually to surface startup errors
- Rust backend:
cd /opt/morse-pi/morse-translator && ./morse-pi - Re-run the installer to repair services and dependencies
- Use the full official troubleshooting page linked below for deeper fixes
Project Structure
Morse-Pi/
├── install.sh ← fresh installer — legacy Python backend
├── install-rust.sh ← fresh installer — recommended Rust backend
├── transition-rust.sh ← migrate Python installs to Rust
├── update.sh ← updater — Python backend
├── update-rust.sh ← updater — Rust backend
├── docs/ ← official documentation site
├── morse-translator/ ← runtime files, templates, settings, stats
└── morse-translator-rust/
├── Cargo.toml ← Rust package manifest
└── src/
├── main.rs ← HTTP server and routes
├── gpio.rs ← GPIO integration via pigpio
├── sound.rs ← tone generation and keyer logic
├── keyboard.rs ← USB HID keyboard support
└── network.rs ← UDP peer discovery
/etc/systemd/system/morse-pi.service and /etc/systemd/system/morse-pi-hid.service so everything auto-starts on boot.
Resources
Official Morse-Pi Docs
The full documentation site with getting started, maintenance, USB HID, reference, and troubleshooting guides.
Read the official docs →Raspberry Pi Imager
The official tool for flashing Raspberry Pi OS to your SD card or USB storage.
Download Imager →Official Troubleshooting
Deeper fixes for Rust builds, GPIO, USB HID conflicts, and networking edge cases.
Open troubleshooting guide →