Files
2026-07-17 15:57:05 +03:00
..
2026-06-03 14:23:30 +03:00
2026-06-03 14:23:30 +03:00
2026-06-03 14:23:30 +03:00
2026-06-03 14:23:30 +03:00
2026-06-03 14:23:30 +03:00

OFDM Radio Link — PlutoSDR

Система цифровой радиосвязи на базе PlutoSDR с использованием OFDM-модуляции и помехоустойчивого кодирования Рида-Соломона RS(255,223).

Оглавление

Возможности

  • OFDM-модуляция: 64 поднесущих, циклический префикс 16, сглаживающее окно 4
  • Помехоустойчивое кодирование: Рида-Соломона RS(255,223) с CRC32
  • Частотная коррекция: адаптивная компенсация CFO через NCO с экспоненциальным фильтром (α=0.95)
  • Ручное управление усилением: фиксированное усиление для максимальной стабильности
  • Потоковая передача: работа через stdin/stdout для конвейерной обработки
  • Мониторинг в реальном времени: RSSI, EVM, CFO, статистика кадров
  • Гибкая настройка: частота, полоса, усиление, амплитуда, паузы между кадрами

Требования

Аппаратное обеспечение

  • 2× PlutoSDR (один на передачу, один на приём) или 1× для тестирования в петле
  • Raspberry Pi (рекомендуется) или любой Linux-компьютер
  • Антенны/аттенюаторы для RF-тракта

Программное обеспечение

# Установка зависимостей
sudo apt update
sudo apt install -y build-essential python3 cmake libfftw3-dev

# libiio (для работы с PlutoSDR)
sudo apt install -y libiio-dev

# liquid-dsp (OFDM и FEC)
git clone https://github.com/jgaeddert/liquid-dsp.git
cd liquid-dsp
./bootstrap.sh
./configure
make -j4
sudo make install
sudo ldconfig

Структура проекта

SDR/
├── common.h              # Общие определения и прототипы
├── common.c              # Реализация общих функций
├── transmitter.c         # Передатчик
├── reciever.c            # Приёмник с частотной коррекцией (имя файла с опечаткой — см. ниже)
├── makefile              # Система сборки
├── README.md             # Этот файл
└── test_input.bin        # Тестовый файл (создаётся make test)

⚠️ Известная проблема сборки приёмника. makefile ожидает файл receiver.c, но в репозитории он называется reciever.c (опечатка в имени). Из-за проверки существования файла цель receiver не попадает в make all, и make собирает только передатчик. Пока имя не исправлено, приёмник собирается вручную:

gcc -Wall -O2 -o receiver reciever.c common.c -liio -lliquid -lfftw3f -lm -lpthread

Долг зафиксирован в docs/tech-debt.md основного проекта.

Быстрый старт

# 1. Сборка
make

# 2. Создание тестового файла (1 МБ)
make test

# 3. Запуск приёмника (на одном устройстве)
./receiver -f 1265000000 -r 3840000 -b 2000000 -c rs8 > output.bin

# 4. Запуск передатчика (на другом устройстве)
cat test_input.bin | ./transmitter -f 1265000000 -r 3840000 -b 2000000 -g -20 -a 0.3 -c rs8

# 5. Проверка результата
md5sum test_input.bin output.bin

Сборка

# Сборка всего проекта
make

# Сборка только передатчика
make transmitter

# Приёмник — вручную, пока файл называется reciever.c (см. «Известная проблема» выше)
gcc -Wall -O2 -o receiver reciever.c common.c -liio -lliquid -lfftw3f -lm -lpthread

# Создание тестового файла 1 МБ
make test

# Очистка
make clean

# Справка
make help

Флаги компиляции:

  • -Wall -O2 — все предупреждения и оптимизация
  • -liio — библиотека libiio для PlutoSDR
  • -lliquid — liquid-dsp (OFDM, FEC, NCO)
  • -lfftw3f — FFTW для преобразований Фурье
  • -lm -lpthread — математика и потоки

Использование

Передатчик

# Базовая передача тестового файла
cat test_input.bin | ./transmitter -f 1265000000 -r 3840000 -b 2000000 -c rs8

# Передача случайных данных
cat /dev/urandom | ./transmitter -f 1265000000 -r 3840000 -b 2000000 -g -20 -a 0.3

# Высокоскоростная передача без пауз
cat data.bin | ./transmitter -f 2400000000 -r 7680000 -b 6000000 -g 0 -a 0.5 -p 0

# Передача текста
echo "Hello, OFDM World!" | ./transmitter -f 1265000000 -r 3840000 -b 2000000

Приёмник

# Базовый приём с декодированием FEC
./receiver -f 1265000000 -r 3840000 -b 2000000 -c rs8 > output.bin

# Приём без FEC (выше скорость, но нет исправления ошибок)
./receiver -f 1265000000 -r 3840000 -b 2000000 -c none > output.bin

# Приём с сохранением лога статистики
./receiver -f 1265000000 -r 3840000 -b 2000000 -c rs8 > output.bin 2> stats.log

# Мониторинг статистики в реальном времени
watch -n 1 'tail -1 stats.log'

Тестирование на одном устройстве (петля)

# Терминал 1: Приёмник
./receiver -f 2400000000 -r 3840000 -b 2000000 -c rs8 > output.bin

# Терминал 2: Передатчик
cat test_input.bin | ./transmitter -f 2400000000 -r 3840000 -b 2000000 -g -40 -c rs8

Параметры командной строки

Общие параметры (для TX и RX)

Параметр Описание По умолчанию
-f ЧАСТОТА Несущая частота в Гц 1265000000 (1265 МГц)
-r СКОРОСТЬ Частота дискретизации в Гц 3840000 (3.84 МГц)
-b ПОЛОСА Полоса пропускания в Гц 3000000 (3 МГц)
-u URI Адрес PlutoSDR ip:192.168.2.1 (RX) / ip:192.168.3.1 (TX)
-c РЕЖИМ FEC: rs8 или none rs8
-h Показать справку

