Files
SDR-Rover/docs/lab043_pluto_to_rtlsdr_spec.md
2026-08-19 18:14:13 +03:00

36 KiB
Raw Blame History

Lab043. Передача JPEG с Pluto+ на независимый RTL-SDR

1. Цель лабораторной

Передать тот же подготовленный JPEG, который использован в Lab042, с Pluto+ на отдельный RTL-SDR и восстановить его побайтово.

В Lab042 передатчик и приёмник находились в одном Pluto+ и использовали общий опорный генератор. Lab043 должна убрать это упрощение и раздельно измерить три эффекта:

  1. рассогласование несущих частот передатчика и приёмника;
  2. относительное рассогласование частот дискретизации двух устройств;
  3. начальную фазу выбора отсчёта символа внутри символьного интервала.

Лабораторная считается успешной только при выполнении радиокритериев, прикладных критериев и программных проверок, определённых в разделе 11. Запуск программы сам по себе успехом не считается.

2. Границы работы

Lab043 остаётся кабельной. Эфир добавил бы многолучёвость, внешние сигналы и неконтролируемые потери, хотя предмет этой работы состоит в синхронизации независимых устройств.

В Lab043 не входят:

  • передача через антенны;
  • выбор рабочего диапазона 200-250 МГц;
  • ARQ и повторная передача;
  • исправление стираний и новая FEC;
  • потоковое видео;
  • скачки по частоте;
  • изменение логики управления и безопасности ровера.

Эфирный тракт остаётся предметом следующей лабораторной.

3. Подтверждённое оборудование и окружение

Состояние оборудования проверено непосредственным опросом. Перед реализацией и перед каждым аппаратным прогоном его необходимо проверить повторно.

3.1. Передатчик

  • Pluto+;
  • устройство должно открываться успешным iio.Context, а не проверяться только командой ping;
  • чип AD9361;
  • используется первый передающий канал.

Конкретный рабочий URI IIO определяется повторным опросом перед опытом и сохраняется в метаданных запуска. Исторически работали сетевой URI ip:192.168.2.1 и прямой USB IIO, но ни один из них нельзя считать доступным без текущей проверки.

3.2. Приёмник

  • USB ID VID_0BDA&PID_2838;
  • имя библиотеки: Generic RTL2832U OEM;
  • тюнер, сообщённый библиотекой: Fitipower FC0013;
  • основной интерфейс MI_00 использует WinUSB от libwdi;
  • устройство открыто из Python через pyrtlsdr и librtlsdr;
  • установка 435 МГц подтверждена чтением значения обратно;
  • частота дискретизации 2 400 000 отсчётов/с работает;
  • получены комплексные отсчёты;
  • доступные аппаратные усиления находятся в диапазоне от -9,9 до 19,7 дБ и задаются дискретными ступенями устройства.

Ошибка второго USB-интерфейса не считается отказом SDR. Основной интерфейс MI_00, через который работает librtlsdr, исправен.

3.3. Зафиксированное программное окружение

  • Python 3.13.1 x64;
  • pyrtlsdr 0.5.0;
  • pyrtlsdrlib 0.0.5;
  • поставляемая пакетом нативная librtlsdr v0.9.0;
  • pyadi-iio и pylibiio для Pluto+.

Принятый способ доступа к RTL-SDR: API pyrtlsdr с поставляемой pyrtlsdrlib нативной библиотекой. Малый собственный DLL-адаптер не нужен. Реализация должна проверять версии и выдавать понятную ошибку, если библиотека или устройство недоступны. Пользовательский путь к DLL зашивать в код запрещено.

4. Физическая схема и безопасность

Схема:

Pluto+ TX -> SMA-кабель -> AT30S 30 дБ -> переходник/кабель -> RTL-SDR RX

