Skip to content

Repository files navigation

Portable Wi-Fi AirPlay Audio Receiver

A battery-powered AirPlay audio receiver using Raspberry Pi Zero 2W with I2S DAC, OLED display, rotary encoder control, and elegant LED feedback.

Table of Contents


Hardware Requirements

Main Components

ComponentModel/SpecNotes
Single Board ComputerRaspberry Pi Zero 2WMust be 2W for WiFi
DACPCM5102 I2S DAC112dB SNR, line-level output
Display0.96" OLED SSD1306128x64, I2C interface
EncoderEC11 / KY-040Rotary encoder with push button
LEDWS2812B (NeoPixel)Single RGB LED
Audio Output3.5mm AUX jackFemale panel mount

Power System

ComponentSpecNotes
Battery3.7V 2000mAh Li-ion~3 hours runtime
ChargerTP4056 moduleWith battery protection
Boost Converter3.7V to 5V, 2A+MT3608 or similar
Power SwitchSPST toggleBetween battery and boost
DiodeIN5819 SchottkyReverse polarity protection
Capacitor1000uF 10VOn 5V rail for stability

GPIO Pinout

Complete Pin Reference

ComponentSignalGPIO (BCM)Physical PinWire Color (suggested)
I2S DAC (PCM5102)
BCKGPIO18Pin 12Yellow
LCK (LRCK)GPIO19Pin 35Orange
DINGPIO21Pin 40Green
OLED Display
SDAGPIO2Pin 3Blue
SCLGPIO3Pin 5Purple
Rotary Encoder
CLK (A)GPIO17Pin 11White
DT (B)GPIO27Pin 13Gray
SW (Button)GPIO22Pin 15Brown
WS2812B LED
DINGPIO10Pin 19Green

Power Connections

ComponentPowerGround
PCM5102 DAC3.3V (Pin 1 or 17)GND
OLED Display3.3VGND
Rotary Encoder3.3VGND
WS2812B LED5V (Pin 2 or 4)GND

Important: The WS2812B LED requires 5V power, not 3.3V. Use a 330 ohm resistor on the data line.


Installation Guide

Step 1: Flash Raspberry Pi OS

Use Raspberry Pi Imager to flash the SD card:

  1. Download and open Raspberry Pi Imager

  2. Click Choose OS > Raspberry Pi OS (other) > Raspberry Pi OS Lite (32-bit)

  3. Click Choose Storage > Select your SD card

  4. Click the gear icon or press Ctrl+Shift+X for advanced options

  5. Configure:

    SettingValue
    Set hostnameairplay
    Enable SSHUse password authentication
    Set username and passworde.g., ravi / yourpassword
    Configure wireless LANEnter your WiFi SSID & password
    Wireless LAN countryYour country code (IN, US, GB, etc.)
  6. Click Save, then Write

Step 2: First Boot & SSH

  1. Insert SD card into Raspberry Pi Zero 2W
  2. Power on and wait 2-3 minutes for first boot
  3. Find your Pi's IP (check router admin page or use ping airplay.local)
  4. SSH into your Pi:
    ssh youruser@airplay.local

Step 3: Copy Project Files

From your computer:

scp -r /path/to/AirplayPortable youruser@airplay.local:~/airplay

Or on the Pi using git:

git clone https://github.com/Techposts/Airplay-Portable.git ~/airplay

Step 4: Run Installation

cd~/airplay
chmod +x install.sh
sudo ./install.sh

What the installer does:

  • Updates system packages
  • Installs build dependencies
  • Enables I2C and SPI interfaces
  • Configures I2S DAC overlay
  • Enables hardware watchdog
  • Builds NQPTP (AirPlay 2 timing)
  • Builds Shairport Sync (AirPlay receiver)
  • Sets up Python virtual environment
  • Installs Python dependencies
  • Creates systemd services
  • Adds user to hardware groups (gpio, i2c, spi, audio)

Installation takes 20-40 minutes on Pi Zero 2W.

Step 5: Reboot

sudo reboot

Step 6: Verify Installation

# Check AirPlay service
sudo systemctl status shairport-sync
# Check UI service
sudo systemctl status airplay-ui
# View logs
journalctl -u airplay-ui -n 30 --no-pager

Hardware Assembly

I2S DAC (PCM5102) Wiring

PCM5102 PinConnect ToNotes
VIN3.3V (Pin 1)Power
GNDGND (Pin 6)Ground
BCKGPIO18 (Pin 12)Bit clock
DINGPIO21 (Pin 40)Data in
LCKGPIO19 (Pin 35)Left/Right clock
FMTGNDI2S format
XMT3.3VSoft unmute (active high)
SCKGNDUse internal clock

