Эксперименты с HackRF (часть 2) – GNU Radio Companion и распознавание радиосигнала на практике

Эксперименты с HackRF (часть 2) – GNU Radio Companion и распознавание радиосигнала на практике

Эксперименты с брелоком от машины и анализатором сигнала baudline были весьма увлекательны (более подробно об этом рассказано в предыдущей статье). Теперь мы попробуем сделать что-то более серьезное, когда выходной сигнал представляет собой большую ценность для нас, (сигнал от автомобильного брелока не представляет особой ценности, поскольку после расшифровки мы, по сути, получаем большое случайное число).

Автор: dragorn

Эксперименты с брелоком от машины и анализатором сигнала baudline были весьма увлекательны (более подробно об этом рассказано в предыдущей статье). Теперь мы попробуем сделать что-то более серьезное, когда выходной сигнал представляет собой большую ценность для нас, (сигнал от автомобильного брелока не представляет особой ценности, поскольку после расшифровки мы, по сути, получаем большое случайное число).

В этом эксперименте подопытный передатчик работает на частоте 433 МГц на платформе Arduino, при помощи которой можно создавать интерактивные электронные объекты.

Рисунок 1: Экспериментальный передатчик

Нам известно, что сигнал передается на частоте 433 МГц, так что захват сигнала (при помощи HackRF) будем делать на частоте 435 МГц:

$ hackrf_transfer -r 435MHz-ASK-HACKRF-CW-8M.iq -f 435000000 -s 8000000

После загрузки результатов работы HackRF в анализатор сигнала Baudline (о том, как это сделать, рассказано в предыдущей статье) получим следующее:

Рисунок 2: Сигнал в анализаторе Baudline

Мы получили приемлемый сигнал и теперь загрузим эти данные в GNU Radio Companion (GRC).

GRC позволяет строить блок-схемы при помощи графического интерфейса. Затем эти блоки компилируются в python-код и могут использоваться независимо от GRC. Написанием кода при помощи блоков GNU Radio можно достичь того же самого, однако GRC содержит много полезных функций, и с ним проще работать новичкам, к которым я также себя причисляю. Однако у графической оболочки GRC есть и обратная сторона: иногда бывает трудно найти нужный блок. В этом случае попробуйте поискать его по имени.

Первым делом необходимо конвертировать файл логов HackRF в формат, который можно прочесть в GNU Radio. Логи HackRF – это данные, представляющие собой пары IQ, которые хранятся как 8-ми битные беззнаковые целые (подробнее с IQ или квадратурной дискретизацией можно ознакомиться здесь). Компонентам GNU Radio, как правило, необходимы комплексные IQ-данные, и, следовательно, мы должны преобразовать наш файл к этому формату (алгоритм показан на рисунке ниже):

Рисунок 3: Блок-схема алгоритма преобразования сигнала в формат для GNU Radio

XML-файл для GRC можно взять здесь.

Вначале блок схемы используется стандартный компонент «File Source» для загрузки файла. Затем блок «UChar to Float» конвертирует беззнаковые 8-ми битные целые числа в числа с плавающей точкой. В блоке «Deinterleave» происходит разделение общего потока данные (IQIQIQ) на два отдельных канала (I и Q), после чего они вновь объединяются, но уже в формате комплексного числа (для этого используется блок «Float to Complex»). Подобный формат как раз и используется в GNU Radio.

После прохождения через блок «Add Const» данные центрируются вокруг 0 (поскольку в HackRF используются беззнаковые целые в диапазоне от 0 до 256, данные центрируется около 127). (Я должен был сообщить об этом Майку Оссману – еще одно весьма веское основание для регистрации в проекте HackRF на Kickstarter – если будет поставлена более амбициозная цель мы получим видео курсов по GNU Radio)

Самый последний блок «Throttle» используется для сжатия частоты выборки до 8 МГц, чтобы система, где используется этот сигнал, работала корректно. В целом я выяснил, что имеет смысл сжимать частоту выборки сигнала, поскольку в противном случае могут возникнуть случайные взаимодействия между частотой выборки и шириной спектра сигнала (в случае с IQ-данными частота выборки и ширина спектра сигнала взаимосвязаны).