Обязательные условия перед каждым включением TX:

  1. Антенны Pluto+ и RTL-SDR сняты.
  2. AT30S включён последовательно в тракт, а не подключён к свободному порту.
  3. Все разъёмы затянуты, кабель не отсоединяется при включённом TX.
  4. Пользователь отдельно подтверждает эту физическую схему.
  5. Первый заранее определённый рабочий режим: TX -30 дБ, RTL-SDR 19,7 дБ, несущая 435 МГц, номинально 2,4 Мвыб/с на обоих устройствах.
  6. Автоматический перебор усилений, частот, порогов и способов синхронизации запрещён.
  7. Если первый режим не проходит, программа сохраняет исходные данные и диагностику и останавливается. Следующий прогон разрешён только после разбора причины и с изменением ровно одного заранее названного параметра.

При TX -30 дБ расчётный уровень после AT30S составляет около -53 дБм. Это значение следует из бюджета Lab042: около +7 дБм при TX 0 дБ, минус 30 дБ настройки TX и минус 30 дБ аттенюатора. Расчёт не заменяет проверку наличия аттенюатора и правильности схемы.

5. Номинальные параметры сигнала и обязательное чтение обратно

Параметр Запрошенное значение Происхождение
Несущая TX и RX 435 МГц Кабельная рабочая точка Lab042
Символьная скорость 20 000 симв/с Lab018-Lab023 и Lab042
Частота дискретизации TX 2 400 000 отсчётов/с Поддерживается Pluto+ и проверена на RTL-SDR
Частота дискретизации RX 2 400 000 отсчётов/с Проверена непосредственным опросом RTL-SDR
Номинальное число отсчётов на символ 120 2 400 000 / 20 000
Полоса TX 200 кГц Минимальная полоса AD9361, использованная в Lab042
Размер данных фрагмента 512 байт Lab042
Модуляция BPSK Lab018-Lab023 и Lab042

Одинаковое номинальное значение 2,4 Мвыб/с выбрано специально. Lab043 измеряет физическую ошибку генераторов, а не искусственно созданную разницу номинальных частот дискретизации.

Перед аппаратным опытом программа обязана установить и прочитать обратно:

  • частоту дискретизации TX Pluto+;
  • частоту дискретизации RX RTL-SDR;
  • центральную частоту TX Pluto+;
  • центральную частоту RX RTL-SDR;
  • усиление TX Pluto+;
  • фактически выбранную ступень усиления RTL-SDR.

Для каждого параметра в отчёте и метаданных хранятся отдельные поля requested и actual. Если API не предоставляет независимого чтения обратно, поле actual имеет значение N/A, а не копию запрошенного значения. Передача не начинается, если частота дискретизации или несущая не прочитаны обратно либо отличаются от запрошенных больше, чем допускает API устройства и заранее установленная проверка.

6. Двухтоновая калибровка

Перед BPSK Pluto+ передаёт два комплексных тона, симметричных относительно несущей:

-Fcal и +Fcal, где Fcal = 50 кГц.

50 кГц выбраны до измерения: оба тона находятся внутри полосы 200 кГц, не сливаются около нуля и дают разнос 100 кГц для оценки масштаба частот. RTL-SDR измеряет положения двух пиков относительно своей настроенной несущей: f_low и f_high.

6.1. Рассогласование несущей

carrier_offset_hz = (f_low + f_high) / 2

carrier_offset_ppm = carrier_offset_hz / 435000000 * 1e6

Положительный результат означает, что принятый спектр сдвинут вверх по частоте. Для компенсации сырые комплексные отсчёты умножаются на:

exp(-j * 2*pi*carrier_offset_hz*n/Fs_rx_actual)

Знак поправки проверяется независимо: после компенсации среднее положение двух тонов должно стать ближе к нулю. Рассогласование несущей не должно подменяться оценкой ошибки частоты дискретизации.

6.2. Относительная ошибка частот дискретизации

clock_scale = (f_high - f_low) / (2*Fcal)

sample_clock_error_ppm = (clock_scale - 1) * 1e6

Здесь положительная ошибка означает, что масштаб передающего такта больше масштаба приёмного. Для перехода принятых отсчётов на временную сетку передатчика ожидаемая длина после передискретизации равна:

len_corrected = round(len_received * clock_scale)

Направление этой операции не принимается на веру. Оно подтверждается машинными тестами из раздела 8. После передискретизации накопленная ошибка символьного времени должна уменьшаться.

6.3. Начальная фаза выбора отсчёта символа

После грубой CFO-коррекции и передискретизации приёмник отдельно ищет начальную фазу выбора отсчёта в диапазоне от 0 до 119 номинальных отсчётов на символ. Это не CFO и не ошибка такта. В результатах отдельно хранятся:

  • carrier_offset_hz и carrier_offset_ppm;
  • clock_scale и sample_clock_error_ppm;
  • symbol_sample_phase и остаточная ошибка символьного времени.

6.4. Формальное определение шумового фона

Шумовой фон и превышение пиков вычисляются одинаковым детерминированным алгоритмом:

  1. Из комплексных отсчётов вычитается среднее.
  2. Оценивается спектральная плотность мощности методом Welch с окном Hann, nfft = nperseg = 65536 и перекрытием 50 процентов.
  3. Разрешение одного БПФ вычисляется по прочитанной обратно частоте как delta_f = Fs_rx_actual / 65536. При 2,4 Мвыб/с оно равно 36,62109375 Гц.
  4. Анализируется полоса от -100 до +100 кГц относительно настроенной несущей.
  5. Нижний пик ищется в диапазоне от -80 до -20 кГц, верхний от +20 до +80 кГц. Эти непересекающиеся окна заданы до измерения.
  6. После нахождения кандидатов ожидаемых тонов из оценки шума исключаются защитные зоны шириной +/-2 кГц вокруг измеренного положения каждого кандидата. Каждая полузона занимает около 55 разрешающих элементов БПФ при 2,4 Мвыб/с, поэтому утечка основного лепестка и ближайших боковых лепестков тона не попадает в медиану шума.
  7. Шумовая мощность P_noise равна медиане линейных значений мощности всех оставшихся спектральных элементов анализируемой полосы.
  8. Для каждого тона вычисляется peak_excess_db = 10*log10(P_peak/P_noise).

Оба пика должны превышать шумовой фон не менее чем на 10 дБ. Порог 10 дБ, полоса анализа, окна поиска и защитные зоны зафиксированы до аппаратного измерения. Если нет двух конечных пиков, недостаточно элементов шума или хотя бы один пик не проходит порог, оценка этого захвата недействительна.

6.5. Повторы и представление недействительных оценок

Без изменения схемы выполняются три отдельных калибровочных захвата. Для каждого захвата отдельно сохраняются:

  • f_low_hz и f_high_hz;
  • low_peak_excess_db и high_peak_excess_db;
  • carrier_offset_hz и carrier_offset_ppm;
  • clock_scale и sample_clock_error_ppm;
  • остаточная CFO после коррекции;
  • остаточная ошибка разноса тонов в герцах и ppm;
  • признак достоверности и причина отказа.

По трём захватам вычисляются среднее, минимум, максимум и стандартное отклонение каждой конечной оценки, а также число недействительных захватов. Стандартное отклонение считается по совокупности всех конечных оценок с ddof=0. Недействительное значение записывается как NaN в CSV и как N/A в текстовом отчёте. Оно никогда не заменяется нулём. Если конечных значений нет, все агрегаты этой величины равны N/A.

7. Диагностическая последовательность передачи

Аппаратная часть выполняется по ступеням. Переход к следующей ступени разрешён только после сохранения результатов предыдущей:

  1. двухтоновые калибровочные захваты;
  2. известная короткая BPSK-последовательность;
  3. символьная синхронизация и измерение BER известной последовательности;
  4. один пакет с CRC;
  5. десять пакетированных фрагментов JPEG;
  6. сборка JPEG;
  7. проверка размера и SHA-256.