OLED Display (SSD1306 I2C) Wiring

OLED PinConnect ToNotes
VCC3.3V (Pin 1)Power
GNDGND (Pin 9)Ground
SDAGPIO2 (Pin 3)I2C Data
SCLGPIO3 (Pin 5)I2C Clock

Rotary Encoder (EC11/KY-040) Wiring

Encoder PinConnect ToNotes
GNDGND (Pin 14)Ground
+3.3V (Pin 17)Power
CLKGPIO17 (Pin 11)Rotation signal A
DTGPIO27 (Pin 13)Rotation signal B
SWGPIO22 (Pin 15)Push button

WS2812B LED Wiring

LED PinConnect ToNotes
VCC5V (Pin 2)Must be 5V, not 3.3V
GNDGND (Pin 20)Ground
DINGPIO10 (Pin 19)Via 330 ohm resistor

Features

Audio

  • High-quality I2S DAC output (112dB SNR)
  • Hardware digital volume control via ALSA
  • Volume persisted across reboots
  • Multi-room AirPlay 2 sync support
  • Audio profiles: Normal, Night Mode (max 50% volume), Loud

Controls (Rotary Encoder)

ActionFunction
Rotate clockwiseVolume up
Rotate counter-clockwiseVolume down
Short press (<2s)Open menu
Long press (2-5s)Mute/unmute
Very long press (>5s)Force AP mode

LED Status Indicators

StateLED BehaviorMeaning
BootingWhite fade inSystem starting
ReadySolid greenConnected, not playing
PlayingBlinking greenStreaming audio
AP ModeSlow amber blinkWiFi setup mode
Low VoltageSolid redPower issue detected
ErrorRapid red blink (3x)Problem detected
DisabledOffLED turned off in settings

OLED Display

Home Screen:

  • Device name
  • Playback status (Ready/Streaming)
  • Volume level with progress bar

Now Playing Screen:

  • Track title (with auto-scrolling for long titles)
  • Artist name (with auto-scrolling)
  • Volume bar

Menu System:

  • Audio > Volume, Mute, Mode (Normal/Night/Loud)
  • Network > Status, Saved WiFi (up to 5), Start AP Mode, Device Name
  • Display > Auto Sleep, Sleep Timer, Clock Saver, LED Enabled, LED Brightness
  • Power > Power Saver, Restart Streaming
  • System > Reboot, Shutdown, About (shows CPU temp, memory, uptime, WiFi signal)

Power Management

The device includes comprehensive power management for battery-powered operation.

Features

FeatureDescription
Hardware WatchdogAuto-reboots device if app hangs (15s timeout)
CPU Scalingpowersave when idle, ondemand when playing
WiFi Power SaveReduces WiFi power consumption when idle
Voltage MonitoringDetects undervoltage via vcgencmd get_throttled
Display SleepDims after 30s, turns off or shows clock after 60s
Clock ScreensaverShows time and power status when idle
Safe ShutdownGraceful shutdown after 3 consecutive low voltage readings

How It Works

  1. Idle State: CPU runs at minimum frequency, WiFi in power save mode
  2. Playing State: CPU switches to on-demand scaling for responsive audio
  3. User Input: Any encoder action wakes the display immediately
  4. Low Voltage: LED turns red, 3 consecutive readings triggers safe shutdown

Battery Life Tips

  • Enable power saver mode (default: on)
  • Use shorter display timeout
  • Disable LED if not needed
  • Keep volume reasonable (lower = less amplifier power)

Settings (via OLED Menu or Web UI)

SettingOptionsDefault
Display SleepOn/OffOn
Sleep After15-120 seconds60s
Clock SaverOn/OffOn
Power SaverOn/OffOn
Audio ModeNormal/Night/LoudNormal

Web UI Settings

When connected to WiFi, access the settings page at http://[device-ip]

Available Settings

SectionSettings
DeviceDevice Name (shown in AirPlay)
AudioVolume (0-100%), Mute toggle
LEDEnable/Disable, Brightness (5-50%)
Power & DisplayDisplay Sleep, Sleep timeout, Power Saver
NetworkWiFi info, Change WiFi button
Track Info (MQTT)Enable MQTT metadata, Broker settings
SystemPower status, Restart AirPlay, Reboot button

Features

  • Auto-save on change
  • Real-time power status monitoring
  • Responsive design for mobile

Changing WiFi Networks

The device saves up to 5 WiFi networks and automatically connects to any available saved network on startup.

