Skip to the content
2 layers95 × 72 mmAPRS Radio Interface, the printed circuit board in 3D

APRS Radio Interface

hiperiondev/esp32idf_APRS16

APRS station on a single ESP32

Size
95 × 72 mm
Copper layers
2
Thickness
1.6 mm
Parts
25
Nets
19
Pads
59
Tracks, vias
156, 0
Routed
Yes
KiCad
KiCad 9.0 (file 20241229)
Created
30 Jul 2026
Updated
28 Sep 2026

Overview

APRS Radio Interface is an open-source printed circuit board by hiperiondev, from the hiperiondev/esp32idf_APRS repository on GitHub, published under the GPL-3.0 licence. It is a 2-layer board of 95 × 72 mm with 25 parts on 19 nets, routed with 156 tracks and 0 vias.

Its parts include 9 resistors, 5 capacitors, 4 diodes, 3 connectors and 1 IC. It belongs with the radio and wireless and interfaces and adapters boards and the ESP32 boards of this library.

README

README.md

esp32idf_APRS

A complete APRS station on a single ESP32 — native ESP-IDF, no Arduino.

IGate · Digipeater · Tracker · Weather · Telemetry, with a built-in web admin, an on-chip AFSK/FSK soft-modem, APRS-IS uplink, a runtime sensor-driver framework and OTA firmware updates.

Docs License Platform Framework [blocked]

🌐 Languages: English · Español · Italiano


What is this?

esp32idf_APRS turns a bare ESP32 DevKit plus a cheap audio interface into a complete, self-contained APRS station. Everything runs on the ESP32 itself — there is no Arduino core, no PlatformIO, and no external DSP library. The entire signal chain, from the correlator demodulator through DPLL bit recovery, NRZI, the HDLC framer, the AX.25 codec and Reed–Solomon FX.25 forward error correction, executes on the microcontroller using only the SAR-ADC in continuous/DMA mode, the DAC, and a general-purpose timer.

In one sentence, the firmware demodulates AFSK/FSK audio from a radio's speaker or discriminator output, decodes HDLC/AX.25 (optionally FX.25 error-corrected) frames, gates them to APRS-IS over Wi-Fi, digipeats them back on RF, beacons its own position, weather and telemetry, modulates and transmits frames back through the ESP32's 8-bit DAC — and is configured entirely through a web admin served by the device itself. No serial console, no recompilation for ordinary settings.

📖 The full, exhaustive documentation lives at esp32idf-aprs.readthedocs.io — trilingual (English / Español / Italiano), with getting-started guides, hardware wiring, the DSP signal chain, the configuration engine, HTTP routes and troubleshooting. This README is only a presentation. For anything beyond a first look, go to the docs.