Известная последовательность задаётся до измерения как PRBS11 длиной 2047 бит с полиномом x^11 + x^9 + 1 и фиксированным ненулевым начальным состоянием, записанным в метаданные. BER вычисляется прямым сравнением каждого принятого бита с ожидаемым до упаковки в пакет и до проверки CRC. CRC не может использоваться вместо измерения BER.

7.1. Контрольный опыт PRBS11 после проверки непрерывного async-приёма

Короткая запись S и длинная запись L являются двумя отдельными аппаратными захватами. Каждый захват выполняется одним непрерывным rtlsdr_read_async() и содержит в этой последовательности: входной запас, двухтоновую калибровку, фиксированный защитный участок 0,10 с, один начальный маркер, непрерывную PRBS11 и выходной запас. Полезная PRBS11 длится 0,25 с в S и не менее 2,0 с в L. Внутри полезной PRBS11 нет периодической повторной синхронизации.

Оценки CFO и масштаба частоты дискретизации для обработки PRBS11 берутся только из двух тонов в той же самой IQ-записи. Оценку из предыдущего двухтонового опыта или из другой записи применять запрещено. Если тоны в текущем захвате недостоверны, PRBS11 этой записи не интерпретируется.

Для обоих захватов заранее фиксируются 435 МГц, номинальные 2 400 000 отсчётов/с TX и RX, 20 000 символов/с, TX -30 дБ, запрос усиления RTL-SDR 19,7 дБ и Fcal = 50 кГц. Асинхронный приём использует callback 262144 байта, 15 буферов и отбрасывает первый callback как разогревочный без перезапуска сеанса. Автоматический подбор параметров запрещён.

Одна и та же IQ-запись обрабатывается режимами A, B и C. В B и C грубая CFO берётся из тонов этой записи; в C дополнительно применяется clock_scale этих же тонов. Разрешённая защищённая тонкая CFO-коррекция не заменяет двухтоновое измерение. Для длинной записи SRO дополнительно оценивается независимо по накопленному дрейфу символьной фазы.

8. Обязательные программные проверки до аппаратного опыта

На синтетических комплексных данных проверяются четыре ошибки частоты дискретизации: +20, -20, +100 и -100 ppm. Для каждого случая тест обязан проверить:

  • знак оценки sample_clock_error_ppm;
  • величину оценки в заранее заданном допуске;
  • направление изменения длины при передискретизации;
  • уменьшение остаточной накопленной ошибки символьного времени после поправки.

Для положительной ошибки длина должна изменяться в направлении, предписанном формулой round(N * clock_scale), для отрицательной в противоположном. Тест должен упасть, если вместо clock_scale применена обратная величина. Допуск оценки и критерий уменьшения остаточной ошибки задаются в тесте до аппаратного измерения и печатаются в его результате.

Дополнительно синтетические тесты проверяют:

  • знак грубой CFO-коррекции для положительной и отрицательной CFO;
  • уменьшение остаточной CFO после поправки;
  • отдельное восстановление начальной фазы выбора отсчёта символа;
  • явный N/A, если два тона не найдены достоверно;
  • формулу шумового фона и порог 10 дБ;
  • BER известной последовательности до CRC;
  • отсутствие ложного успеха при неполном пакете или изображении;
  • формирование кода возврата только по полному набору критериев.

До прохождения этих проверок передатчик включать нельзя.

9. Порядок аппаратного эксперимента

  1. Открыть Pluto+ успешным iio.Context и записать URI и идентификаторы.
  2. Открыть RTL-SDR через pyrtlsdr и записать имя устройства и тюнера.
  3. Установить и прочитать обратно параметры из раздела 5.
  4. Получить отдельное подтверждение пользователя, что кабельная схема из раздела 4 собрана и AT30S находится в разрыве.
  5. Запустить один непрерывный приём RTL-SDR за 0,5 с до передачи Pluto+.
  6. Выполнить три отдельных двухтоновых калибровочных захвата.
  7. Сохранить оценки каждого захвата, агрегаты и не менее одного эталонного сырого IQ-захвата.
  8. Передать известную BPSK-последовательность и измерить BER.
  9. Принять один пакет и проверить CRC.
  10. Передать десять фрагментов JPEG и проверить критерии раздела 11.

