ESPARGOS/SoapyESPSDR

ESP-SDR plugin for SoapySDR: Stream I/Q samples from ESP32-S31 to various SDR applications (gqrx, GNU Radio, ...) over USB or Ethernet via SoapySDR

C++

0

3 commits

updated Oct 2, 2026

See the code

See what people are saying

SourceMessageScoreDate

and a day later https://github.com/ESPARGOS/SoapyESPSDR already got native ESP32-S31s USB 2.0 working streaming 20 MSa/s @8bit, pretty amazing at $7 + shipping.

on Various Projects Find Hidden SDR Capabilities in ESP32 Microcontrollers

0

Oct 2, 2026

README

SoapyESPSDR

ESPARGOS logo

ESP-SDR + SoapyESPSDR enable continuous I/Q streaming with ESP32-S31 at up to 20 MSa/s over USB or 40 MSa/s over Ethernet.

SoapyESPSDR is a SoapySDR plugin that lets you use an ESP32-S31 as a radio receiver in Gqrx, GNU Radio, and other SoapySDR-compatible applications.

SoapyESPSDR is different from ESP-WebSDR, which lets you explore signals in your browser, but with a limited capture duty cycle. SoapyESPSDR adds continuous I/Q streaming to desktop applications: listen to signals in Gqrx, record samples, or build your own demodulator in GNU Radio. Transmission is not supported.

Experimental: The driver and streaming firmware are under development. Signal quality, including the remaining DC peak, still needs improvement.

What you need

  • Linux and an ESP32-S31 Function-CoreBoard running ESP-SDR's ESP32-S31 Function-CoreBoard · Ethernet / USB for SoapyESPSDR firmware. This is different from the ordinary ESP32-S31 firmware for use with ESP-WebSDR, which uses a different (much slower) protocol. Just flash the firmware from your browser.
  • The board's native high-speed USB connector or Gigabit Ethernet. The UART and USB Serial/JTAG connectors are for flashing/debugging. Ethernet must be gigabit along the entire path; shared USB bandwidth can also limit the sample rate.

Build and install

On Debian/Ubuntu:

sudo apt install build-essential cmake pkg-config libsoapysdr-dev soapysdr-tools \
  libcurl4-openssl-dev libjsoncpp-dev libusb-1.0-0-dev
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
sudo cmake --install build

To use the build without installing, set both variables in the application’s shell. They isolate it from any older installed driver; unset them to restore normal system-wide driver discovery.

export SOAPY_SDR_ROOT="$PWD/build"
export SOAPY_SDR_PLUGIN_PATH="$PWD/build"

For USB access without root, add this to /etc/udev/rules.d/70-espsdr.rules, run sudo udevadm control --reload-rules, and reconnect the board:

SUBSYSTEM=="usb", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="4531", MODE="0660", TAG+="uaccess"

Connect

For Ethernet, find the board's DHCP address in your router or UART boot log. Replace 192.168.1.100 below with that address. Open it in a browser for the board's control/status page.

ConnectionGqrx device string (choose Other)
USBsoapy=0,driver=espsdr,usb=1
Ethernetsoapy=0,driver=espsdr,host=192.168.1.100

Use a sample rate of 20000000 to start. Check discovery or connectivity with:

SoapySDRUtil --find="driver=espsdr"
SoapySDRUtil --probe="driver=espsdr,usb=1"
SoapySDRUtil --probe="driver=espsdr,host=192.168.1.100"

Optional device arguments: usb_serial=<serial> selects a USB board; interface=eth0 selects a network interface; http_port=80 sets the control port. Avoid placing host Wi-Fi and Ethernet on the same receiver subnet. Only one connection can receive at a time. During reception, change settings through the SDR application so its processing stays in sync. Network control is unauthenticated; use a trusted local network.

Capabilities and limitations

  • Tuning: 2300–2800 MHz in 1 MHz steps; manual gain is a PHY table index, not calibrated dB.
  • Sample rates: 4, 8, 16, 20 MSa/s; Ethernet also supports 40 MSa/s.
  • Samples: native signed 8-bit I and 8-bit Q. CS8, CS16, and CF32 are supported; wider formats do not add ADC precision.
  • Analog bandwidth: 13–54 MHz; zero follows the sample rate. Lower sample rates do not add an anti-alias filter, so out-of-band signals can alias.
  • Timing: boot-relative timestamps and loss counters; no synchronized multi-board clock.

Known issue — DC offset: A residual bias in the I/Q samples can create a spurious peak at the center of the spectrum, even with correction enabled.

Tests

The C++ tests and Python localhost tests need no radio. The latter additionally require python3-soapysdr and python3-numpy:

ctest --test-dir build --output-on-failure
SOAPY_SDR_ROOT="$PWD/build" SOAPY_SDR_PLUGIN_PATH="$PWD/build" python3 tests/loopback_test.py

To check reception with a connected board, the loss monitor reports missing samples, overflows, and timeouts, and fails on empty or lossy reception:

./build/espsdr_loss_monitor --device driver=espsdr,usb=1 --rate 20000000 --seconds 60

Use driver=espsdr,host=<board-IP> to check Ethernet.

License

GPL-3.0-or-later; see LICENSE.

ESPARGOS/SoapyESPSDR

ESP-SDR plugin for SoapySDR: Stream I/Q samples from ESP32-S31 to various SDR applications (gqrx, GNU Radio, ...) over USB or Ethernet via SoapySDR

C++

0

3 commits

updated Oct 2, 2026

See the code

See what people are saying

SourceMessageScoreDate

and a day later https://github.com/ESPARGOS/SoapyESPSDR already got native ESP32-S31s USB 2.0 working streaming 20 MSa/s @8bit, pretty amazing at $7 + shipping.

on Various Projects Find Hidden SDR Capabilities in ESP32 Microcontrollers

0

Oct 2, 2026

README

SoapyESPSDR

ESPARGOS logo

ESP-SDR + SoapyESPSDR enable continuous I/Q streaming with ESP32-S31 at up to 20 MSa/s over USB or 40 MSa/s over Ethernet.

SoapyESPSDR is a SoapySDR plugin that lets you use an ESP32-S31 as a radio receiver in Gqrx, GNU Radio, and other SoapySDR-compatible applications.

SoapyESPSDR is different from ESP-WebSDR, which lets you explore signals in your browser, but with a limited capture duty cycle. SoapyESPSDR adds continuous I/Q streaming to desktop applications: listen to signals in Gqrx, record samples, or build your own demodulator in GNU Radio. Transmission is not supported.

Experimental: The driver and streaming firmware are under development. Signal quality, including the remaining DC peak, still needs improvement.

What you need

  • Linux and an ESP32-S31 Function-CoreBoard running ESP-SDR's ESP32-S31 Function-CoreBoard · Ethernet / USB for SoapyESPSDR firmware. This is different from the ordinary ESP32-S31 firmware for use with ESP-WebSDR, which uses a different (much slower) protocol. Just flash the firmware from your browser.
  • The board's native high-speed USB connector or Gigabit Ethernet. The UART and USB Serial/JTAG connectors are for flashing/debugging. Ethernet must be gigabit along the entire path; shared USB bandwidth can also limit the sample rate.

Build and install

On Debian/Ubuntu:

sudo apt install build-essential cmake pkg-config libsoapysdr-dev soapysdr-tools \
  libcurl4-openssl-dev libjsoncpp-dev libusb-1.0-0-dev
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
sudo cmake --install build

To use the build without installing, set both variables in the application’s shell. They isolate it from any older installed driver; unset them to restore normal system-wide driver discovery.

export SOAPY_SDR_ROOT="$PWD/build"
export SOAPY_SDR_PLUGIN_PATH="$PWD/build"

For USB access without root, add this to /etc/udev/rules.d/70-espsdr.rules, run sudo udevadm control --reload-rules, and reconnect the board:

SUBSYSTEM=="usb", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="4531", MODE="0660", TAG+="uaccess"

Connect

For Ethernet, find the board's DHCP address in your router or UART boot log. Replace 192.168.1.100 below with that address. Open it in a browser for the board's control/status page.

ConnectionGqrx device string (choose Other)
USBsoapy=0,driver=espsdr,usb=1
Ethernetsoapy=0,driver=espsdr,host=192.168.1.100

Use a sample rate of 20000000 to start. Check discovery or connectivity with:

SoapySDRUtil --find="driver=espsdr"
SoapySDRUtil --probe="driver=espsdr,usb=1"
SoapySDRUtil --probe="driver=espsdr,host=192.168.1.100"

Optional device arguments: usb_serial=<serial> selects a USB board; interface=eth0 selects a network interface; http_port=80 sets the control port. Avoid placing host Wi-Fi and Ethernet on the same receiver subnet. Only one connection can receive at a time. During reception, change settings through the SDR application so its processing stays in sync. Network control is unauthenticated; use a trusted local network.

Capabilities and limitations

  • Tuning: 2300–2800 MHz in 1 MHz steps; manual gain is a PHY table index, not calibrated dB.
  • Sample rates: 4, 8, 16, 20 MSa/s; Ethernet also supports 40 MSa/s.
  • Samples: native signed 8-bit I and 8-bit Q. CS8, CS16, and CF32 are supported; wider formats do not add ADC precision.
  • Analog bandwidth: 13–54 MHz; zero follows the sample rate. Lower sample rates do not add an anti-alias filter, so out-of-band signals can alias.
  • Timing: boot-relative timestamps and loss counters; no synchronized multi-board clock.

Known issue — DC offset: A residual bias in the I/Q samples can create a spurious peak at the center of the spectrum, even with correction enabled.

Tests

The C++ tests and Python localhost tests need no radio. The latter additionally require python3-soapysdr and python3-numpy:

ctest --test-dir build --output-on-failure
SOAPY_SDR_ROOT="$PWD/build" SOAPY_SDR_PLUGIN_PATH="$PWD/build" python3 tests/loopback_test.py

To check reception with a connected board, the loss monitor reports missing samples, overflows, and timeouts, and fails on empty or lossy reception:

./build/espsdr_loss_monitor --device driver=espsdr,usb=1 --rate 20000000 --seconds 60

Use driver=espsdr,host=<board-IP> to check Ethernet.

License

GPL-3.0-or-later; see LICENSE.

Languages

C++

79.6%

Python

17.5%

CMake

2.9%