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
Нет приёма сигнала
- Проверьте частоту — убедитесь, что TX и RX на одной частоте
- Увеличьте усиление TX — попробуйте
-g 0вместо-g -30 - Уменьшите расстояние — или используйте проводное соединение
- Проверьте антенны — убедитесь, что они подключены к правильным портам
- Используйте петлю — подключите TX напрямую к RX через аттенюатор 30-40 дБ
Высокий EVM / много ошибок
- Уменьшите полосу —
-b 1500000вместо-b 3000000 - Увеличьте усиление RX — отредактируйте
RX_GAINвreciever.c - Добавьте паузы —
-p 5000для стабилизации - Уменьшите амплитуду TX —
-a 0.15для снижения искажений - Проверьте CFO — значение > 0.1 требует настройки частоты
Ошибка сегментирования (Segmentation Fault)
- Проверьте версию liquid-dsp — требуется >= 1.3.0
- Пересоберите с отладкой:
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 - Проверьте права доступа к 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/.