На стадии сжатия используется переменная throttle_rate (самый верх блок схемы), которая позволяет задавать частоту для различных сигналов. Здесь нас поджидает один сюрприз: GRC не показывает числа в том формате, в котором они на самом деле используются! GRC допускает числа в обычном или научном формате (шестнадцатеричные, восьмеричные или любые другие, которые поддерживает Python), однако отображаются эти числа в удобочитаемом формате (в этом формате числа задавать нельзя). В нашем случае допустимые значения 8000000 или 8e6, однако, число 8М недопустимо.

Теперь у нас есть файл, загруженный в нужном формате. Что же дальше?

Первый шаг – более подробное изучение нашего сигнала. Мы можем сразу же после сжатия сигнала направить его в блок с быстрым преобразованием Фурье:

Рисунок 4: Параметры блока быстрого преобразования Фурье

На выходе преобразователя получаем такой сигнал:

Рисунок 5: Сигнал после преобразователя

На рисунке выше мы видим пик на частоте захвата (435 МГц) и часть передаваемого сигнала в районе частоты 433.8 МГц.

Теперь рассмотрим настройки преобразователя. По умолчанию GNU Radio ничего не знает о несущей частоте (если ее не задать, считается, что эта частота равна нулю). В этом случае сам сигнал был бы на частоте -1.2 МГц. Меня это, конечно же, не устраивает, и я буду выставлять реальные значения:

Рисунок 6: Параметры FFT-преобразователя

Параметры «Sample Rate» (частота выборки) и «Baseband Freq» (частота захвата) соответствуют переменным «samp_rate» и «capture_freq». Параметр «Sample Rate» должен совпадать с входным сигналом (в нашем случае это 8МГц; то значение, до которого мы сжимали выборку). В противном случае преобразователь будет работать некорректно.

В GRC мы используем соответствующие блоки с переменными:

Рисунок 7: Блоки с переменными

Поскольку мы знаем, где находится наш сигнал, захват производился на смещенной частоте в 435МГц для того, чтобы избежать пика на рабочей частоте. Кроме того, мы захватили намного больше данных, чем нам нужно (если сравнивать с шириной спектра). Для того чтобы решить обе эти проблемы одним махом, мы будем использовать блок "Frequency XLating FIR Filter" (КИХ-фильтр с переносом частоты).

Рисунок 8: Используем промежуточный КИХ-фильтр

Использование подобного фильтра позволяет одновременно решить три задачи:

  1. Сместить несущую частоту сигнала. Мы как бы «прокручиваем вниз» до желаемого участка сигнала.
  2. Использовать полосовой фильтр для удаления тех участков сигнала, которые нам не нужны. Далее, когда мы будем проводить измерения, мы будем измерять только наш сигнал без примесей радиошума.
  3. Разделить сигнал. Это позволит уменьшить ширину спектра и число выборок сигнала, что уменьшит вычислительные мощности для обработки. Поскольку уменьшается частота выборки, мы должны учесть это при настройке последующих блоков.

Рисунок 9: Параметры промежуточного КИХ-фильтра

Здесь мы для установки параметра децимации (или разделения) вновь используем переменные, поскольку этот способ намного удобнее. Для получения значения децимации нам необходимо разделить входное значение частоты дискретизации на выходное ее значение (в нашем случае выходное значение равно 50 кГц, относительно произвольное значение). 50 кГц – достаточно широко, чтобы охватить весь наш сигнал, и в дальнейшем у нас не возникнет никаких проблем, поскольку сигнал очень сильный. В реальной жизни нам, возможно, следует использовать намного меньшее значение. Мы должны преобразовать результат к целому числу для корректной работы GRC (для этого используем Python-функцию int).

К параметру «Taps» привязываем переменную firdes_tap (подробнее об этом чуть позже). Этот параметр позволяет изолировать наш сигнал.

И, наконец, параметром «Center Frequency» мы задаем смещение несущей частоты (опять же с использованием переменных). Нам необходимо сместить наш сигнал вниз, следовательно, смещение примерно равно 1.2 МГц (или 435 МГц – 433 МГц). Поскольку смещение происходит вниз, значение должно быть отрицательным.