Если любая ступень не проходит, переход к следующей запрещён. Исходные данные и отрицательный результат сохраняются без подгонки. Изменение одного параметра для следующего запуска оформляется как отдельное заранее объяснённое действие.

Весь опыт принимается RTL-SDR как одна непрерывная временная последовательность. Продолжительность приёма вычисляется из фактически сформированной передаваемой последовательности:

T_rx = 0,5 с + N_tx / Fs_tx_actual + 0,5 с.

Здесь N_tx является фактическим числом комплексных отсчётов всей сформированной TX-последовательности. Общая длительность опыта не задаётся произвольной константой. Поток разрешено читать блоками, например около 262144 отсчётов, но блоки объединяются без пропусков и перестановок в одну последовательность. Размер блока чтения является параметром реализации, а не физическим защитным интервалом. Десять отдельных запусков приёмника для десяти кадров запрещены, потому что они уничтожили бы наблюдаемое накопление ошибки тактов.

Между BPSK-кадрами не добавляются новые интервалы. Используется структура Lab042: GUARD_SYMBOL_COUNT импортируется из её текущей конфигурации без копии числовой константы в Lab043, а формирование кадра повторяет ту же последовательность переднего интервала, символов, заднего интервала и RRC. Готовая функция Lab042 жёстко связана с 128 отсчётами на символ, поэтому при 120 отсчётах Lab043 переиспользуются её параметры, а не скрытая копия её глобальной частоты дискретизации. Если в дальнейшем отдельный интервал исчезнет из Lab042, Lab043 не создаёт новый без отдельного диагностического решения.

10. Три режима обработки одной записи

Одна и та же сохранённая BPSK/IQ-запись обрабатывается тремя режимами:

  • режим A: без грубой CFO-коррекции и без коррекции частоты дискретизации;
  • режим B: только грубая CFO-коррекция из двухтоновой калибровки;
  • режим C: грубая CFO-коррекция, коррекция частоты дискретизации и защищённая тонкая CFO-коррекция.

Во всех режимах начальная фаза выбора отсчёта символа оценивается и записывается отдельно. Для каждого режима сохраняются BER известной последовательности, остаточная CFO, остаточная временная ошибка, корреляция маркера, число найденных кадров, число разобранных заголовков и CRC пакетов.

В режиме C защищённая функция should_apply_cfo_correction из protocol/bpsk_radio.py остаётся тонкой коррекцией после грубого измерения. Она не используется как единственный способ поиска сдвига в десятки килогерц, поскольку символьная оценка неоднозначна за пределами половины символьной скорости.

Провал режимов A или B не считается провалом лабораторной. Они являются контрольными измерениями. Критерии передачи применяются к режиму C.

11. Критерии приёмки

11.1. Радиокритерии режима C

  • найдены все 10 кадров;
  • разобраны все 10 пакетов;
  • CRC32 сошлась у всех 10 пакетов.

11.2. Прикладные критерии режима C

  • восстановлены все 10 уникальных фрагментов;
  • JPEG собран без заполнения отсутствующих данных;
  • размер принятого JPEG совпадает с размером переданного;
  • SHA-256 принятого JPEG совпадает с SHA-256 переданного.

11.3. Общий результат

Код возврата 0 разрешён только при одновременном выполнении:

  • всех радиокритериев;
  • всех прикладных критериев;
  • всех обязательных программных проверок раздела 8.

Для подтверждения воспроизводимости заранее выбранная рабочая точка запускается три раза подряд без изменения схемы и параметров. Каждый повтор сохраняется отдельно. Три повтора являются проверкой воспроизводимости, а не статистической оценкой вероятности отказа.

Отрицательный результат допустим и сохраняется полностью. Запрещено автоматически поднимать усиление, менять частоту, пороги или алгоритм синхронизации после неудачного прогона.

12. Измерения и артефакты

12.1. Измерения передачи