Option 1: Via Encoder (Recommended)

  1. Press and hold encoder button for 5 seconds
  2. LED turns amber (blinking) - AP mode active
  3. Connect phone/laptop to "AirPlay-Setup" WiFi network
  4. Open browser to http://192.168.4.1
  5. Select new WiFi network and enter password
  6. Device reboots and connects to new network

Option 2: Via Web UI (When Connected)

  1. Find device IP on your router or check the display
  2. Open browser to http://[device-ip]
  3. Click "Change Wi-Fi Network" in settings
  4. Device enters AP mode for reconfiguration

Viewing Saved Networks

Navigate to Network > Saved WiFi in the OLED menu to see your saved networks.


Troubleshooting

Service Issues

# Check service status
sudo systemctl status airplay-ui
sudo systemctl status shairport-sync
# View detailed logs
journalctl -u airplay-ui -n 50 --no-pager
# Run manually for debuggingcd~/airplay
source venv/bin/activate
python3 src/main.py

Audio Issues

# Check if DAC overlay is loaded
aplay -l
# Test audio output
speaker-test -t sine -f 440 -c 2 -D hw:0
# Check ALSA mixer
amixer -c 0

Display Issues

# Check I2C is enabled
ls /dev/i2c*# Scan for I2C devices (OLED should show at 0x3C)
sudo i2cdetect -y 1

AirPlay Not Visible

# Check shairport-sync
sudo systemctl status shairport-sync
# Check avahi (mDNS/Bonjour)
sudo systemctl status avahi-daemon
# Restart services
sudo systemctl restart shairport-sync avahi-daemon

Project Structure

airplay/
├── install.sh # Installation script
├── device_config.json # Runtime configuration
├── config/
│ ├── shairport-sync.conf # AirPlay config template
│ ├── asound.conf # ALSA configuration
│ ├── hostapd.conf # AP mode hotspot config
│ └── dnsmasq.conf # AP mode DHCP config
├── src/
│ ├── main.py # Main entry point & orchestration
│ ├── config.py # JSON config management
│ ├── display.py # OLED SSD1306 handler
│ ├── encoder.py # Rotary encoder with debouncing
│ ├── led.py # WS2812B animations
│ ├── menu.py # Menu system & navigation
│ ├── audio.py # ALSA volume control
│ ├── network.py # WiFi & AP mode management
│ ├── power.py # Power management & watchdog
│ └── wifi_portal.py # Flask web UI
├── templates/
│ ├── portal.html # WiFi setup page (AP mode)
│ └── settings.html # Device settings page
├── services/
│ ├── airplay-ui.service # Main UI systemd service
│ └── wifi-portal.service # WiFi portal systemd service
└── venv/ # Python virtual environment

Configuration File

The device configuration is stored in ~/airplay/device_config.json:

{
"device_name": "Portable AirPlay",
"volume": 70,
"muted": false,
"led_enabled": true,
"led_brightness": 20,
"display_timeout_enabled": true,
"display_timeout_secs": 60,
"screensaver_clock": true,
"power_saver_enabled": true,
"audio_profile": "normal",
"wifi_configured": true,
"wifi_ssid": "YourNetworkName",
"saved_networks": [
{"ssid": "Network1", "password": "****"},
{"ssid": "Network2", "password": "****"}
]
}

Settings are automatically saved when changed via the OLED menu or Web UI.


API Reference

Endpoints

EndpointMethodDescription
/GETMain page (settings or WiFi setup)
/api/statusGETGet all current settings
/api/settingsPOSTUpdate multiple settings
/api/volumePOSTSet volume level
/api/mutePOSTToggle mute state
/api/restart-airplayPOSTRestart AirPlay (shairport-sync) service
/scanGETScan WiFi networks
/connectPOSTConnect to WiFi
/rebootPOSTReboot device
/restart-wifiPOSTEnter AP mode

Example: Update Settings

curl -X POST http://192.168.1.100/api/settings \
-H "Content-Type: application/json" \
-d '{"volume": 50, "led_enabled": true}'

Known Limitations

  • Pi Zero 2W only - Requires WiFi and sufficient CPU for AirPlay 2
  • No Bluetooth - WiFi-only for better audio quality and sync
  • Single LED - Minimal visual feedback by design
  • 3-hour battery - With 2000mAh battery; larger battery = longer runtime

License

MIT License - Feel free to modify and share!


Credits

  • Shairport Sync - AirPlay audio receiver
  • NQPTP - PTP timing for AirPlay 2
  • Adafruit CircuitPython libraries for hardware support

About

No description, website, or topics provided.

Resources

Stars

11 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages