Skip to content

Raspberry Pi Satellite

Deploy a Raspberry Pi as a BirdNET-NG satellite node for continuous bird audio capture.

Hardware

  • Raspberry Pi 3B+ or newer (4 recommended)
  • USB microphone or I2S MEMS microphone (e.g., Adafruit SPH0645)
  • SD card (16GB+)
  • Power supply
  • Optional: GPS module (e.g., u-blox NEO-6M, Adafruit Ultimate GPS, BN-880)

Software Setup

1. Install Node.js

bash
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -
sudo apt install -y nodejs

2. Install audio tools

bash
sudo apt install -y alsa-utils
arecord -l                    # List audio devices
arecord -D plughw:1,0 -f S16_LE -r 48000 -c 1 -d 3 test.wav
aplay test.wav                # Verify recording works

3. Register the satellite

Use the web UI to register, or via API:

bash
curl -X POST https://birdnet.example.com/api/satellites \
  -H "Authorization: Bearer <jwt-token>" \
  -H "Content-Type: application/json" \
  -d '{"tenantId":"<uuid>","name":"Garden Pi","latitude":43.56,"longitude":3.90}'

Save the returned id, mqtt.username, and mqtt.password.

4. Configure and run

bash
git clone https://github.com/birdnet-ng/birdnet-ng.git
cd birdnet-ng
pnpm install && pnpm build

cd packages/satellite
cat > .env << 'EOF'
SATELLITE_ID=<from registration>
TENANT_ID=<your tenant>
MQTT_BROKER_URL=mqtts://mqtt.birdnet.example.com:8883
MQTT_USERNAME=<satellite id>
MQTT_PASSWORD=<from registration>
CAPTURE_MODE=alsa
AUDIO_DEVICE=plughw:1,0
LATITUDE=43.56
LONGITUDE=3.90
RECORDING_PROFILE=continuous
EOF

node dist/index.js

5. Run as a systemd service

bash
sudo tee /etc/systemd/system/birdnet-satellite.service << 'EOF'
[Unit]
Description=BirdNET-NG Satellite
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/birdnet-ng/packages/satellite
EnvironmentFile=/home/pi/birdnet-ng/packages/satellite/.env
ExecStart=/usr/bin/node dist/index.js
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable --now birdnet-satellite

GPS Setup

For live GPS positioning instead of static coordinates:

bash
sudo apt install -y gpsd gpsd-clients

Edit /etc/default/gpsd:

DEVICES="/dev/ttyUSB0"    # or /dev/serial0 for GPIO UART
GPSD_OPTIONS="-n"
START_DAEMON="true"
bash
sudo systemctl enable --now gpsd
cgps                         # Verify GPS fix

Add to .env:

bash
GPS_MODE=gpsd
GPSD_HOST=localhost
GPSD_PORT=2947

When GPS mode is gpsd, the satellite reads live coordinates from the GPS daemon and updates the hub via telemetry. Falls back to static coordinates if GPS has no fix.

Recording Profiles

Profiles control when the satellite captures audio. They are pushed from the hub via MQTT and can be changed on the Satellites page.

ProfileScheduleDescription
continuous24/7Always recording
dawn_chorussunrise-30min to sunrise+2hPeak bird activity
night_migrationsunset+30min to sunset+12hNocturnal flight calls
low_powersunrise±30min, sunset±30minDawn and dusk only

Sunrise and sunset times are calculated automatically from the satellite's GPS coordinates using the NOAA solar algorithm. Times update daily as day length changes with seasons.

When outside a recording window, the satellite:

  • Pauses the capture loop (no CPU/disk usage)
  • Continues sending heartbeats (stays "online" on the hub)
  • Reports state as scheduled_off in the heartbeat
  • Re-checks the schedule every 5 minutes

Heartbeat

The satellite sends a lightweight heartbeat every 30 seconds via MQTT QoS 1. This keeps the satellite showing as "online" on the hub even when all audio chunks are filtered out (silence).

The heartbeat includes the satellite's current state (recording, scheduled_off, error), visible on the Satellites page.

On-Device Audio Filtering

Before sending a chunk, the satellite checks:

  1. RMS energy > 0.005 (reject silence)
  2. Bird-band frequency ratio > 0.1 (reject audio outside 1–10kHz)

This typically filters 70–90% of chunks, reducing bandwidth and hub processing load. Disable with AUDIO_FILTER=false.

Filtering is automatically disabled for simulate and replay capture modes.

Troubleshooting

SymptomCheck
Satellite shows offlineVerify MQTT credentials, check journalctl -u birdnet-satellite
No detectionsCheck if all chunks are filtered (low audio activity), verify worker is running
GPS unavailableCheck cgps for fix, verify /dev/ttyUSB0 permissions
High CPU tempNormal for Pi 4 under load; add heatsink or fan
Storage filling upIncrease RETENTION_HOURS or check outbox drain

Distributed bird sound identification