Hardware confirmed from a photo of the bench: the device is a Pluto+ (2RX/2TX, Gigabit Ethernet), not the stock ADALM-PLUTO, plus an RTL-SDR dongle and several antennas. No attenuator on hand. - record the actual inventory and the Pluto+ differences that matter: Ethernet transport, two channels, adi.Pluto first with adi.ad9361 as the only permitted fallback - replace "use an attenuator" with numbers: TX puts out about +7 dBm at 0 dB, the RX damage threshold is about +2.5 dBm, so give a staged gain procedure starting at -60 dB and capped at -30 dB until an attenuator arrives - require the antennas to be physically removed from the bench rather than merely left unplugged - add the environment blocker found on inspection: the interpreter on PATH is a standalone Python 3.13.1 without pyadi-iio, libiio or scipy, while Lab024a clearly ran somewhere else; identifying and recording that environment is now the first task - renumber sections and align the TX gain figure with the safety section Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
23 KiB
Lab042 — техническое задание
Передача JPEG через настоящий радиотракт: кабельная петля на одном PlutoSDR
Документ предназначен для исполнителя, не участвовавшего в предыдущих лабораторных. Всё, что нужно для работы, изложено здесь.
1. Зачем эта лабораторная
За Lab001–Lab041 собран весь тракт передачи изображения, кроме одного звена: передатчик ни разу не включался. Во всём проекте нет ни одного вызова передачи через SDR.
Цель Lab042 — соединить уже готовые части и получить изображение, прошедшее через настоящий радиотракт. Не улучшить, не оптимизировать, не измерить дальность. Получить картинку на выходе.
Всё, что не требуется для этой цели, в Lab042 не делается.
2. Что уже готово и должно быть переиспользовано
Ничего из перечисленного писать заново не нужно.
| Звено | Где взять |
|---|---|
| Разбиение JPEG на фрагменты и сборка обратно | protocol/image_fragments.py, примеры в tests/lab007_image_fragmentation.py |
| Пакет с CRC32, кодирование и разбор | protocol/packet.py |
| Подбор размера и качества JPEG | tests/lab010_image_optimization.py, готовые профили в data/processed/lab010 |
| Формирование радиокадра с преамбулой и маркером | build_radio_frame в tests/lab018_bpsk_radio_frame.py |
| Фильтр приподнятого косинуса | root_raised_cosine_taps там же |
| Модуляция BPSK | bpsk_modulate там же |
| Поиск кадра в потоке отсчётов | find_radio_frame в tests/lab019_bpsk_receiver.py |
| Оценка и коррекция ухода частоты | estimate_carrier_parameters, correct_phase_and_frequency там же |
| Демодуляция и разбор кадра | bpsk_demodulate, decode_radio_frame там же |
| Работа с Pluto на приём | tests/lab024a_pluto_rx_capture.py |
Единственное, чего нет в проекте — передача. Это и есть основной объём работы.
3. Почему петля на одном устройстве, а не два устройства
Передатчик и приёмник одного PlutoSDR работают от общего опорного генератора. Поэтому между ними практически нет ухода несущей частоты и не расходятся часы.
Это снимает ровно те две проблемы, которые в проекте проработаны слабее всего, и позволяет получить картинку сразу. Разведение на два устройства — отдельная лабораторная Lab043, там появится настоящий уход частоты, и вот там понадобятся наработки Lab021–Lab023.
Не пытайтесь сделать Lab042 и Lab043 одной работой. Разница между ними — вся сложность синхронизации.
4. Наличное оборудование
Подтверждено по состоянию на 10 августа 2026 года.
| Позиция | Состояние |
|---|---|
| Pluto+ — SDR, 2 приёмника и 2 передатчика, гигабитный Ethernet | есть |
| RTL-SDR — приёмный донгл | есть, понадобится в Lab043 |
| Кабели SMA | будут найдены |
| Антенны: штыревые на магнитном основании, короткая штыревая | есть, в Lab042 не используются |
| Рамочная антенна Donut AM (0,5–2 МГц) | к проекту отношения не имеет |
| Аттенюатор SMA 30 дБ | отсутствует |
Важно: устройство — Pluto+, а не оригинальный ADALM-PLUTO. Отличия, которые имеют значение:
- связь по Ethernet, а не по USB; адрес
ip:192.168.2.1уже подтверждён работой Lab024a; - два приёмных и два передающих канала; в Lab042 используется только первый канал каждого;
- класс
adi.Plutoв Lab024a отработал на приёме. Начинать с него. Если передача на этом классе не пойдёт из-за двухканальности, перейти наadi.ad9361с тем же адресом. Это единственное разрешённое отступление от задания, и о нём нужно сообщить.
5. Требования безопасности
Обязательны к исполнению. Это правило 8 проекта, оно не формальное.
- Антенны убрать со стола до начала работы. Не «не подключать», а физически убрать. Случайно вкрученная в передатчик антенна превращает лабораторную в незаконный выход в эфир.
- Передатчик не включать при отключённом кабеле: выход без нагрузки вреден для оконечного каскада.
- Соединять выход передатчика со входом приёмника только через аттенюатор. Аттенюатора сейчас нет, поэтому действует временный порядок ниже.
Про аттенюатор: почему он нужен и как начать без него
Выход передатчика Pluto+ при нулевом ослаблении даёт примерно +7 дБм. Предельно допустимый уровень на входе приёмника — около +2,5 дБм. То есть прямой кабель при максимальном усилении передатчика выводит приёмник за предел и может его повредить.
Регулировка tx_hardwaregain_chan0 работает в диапазоне от −89 до 0 дБ. При установке −30 дБ выход составит около −23 дБм — это в тридцать раз ниже опасного порога и одновременно отличный рабочий уровень для кабеля.
Временный порядок до появления аттенюатора:
- Перед первым включением выставить
tx_hardwaregain_chan0 = -60. - Убедиться, что приёмник видит сигнал. При −60 дБ он будет слабым, но различимым.
- Поднимать усиление шагами по 10 дБ, не превышая −30 дБ, пока созвездие не станет чистым.
- Значение выше −20 дБ без аттенюатора не выставлять ни при каких обстоятельствах.
Аттенюатор на 30 дБ стоит недорого и защищает не от расчётного уровня, а от ошибки оператора: одна опечатка в настройке усиления — и приёмник выходит из строя. Заказать стоит, начинать работу можно не дожидаясь.
6. Программное окружение: препятствие, которое надо снять первым
Проверка окружения 10 августа 2026 года показала следующее.
Интерпретатор, доступный в командной строке — C:\Users\user\AppData\Local\Programs\Python\Python313\python.exe, версия 3.13.1. В нём отсутствуют pyadi-iio и libiio, то есть работать с Pluto+ из него невозможно. Также отсутствует scipy, который нужен лабораторным Lab020–Lab022, Lab024b и Lab025.
При этом Lab024a когда-то отработала с настоящим устройством. Значит, существует второе окружение — по всей видимости, среда Anaconda, — где всё установлено, и запуск шёл оттуда.
Первое действие исполнителя: определить, в каком окружении запускаются лабораторные, и зафиксировать это. Пока это не сделано, невозможно ни повторить Lab024a, ни начать Lab042.
Требуется:
- Найти окружение, где установлены
pyadi-iioиlibiio, и проверить связь с устройством. - Записать в отчёт: путь к интерпретатору, версию Python, версии
pyadi-iioиlibiio. - Если такого окружения нет — установить
pyadi-iioиlibiio, зафиксировав версии.
Расчётные лабораторные, включая Lab041, в окружении без pyadi-iio запускаются нормально — им нужны только numpy, matplotlib и opencv. Разделение аппаратных и расчётных зависимостей относится к этапу стабилизации и в Lab042 не решается, но результат проверки надо записать: он понадобится при составлении описания окружения.
7. Параметры тракта
Значения тракта взяты из Lab018 и менять их в этой лабораторной запрещено. Причина: переход на железо сам по себе вносит достаточно неизвестных. Менять одновременно и параметры сигнала — значит потерять возможность понять причину отказа.
| Параметр | Значение | Источник |
|---|---|---|
| Символьная скорость | 20 000 симв/с | SYMBOL_RATE, Lab018 |
| Отсчётов на символ | 32 | SAMPLES_PER_SYMBOL, Lab018 |
| Частота дискретизации | 640 000 Гц | произведение двух предыдущих |
| Скругление фильтра | 0,35 | RRC_ROLLOFF, Lab018 |
| Длина фильтра | 10 символов | RRC_SPAN_SYMBOLS, Lab018 |
| Преамбула | 64 бита | PREAMBLE_BIT_COUNT, Lab018 |
| Слово синхронизации | 0xD391 | RADIO_SYNC_WORD, Lab018 |
| Защитный интервал | 16 символов | GUARD_SYMBOL_COUNT, Lab018 |
| Амплитуда передачи | 0,70 | TX_AMPLITUDE, Lab018 |
Полезная скорость получается около 20 кбит/с. Для картинки в несколько килобайт это единицы секунд. Этого достаточно: цель — картинка, а не скорость.
Параметры PlutoSDR
| Параметр | Значение | Примечание |
|---|---|---|
| Адрес устройства | ip:192.168.2.1 |
как в Lab024a |
| Несущая передачи и приёма | 435 МГц | обе одинаковые |
| Частота дискретизации | 640 000 | совпадает с трактом |
| Полоса радиочастотного тракта | 200 000 Гц | минимум Pluto, сигнал занимает около 27 кГц |
| Усиление передатчика | начать с −60 дБ, не выше −30 дБ без аттенюатора | см. раздел 5 |
| Режим усиления приёмника | manual |
автоматика мешает измерениям |
| Усиление приёмника | начать с 20 дБ | подобрать по амплитуде |
| Циклический буфер передачи | выключен | см. раздел 7 |
Про несущую: 435 МГц выбрана потому, что нижняя граница PlutoSDR составляет около 325 МГц, а целевой диапазон проекта ниже 350 МГц находится у самого края. Поскольку передача идёт по кабелю и в эфир не выходит, выбор частоты здесь ни на что не влияет. Вопрос рабочего диапазона решается отдельно перед Lab044.
8. Порядок работы
Передающая сторона
- Взять исходное изображение из
data/raw, привести к профилю из Lab010 так, чтобы JPEG получился не крупнее 5 КБ. - Разбить на фрагменты через
protocol/image_fragments.py. - Каждый фрагмент упаковать в пакет с CRC32 через
protocol/packet.py. - Каждый пакет обернуть в радиокадр через
build_radio_frame. - Промодулировать BPSK и отфильтровать.
- Привести к целым числам и передать.
Приёмная сторона
- Запустить приём до начала передачи.
- Найти кадры через
find_radio_frame. - Скорректировать фазу и частоту.
- Демодулировать, разобрать кадр, проверить CRC32.
- Собрать изображение из уцелевших фрагментов и сохранить на диск.
Приём и передача идут в одном процессе. Приём запускается первым — иначе начало первого кадра теряется безвозвратно.
9. Ловушки, на которых спотыкаются в первый раз
Перечислено то, что почти наверняка будет сделано неправильно без предупреждения.
-
Циклический буфер передачи. У PlutoSDR буфер передачи по умолчанию повторяется бесконечно. Кажется, что передан один кадр, а передаётся бесконечный поток. Признак: приёмник видит тысячи копий одного кадра, а передача не заканчивается. Буфер надо явно выключить и явно освобождать после передачи.
-
Масштаб отсчётов. PlutoSDR принимает целые числа, а не дробные значения от минус единицы до единицы. Готовый сигнал надо умножить на масштабный множитель, обычно 2 в степени 14. Признак ошибки: передаётся почти тишина, приёмник ничего не находит.
-
Приём запущен после передачи. Начало кадра теряется, преамбула не находится. Признак:
find_radio_frameне срабатывает при заведомо исправном сигнале. -
Размер приёмного буфера меньше кадра. Кадр не помещается целиком, поиск преамбулы срывается. Буфер должен вмещать кадр с запасом минимум вдвое.
-
Автоматическая регулировка усиления приёмника. Меняет амплитуду в процессе и портит оценку. Режим должен быть ручным.
-
Насыщение приёмника. При слишком слабом ослаблении сигнал упирается в потолок и созвездие разваливается, хотя уровень кажется отличным. Признак: демодуляция не работает при очень сильном сигнале. Лечится увеличением ослабления, а не усилением.
-
Переходный процесс в начале передачи. Первые несколько десятков отсчётов недостоверны. Поэтому в тракте есть защитный интервал в 16 символов — его нельзя убирать.
10. Что считается выполненной работой
Лабораторная принимается, если выполнено всё перечисленное.
Обязательный результат
- Файл принятого изображения на диске, открывающийся просмотрщиком.
- Принятое изображение совпадает с переданным при отсутствии потерь — сравнение по контрольной сумме всего файла.
- Работа воспроизводится: два запуска подряд дают одинаковый успешный результат.
Обязательные измерения
| Величина | Как получить |
|---|---|
| Размер переданного JPEG, байт | из файла |
| Число фрагментов и пакетов | из разбиения |
| Число принятых кадров | счётчик приёмника |
| Число кадров, не прошедших CRC32 | счётчик приёмника |
| Доля успешно принятых фрагментов | отношение |
| Полное время передачи, секунды | измерение |
| Фактическая полезная скорость, кбит/с | расчёт из двух предыдущих |
| Усиление передатчика и приёмника | из настроек устройства |
| Ослабление аттенюатора, дБ | из состава схемы |
Обязательные файлы в data/processed/lab042
- принятое изображение;
- CSV с измерениями из таблицы выше;
- текстовый отчёт;
- график созвездия принятого сигнала;
- график спектра принятого сигнала.
Требования к коду
- Ничего из
protocol/не переписывать. Только использовать. - Параметры тракта из раздела 5 не менять.
- Все константы вынести в начало файла с указанием источника, как это сделано в Lab041.
- Никаких вписанных руками результатов: каждое число в отчёте должно вычисляться из измерений текущего запуска. Это отдельно проверяется при приёмке.
- Файл лабораторной:
tests/lab042_pluto_image_loopback.py, запуск черезpython -m tests.lab042_pluto_image_loopbackиз корня проекта.
11. Что в этой лабораторной делать не надо
Перечислено, чтобы не расширять объём.
- Не реализовывать повторную передачу потерянных фрагментов. Потери фиксируются, но не восстанавливаются.
- Не подключать исправление стираний из
protocol/packet_erasure_fec.py. - Не поднимать скорость и не менять модуляцию.
- Не выходить в эфир и не подключать антенну.
- Не работать с двумя устройствами.
- Не трогать логику сеансов, аварийной остановки и приоритетов — она к передаче картинки отношения не имеет.
Всё это относится к последующим лабораторным.
12. Порядок приёмки
- Исполнитель выполняет работу и сообщает о готовности.
- Проверяется
python tools/quick_gate.py— должен проходить. - Проводится аудит: соответствие разделу 10, отсутствие вписанных результатов, происхождение каждого числа в отчёте.
- При наличии замечаний они оформляются списком с указанием файла и строки.
- После приёмки в
PROJECT_LOG.mdдобавляется новая запись по принятому в проекте образцу.
13. Что дальше
- Lab043 — разведение на два устройства: передаёт PlutoSDR, принимает RTL-SDR. Появляется настоящий уход несущей частоты и расхождение часов. Здесь понадобятся Lab021–Lab023.
- Lab044 — выбор рабочего диапазона и первый выход в эфир на малой мощности.
- Повышение скорости, исправление стираний и передача последовательности кадров — после того, как картинка устойчиво проходит.