Highlights

  • On-chip soft-modem. AFSK 1200 Bd Bell 202 (standard APRS) with up to twelve parallel demodulators (a multi-slicer set on four tilted prefilters covering about 33 dB of tone twist, from discriminator and speaker audio alike, tunable from the web admin, with a tone-band receive level meter), plus AFSK 1200 Bd V.23, AFSK 300 Bd, and G3RUH 9600 Bd FSK — all in pure C on the ESP32's own ADC/DAC.
  • FX.25 forward error correction. Reed–Solomon FEC over AX.25, RX-only or RX+TX, for reliable decodes in weak-signal conditions.
  • Full APRS-IS IGate. Bidirectional RF→INET and INET→RF gating with duplicate suppression, qAR/qAO construction, payload-type gating, callsign budlists, a local range gate (haversine distance), a prefix whitelist and, on the INET→RF side, a position requirement, a locally-heard source test and per-source spacing that keep a wide APRS-IS subscription off the local channel. Up to four APRS-IS servers can be listed, with automatic failover between the enabled ones.
  • BrandMeister APRS interconnect. Recognises, gates and routes the APRS traffic BrandMeister injects, over the APRS-IS session the IGate already has — an APBMxx tocall, a DMR path alias or a named entry gateway identifies it. Its own page, off by default. No DMR connection of any kind is involved.
  • Digipeater. A four-row n-N alias table (WIDE1-1 / WIDE2-2 / WIDE#-2 by default), each row with its own hop limit and trace/flood mode, plus hop-count trapping, fill-in-only operation and duplicate suppression.
  • Beacons, messaging & chat. Fixed-position beacons for tracker/igate/digi, APRS text messaging with ack/retry (RF and/or INET), and an in-browser message chat UI.
  • GNSS receiver & live tracking. An NMEA module on its own UART (RMC/GGA/GSA/GSV/VTG, multi-constellation) with a master switch, a live view page refreshed once a second, and a Use GPS control that fills any page's position fields from the current fix. The Tracker beacon can transmit the live fix instead of a fixed position, with SmartBeaconing making the interval speed-adaptive and pegging it on corners.
  • APRS query responder. Answers the general ?APRS?/?WX?/?IGATE?/?QRU? queries and the directed set (?APRSD/?APRSH/?APRSM/?APRSO/?APRSP/?APRSS/?APRST/?PING?), each with per-type and per-source rate limits, plus an optional periodic station-capabilities beacon.
  • Weather & telemetry. On-air APRS Weather Reports with 1 Hz sensor refresh and per-field averaging, plus APRS Telemetry (analog A1–A5 + digital B1–B8) with T#nnn reports and metadata.
  • Winlink radio e-mail (APRSLink). The station reads and writes its own CALLSIGN@winlink.org mail through the WLNK-1 service — challenge/response login with the password never on the air, a paced one-command-at-a-time session, and a browser terminal whose mailbox listing carries per-message read/reply/forward/delete buttons — and, separately, relays a neighbouring RF station's own Winlink session through its IGate.
  • Objects, items & bulletins. Up to five own-station APRS Objects/Items and five bulletins (BLN1–BLN5), each on RF and/or INET with expiry/decay control.
  • Telegram bot. An optional bot alongside the APRS services — long polling, per-user and per-chat authorization, station-message and bulletin routing to Telegram, and a Mini App button — so the station can be checked on and lightly controlled from a phone.
  • Runtime sensor framework. A dynamic, self-registering driver registry (sensors_local) — includes a BME280/BMP280 (I²C) driver out of the box, plus an optional BMP180 one on the same bus.
  • Web admin, 22 pages. HTTP Basic auth with two accounts — an administrator and an optional read-only one that sees every page, changes nothing, and may only start and stop the console log viewer —, a live dashboard with a live traffic log (JSON long-poll) and a last-heard JSON feed, LittleFS file management (upload/download/delete/format), Wi-Fi AP/STA/AP+STA with scan and TX-power control, CPU frequency control (80/160/240 MHz), and an on-demand console log viewer that mirrors the serial output into the browser. The whole UI is responsive from one stylesheet — on a tablet or a phone the sidebar becomes a slide-in drawer, form rows collapse to a single column, wide tables scroll within the page and the controls grow to a touch size.
  • OTA updates with auto-rollback. Dual ota_0/ota_1 app slots; a failed image rolls back automatically on the next boot.
  • Trilingual UI. English, Spanish and Italian (compile-time, one language per image).

Feature matrix

AreaNotes
AFSK 1200 Bd Bell 202Up to twelve parallel demodulators, default profile
AFSK 1200 Bd V.23 · AFSK 300 Bd · G3RUH 9600 Bd FSKMultiple selectable modem profiles
HDLC / AX.25 UI frame RX + TXFull soft-modem TX/RX path
FX.25 (Reed–Solomon FEC over AX.25)RX-only / RX+TX modes
PTT keyingCompile-time GPIO + polarity, minimum-unkey hold
CSMA / TX time-slot / TXDelay preamble / TXTailpreamble, tx_tail (TXTail, default 20 ms), tx_timeslot, csma_persist, csma_slot_ms (SlotTime), csma_busy_max_s (busy-channel wait, 0 = unlimited)
Transmit duty-cycle limiterOptional ceiling over a rolling 10-minute window
APRS-IS IGate RF→INET & INET→RFFilters, dedup, budlist, third-party unwrap opt-in, INET→RF flood gates
APRS-IS multiserver failover4 server slots, circular retry over the enabled ones
Local range gate & prefix gateHaversine distance + callsign-prefix whitelist
BrandMeister APRS interconnectRecognition, gating and message routing over the existing APRS-IS session; no DMR link
DigipeaterConfigurable n-N alias table (trace/flood), hop trapping, dup-suppression
Objects / Items · BulletinsUp to 5 each, RF and/or INET, expiry/decay
Telegram botLong polling, per-user/chat authorization, message & bulletin routing, Mini App button
Messaging + ack/retry · Chat UIRF and/or INET
Winlink radio e-mail (APRSLink)Own mailbox over WLNK-1, plus gateway for local stations
GNSS receiver (NMEA, own UART)Master switch, live view page, Use GPS position fill on every page
Live GPS tracking + SmartBeaconingTracker beacon only; speed-adaptive interval and corner-pegging
APRS query responderGeneral ?APRS?/?WX?/?IGATE?/?QRU? + directed set, rate-limited; capabilities beacon
Weather Report1 Hz sensor refresh, optional averaging
TelemetryAnalog A1–A5 + digital B1–B8, T#nnn + metadata
Sensor driver frameworkDynamic registry, BME280/BMP280 driver included
Web admin22 pages, live dashboard, live traffic log + last-heard feed, console log viewer, per-option contextual help
StorageLittleFS 512 KB, upload/download/delete/format
NetworkingWi-Fi AP/STA/AP+STA, scan, TX power, SNTP (UTC clock, selectable timezone for display)
CPU frequency control80 / 160 / 240 MHz
OTA updateota_0/ota_1 slots, auto-rollback
LocalizationEN / ES / IT, compile-time, labels and help balloons alike

Hardware

  • Target: ESP32 (classic, Xtensa dual-core), 4 MB flash. Dual-core is required — the ADC ISR and DAC sample clock are pinned to different cores on purpose.
  • Audio in (ADC): default GPIO33 (ADC1). GPIO 32–39 only — ADC2 is unusable while Wi-Fi is up.
  • Audio out (DAC): default GPIO25. GPIO 25 or 26 only — the ESP32 DAC is hard-wired to those pads.
  • PTT: default GPIO26, polarity selectable at compile time.
  • GNSS (optional): UART2, default GPIO16 (RX, from the module's TX) and GPIO17 (TX). Set in main/include/gps.h. Unusable on an ESP32-WROVER, where those pins belong to the SPI PSRAM die.
  • Note: ESP32-S3/C3/C6/H2 have no DAC and cannot run the TX path unmodified.

Board wiring (audio pins, PTT pin/polarity, ADC sample rate) is set as compile-time constants in the top-level CMakeLists.txt. A KiCad radio-interface schematic is included under schematics/.

The audio interface itself can be as small as one coupling capacitor and one level trimmer per direction: the Radiomodem page carries an Audio interface section that biases the ADC input from the pad's own pull resistors, sets the transmit output swing and sample rate, warns on receive over-range and bounds how long the transmitter may stay keyed. Every one of those settings defaults to the behaviour an interface board with its own bias network, attenuators and reconstruction filter expects, so an existing build is unaffected. Two buttons next to LOOP TEST — RX LEVEL and TX TEST — set the two trimmers once a transceiver has replaced the loopback jumper.

Full pinout tables and wiring constraints are in the Hardware chapter of the documentation.


Quick start

bash
# Requires ESP-IDF v6.1 (tested and locked at 6.1)
idf.py set-target esp32
idf.py build
idf.py -p PORT flash monitor

On first boot the device brings up a Wi-Fi AP; connect and open the web admin to configure your callsign, radio and services. After the one-time USB/UART flash, all further updates can be done from the web admin's About / Firmware page over OTA.

📖 The step-by-step first-run guide is in Getting Started.


Documentation

Everything is documented in full at 👉 esp32idf-aprs.readthedocs.io

The documentation is trilingual and organised into Functionalities (what the station does), Capabilities (cross-cutting properties), Internals (how it is built) and a Reference section:

This README is a presentation only — please consult the documentation for installation, wiring, configuration and internals.


Credits & license

Created by Emiliano Augusto González (LU3VEA).

Built on ideas from earlier projects — VP-Digi, ESP32APRS and LibAPRS; please refer to their authors for more information.

Released under the GNU General Public License v3. See LICENSE.

Parts

25
QtyValueFootprintReferences
410kAPRS_IF:R_AX_P10.16R3, R5, R6, R10
210uFAPRS_IF:CP_RAD_P2.54C1, C4
215nFAPRS_IF:C_DISC_P5.08C2, C3
21kAPRS_IF:R_AX_P10.16R7, R9
22k2APRS_IF:R_AX_P10.16R1, R2
2BAT54/1N4148APRS_IF:D_DO35_P7.62D1, D2
2LEDAPRS_IF:LED_P2.54D3, D4
110kAPRS_IF:TRIM_3362PRV2
11kAPRS_IF:TRIM_3362PRV1
11nFAPRS_IF:C_DISC_P5.08C5
1220RAPRS_IF:R_AX_P10.16R8
12N2222APRS_IF:TO92Q1
1ESP32APRS_IF:HDR_1x05J3
1PC817APRS_IF:DIP4U1
1TRS 2.5mmAPRS_IF:HDR_1x03J1
1TS 3.5mmAPRS_IF:HDR_1x02_13J2

Similar boards

  • 2 layers159.5 × 30 mmType f, the printed circuit board in 3D

    Type f

    google/mozc-devices

    Circuit diagrams and firmware source code for Gboard DIY keyboards

    25 parts3kApache-2.0
  • 2 layers113.5 × 95.1 mmSweep high, the printed circuit board in 3D

    Sweep high

    davidphilipbarr/Sweep

    Sweep - a small promicro based keyboard inspired by the Ferris.

    25 parts2.1k
  • 2 layers58.4 × 114.3 mmPicoPedal, the printed circuit board in 3D

    PicoPedal

    hackclub/OnBoard

    💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

    25 parts915
  • 2 layers54 × 15 mmXyp gpib, the printed circuit board in 3D

    Xyp gpib

    xyphro/UsbGpib

    Versatile, cheap and portable USB to GPIB converter (USBTMC class based)

    25 parts690MIT
  • 2 layers50 × 76 mmVoron 0, the printed circuit board in 3D

    Voron 0

    dennisss/dacha

    Monorepo for awesome tools/projects/libraries

    25 parts397Apache-2.0
  • 2 layers237.5 × 102.9 mmStorage, the printed circuit board in 3D

    Storage

    jes/scamp-cpu

    A homebrew 16-bit CPU with a homebrew Unix-like-ish operating system.

    25 parts301Unlicense
  • 2 layers43.3 × 21 mmNanoS3 Carrier, the printed circuit board in 3D

    NanoS3 Carrier

    UnexpectedMaker/esp32s3

    Assorted files for my ESP32-S3 development boards

    25 parts296

Questions

How big is the APRS Radio Interface PCB?

It measures 95 × 72 mm and has 2 copper layers, 1.6 mm thick.

What parts does the APRS Radio Interface use?

25 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the APRS Radio Interface KiCad files?

From the hiperiondev/esp32idf_APRS repository on GitHub, at the commit this page was made from: the board is schematics/APRS_Radio_Interface/APRS_Radio_Interface.kicad_pcb and its schematic schematics/APRS_Radio_Interface/APRS_Radio_Interface.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the APRS Radio Interface design in my own project?

Its repository publishes it under the GPL-3.0 licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).