Я использую GNU Radio 3.6. Однако самая последняя версия – 3.7, в которой произошли некоторые изменения. В частности, параметр «Center Frequency» рассматривается как «фактическая» несущая частота. Если вы используете GNU Radio 3.7, удалите отрицательный знак. С этими и другими изменениями в новой версии можно ознакомиться здесь.

[Обновление от 9 февраля 2013 года – После обновления GNU Radio, мне не понятно, в чем заключаются изменения, поскольку отрицательное смещение работает прекрасно, а положительное – нет.]

Рисунок 10: Значения переменной firdes_tap

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

  1. Коэффициент усиления = 1 - мы не усиливаем сигнал.
  2. Частота выборки (samp_rate) – соответствует частоте выборки входного сигнала (в нашем случае 8МГц).
  3. Частота среза = 2000 – мы определяем частоту среза в 2 КГц.
  4. Частота переходной полосы фильтра = 20000 – устанавливает переходную полосу фильтра, которая должна быть примерно в два раза меньше, чем частота выборки (в нашем случае конечная частота выборки равна 50 кГц, следовательно, переходная частота около 20 кГц).

Параметры WIN_HAMMING и 6.76 указывают GNU Radio на то, что нужно использовать оконный фильтр. На эти параметры можно не обращать внимание.

После прохождения сигнала через фильтр, децимацию и повторное центрирование, мы вновь пропускаем сигнал через преобразователь Фурье. На выходе получается следующее:

Рисунок 11: Сигнал, пропущенный через фильтр и преобразователь

Обратите внимание, что у сигнала уменьшилась ширина спектра, а также произошло сглаживание вне рассматриваемой нами области.

Выставляя различные значения у низкочастотного фильтра, можно получить разные результаты (более подробно о настройке низкочастотного фильтра можно прочитать здесь).

Не забудьте настроить преобразователь Фурье:

Рисунок 12: Настройки преобразователя

Особенно следует обратить внимание на изменение частоты выборки нашего сигнала (до 50 кГц) и несущей частоты. Таким образом, мы установили в параметры «Sample Rate» и «Baseband Freq» соответствующие переменные.

Теперь у нас есть отфильтрованный, отцентрированный, узкополосный амплитудно-модулированный сигнал. Что же мы можем с этим сделать?

При амплитудной модуляции происходит изменение амплитуды, и мы можем обнаружить подобный сигнал путем измерения этого параметра:

Рисунок 13: Схема измерения сигнала

Блок «Complex to Mag» приводит комплексный IQ-сигнал к абсолютной величине. Поскольку наш сигнал очень сильный и к тому же пропущен через фильтр, мы может прибегнуть к вычислению амплитуды. Если бы сигнал был нефильтрованный и присутствовал бы шум, мы не смогли бы прибегнуть к использованию столь простого метода.

Обратите внимание на цвет выходного вывода «Out» у блока «Complex to Mag» (оранжевый вместо синего). Это означает, что выходной сигнал представляет собой значение с плавающей точкой и, следовательно, входные блоки должны принимать сигнал именно такого типа.

Рисунок 14: Установка типа принимаемого сигнала

Мы можем установить тип сигнала в выпадающем меню параметра «Type».

Теперь при запуске GRC выходной сигнал представляет собой вычисленную магнитуду. Если мы прокрутим при помощи колеса мыши временной диапазон, то увидим такую картину:

Рисунок 15: Графическое изображение вычисленной магнитуды сигнала

Сигнал на рисунке выше выглядит замечательно, как и сигнал, полученный при просмотре в анализаторе Baudline. В последнем случае мы прибегли к изолированию и выделению полезного сигнала и конвертированию его в последовательность вычисленных магнитуд.

Рисунок 16: Сравнение двух сигналов

Вы можете загрузить файл с выборкой данных отсюда, а GRC-файл – отсюда.

В следующей статье мы попробуем преобразовать сигнал из GRC обратно к первоначальной выборке.

Спасибо Майку Оссману, всем с канала #hackrf на Freenode и вообще всем, кто помогал в написании этой статьи и высказывал свои замечания.

Теория струн? У нас целый оркестр научных фактов!

От классики до авангарда — наука во всех жанрах

Настройтесь на нашу волну — подпишитесь