Для каждого запуска и каждого режима обработки сохраняются:

  • запрошенные и фактические усиления, несущие и частоты дискретизации;
  • число принятых отсчётов;
  • отдельные оценки CFO, ошибки частоты дискретизации и начальной символьной фазы;
  • BER известной последовательности до CRC;
  • число найденных кадров и разобранных заголовков;
  • CRC каждого пакета;
  • решение защищённой тонкой CFO-коррекции и его диагностические величины;
  • корреляция маркера и корректно определённая EVM;
  • число и номера восстановленных фрагментов;
  • размер и SHA-256 переданного и принятого JPEG;
  • длительность сигнала и полезная скорость.

Каждое число вычисляется из текущего запуска. Перенесённые константы снабжаются ссылкой на лабораторную-источник. Невычислимая величина записывается как NaN или N/A, но не как правдоподобный ноль.

12.2. План программных артефактов

Предполагаемые файлы после отдельного согласования реализации:

  • experiments/lab043_pluto_to_rtlsdr.py;
  • tests/test_lab043_calibration.py;
  • data/processed/lab043/lab043_calibration.csv;
  • data/processed/lab043/lab043_frames.csv;
  • data/processed/lab043/lab043_summary.csv;
  • data/processed/lab043/lab043_report.txt;
  • графики калибровочного спектра, остаточной ошибки и доставки фрагментов.

12.3. Эталонный сырой IQ-захват

Не менее одного полного эталонного захвата до CFO- и SRO-коррекций сохраняется в data/raw/lab043/ и не добавляется в Git.

Формат отсчётов: NumPy .npy, одномерный массив complex64 в порядке приёма. Нормирование исходных 8-битных I/Q отсчётов и порядок I/Q должны быть однозначно описаны в метаданных. Рядом сохраняется UTF-8 JSON с тем же базовым именем и полями:

  • локальная метка времени и UTC;
  • идентификаторы устройств и модель тюнера;
  • версии Python, pyrtlsdr, pyrtlsdrlib, librtlsdr, pyadi-iio и pylibiio;
  • запрошенные и фактические частоты дискретизации, несущие и усиления;
  • число отсчётов, длительность, dtype и порядок байтов;
  • идентификатор и SHA-256 переданной формы сигнала;
  • результаты калибровки, применённые к этой записи;
  • SHA-256 файла .npy.

IQ-файл содержит всю единую последовательность приёма. Ожидаемое число отсчётов вычисляется как ceil(T_rx * Fs_rx_actual). Чтение выполняется последовательными блоками до достижения этого числа, последний блок обрезается только после получения требуемого количества отсчётов.

12.4. Разделение общего и лабораторного кода

Общие математические примитивы обнаружения двух известных тонов, оценки грубой CFO и относительной ошибки частот дискретизации, грубой частотной коррекции и передискретизации размещаются в protocol/bpsk_radio.py либо в другом подходящем существующем модуле protocol/. Каждый такой перенос сопровождается быстрым синтетическим тестом.

В experiments/lab043_pluto_to_rtlsdr.py остаются сценарий лабораторной, конкретное Fcal, три калибровочных захвата, методика оценки шума Lab043, режимы A/B/C, PRBS11, контрольный пакет, JPEG, отчётные артефакты, критерии приёмки и аппаратная последовательность. Общий код не зависит от конкретного JPEG и номера лабораторной.

13. Точка остановки перед аппаратным опытом

Программная реализация и синтетические проверки разрешены. Перед аппаратным опытом необходимо отдельно:

  1. пройти все обязательные программные проверки раздела 8;
  2. повторно проверить доступность устройств и чтение параметров обратно;
  3. получить подтверждение пользователя о схеме и отдельное разрешение на включение TX.

Способ Python-доступа к RTL-SDR уже выбран и не является вопросом точки остановки.

До отдельного разрешения передатчик не включается, усиление Pluto+ не изменяется, аппаратная калибровка и передача тонов, BPSK или JPEG не выполняются. Операции git add, commit, push, pull и fetch также не выполняются.