Специфичные параметры передатчика

Параметр Описание По умолчанию
-g УСИЛЕНИЕ Усиление TX в дБ -30.0
-a АМПЛИТУДА Амплитуда сигнала (0..1) 0.2
-p ПАУЗА Пауза между кадрами в мкс 2000

Специфичные параметры приёмника

Параметр Значение Примечание
Усиление 50 дБ Фиксированное, ручной режим
CFO фильтр α=0.95 Экспоненциальное сглаживание

Формат кадра

┌─────────────────────────────────────────────────────────────────┐
│                         OFDM КАДР                               │
├──────────┬──────────────────────────────────────────────────────┤
│ Заголовок│              Полезная нагрузка                        │
│  12 байт │              до 1024 байт                            │
└──────────┴──────────────────────────────────────────────────────┘

Заголовок (12 байт):
┌───────┬───────┬──────────────────┬───────────────┬───────────────┬──────────────┬──────────┐
│ Байты │ 0-1   │      2-5         │     6-7       │     8-9       │     10       │   11     │
├───────┼───────┼──────────────────┼───────────────┼───────────────┼──────────────┼──────────┤
│ Знач. │ 0xF0  │ Порядковый номер │ Длина исходных│ Кол-во блоков │ Последний    │ Резерв   │
│       │ 0xAA  │ кадра (32 бита)  │ данных (16 бит)│ FEC (16 бит)  │ блок RS      │          │
└───────┴───────┴──────────────────┴───────────────┴───────────────┴──────────────┴──────────┘

Диагностика

Вывод приёмника в реальном времени

Кадры   | Загол. | CRC  | RS испр | Вывод  | RSSI  | EVM   | CFO
--------+--------+------+---------+--------+-------+-------+----------
   1234 |   1200 | 1180 |      15 |   1195 |   -45 |   2.3 |   0.0015

Расшифровка:

  • Кадры — всего обнаружено кадров синхронизатором
  • Загол. — количество корректно декодированных заголовков
  • CRC — кадры с корректной контрольной суммой
  • RS испр — кадры, исправленные кодом Рида-Соломона
  • Вывод — успешно выведено кадров в stdout
  • RSSI — уровень сигнала в дБм (чем ближе к 0, тем лучше)
  • EVM — вектор ошибки в % (чем меньше, тем лучше)
  • CFO — оценка частотного сдвига в рад/семпл

Итоговая статистика

═══════════════════════════════════════════════════
 ПРИЁМ ЗАВЕРШЁН
═══════════════════════════════════════════════════
Обнаружено кадров:     1024
Корректных заголовков:  1024 (100.0%)
Корректных CRC:         1024 (100.0%)
Исправлено RS:          0
Успешно выведено:       1024 кадров
Всего принято данных:   1048576 байт (1.00 МБ)
Финальная оценка CFO:   0.0012 рад/семпл
═══════════════════════════════════════════════════

Устранение неполадок

Ошибка подключения к PlutoSDR

# Проверка подключения
iio_info -s

# Пинг устройства
ping 192.168.2.1

# Проверка интерфейса
ifconfig eth1

Нет приёма сигнала

  1. Проверьте частоту — убедитесь, что TX и RX на одной частоте
  2. Увеличьте усиление TX — попробуйте -g 0 вместо -g -30
  3. Уменьшите расстояние — или используйте проводное соединение
  4. Проверьте антенны — убедитесь, что они подключены к правильным портам
  5. Используйте петлю — подключите TX напрямую к RX через аттенюатор 30-40 дБ

Высокий EVM / много ошибок

  1. Уменьшите полосу-b 1500000 вместо -b 3000000
  2. Увеличьте усиление RX — отредактируйте RX_GAIN в reciever.c
  3. Добавьте паузы-p 5000 для стабилизации
  4. Уменьшите амплитуду TX-a 0.15 для снижения искажений
  5. Проверьте CFO — значение > 0.1 требует настройки частоты

Ошибка сегментирования (Segmentation Fault)

  1. Проверьте версию liquid-dsp — требуется >= 1.3.0
  2. Пересоберите с отладкой:
    gcc -g -O0 -o receiver_debug reciever.c common.c -liio -lliquid -lfftw3f -lm -lpthread
    gdb ./receiver_debug
    run -f 1265000000 -r 3840000 -b 2000000 -c rs8
    bt
    
  3. Проверьте права доступа к USB:
    sudo chmod 666 /dev/iio*
    

Предупреждения компиляции

Предупреждения типа -Wformat исправлены добавлением суффикса LL к константам:

#define DEFAULT_FREQ 1265000000LL  // было 1265000000

Оптимальные параметры для разных сценариев

Максимальная скорость

# TX
cat data.bin | ./transmitter -f 2400000000 -r 7680000 -b 6000000 -g 0 -a 0.5 -p 0

# RX
./receiver -f 2400000000 -r 7680000 -b 6000000 -c none > output.bin

Максимальная надёжность

# TX
cat data.bin | ./transmitter -f 1265000000 -r 3840000 -b 1500000 -g -10 -a 0.4 -p 5000 -c rs8

# RX
./receiver -f 1265000000 -r 3840000 -b 1500000 -c rs8 > output.bin

Статус подпроекта

SDR — автономный подпроект в репозитории GPIO Monitor: со своей сборкой, без связи с Go-сервером. Радиоканал используется как альтернативный транспорт байтов GPIO-шины (см. scripts/emulatohackrf.sh — передача потока эмулятора через HackRF). Общая документация основного проекта — в docs/.