GNU Radio это набор инструментов и готовых программных модулей, которые могут использоваться для разработки радиосистем, работающих про принципу SDR (Software Defined Radio). В этом руководстве (перевод статьи [1]) на простых примерах будет показано, как использовать среду разработки GNU Radio Companion (GRC) для создания различных звуков. Непонятные термины и сокращения ищите в разделе "Словарик" статьи [3].
[Введение в GRC]
Среда разработки GRC была создана для упрощения использования GNU Radio, чтобы можно было создавать файлы на языке Python с помощью графического редактора схем вместо того, чтобы писать код вручную. Давайте рассмотрим основной интерфейс GRC. Окно редактора состоит 5 частей: Library (библиотека), Toolbar (кнопки для быстрого запуска основных функций), Terminal (окно терминала, куда выводится информация о запуске кода и ошибках), и Workspace (рабочая область редактора, где создается схема проекта из отдельных библиотечных блоков) и Variables (область переменных проекта). Для наглядности на рисунке ниже эти области редактора GRC обозначены разными цветами:
Среда разработки GRC в среде Windows запускается двойным кликом на иконке GNURadio Companion:
В среде Linux редактор GRC можно запустить из командной строки:
$ gnuradio-companion
Примечание: если у Вас GRC не запускается, то необходимо выполнить процедуру установки пакета GNU Radio, описанную в статье [2].
Поиск блоков. Библиотека GRC содержит различные блоки, из которых конструируется исполняемый проект GRC. Все эти блоки устанавливаются вместе с пакетом GNU Radio, и каждый блок представляет модуль готового функционального кода. Список блоков находится в правой части окна редактора GRC.
Поначалу кажется, что очень трудно ориентироваться среди такого большого списка блоков. Например, если нужно генерировать сигнал, в какой категории находится необходимый для этого блок? Если внимательно просмотреть иерархию списка блоков, то Вы найдем категорию Waveform Generators, и скорее всего это то, что нам нужно. Однако если нужно найти блок, чтобы отобразить данные, то как лучше всего это сделать? Блоки, которые принимают сигнал, имеют в своем названии Sink; чтобы его найти, можно воспользоваться полезной функцией поиска блоков. Для этого кликните мышью на иконку с лупой в верхней правой части окна, и появится поле ввода, где можно ввести часть имени блока (альтернативно для поиска можно воспользоваться комбинацией клавиш Ctrl+F):
По мере ввода искомого имени блока отображаемый список дерева блоков будет уменьшаться, и найти нужный блок будет намного легче. Попробуйте ввести sink, и Вы увидите, что в списке блоков будут показаны только те блоки, имена которых содержат буквы sink.
Теперь можно добавить нужный блок в проект. Это это делается либо двойным кликом на имени блока, либо его перетаскиванием в рабочую область редактора GRC (Workspace, основная часть экрана GRC). Добавьте блок QT GUI Time Sink в поле редактора GRC.
Изменение свойств блока. Workspace GRC (основная область экрана) содержит все наши блоки, из которых строится проект (проект GRC называют flowgraph, или flow graph, что отражает его графическое отображение в виде схемы). Внутри каждого блока есть набор различных параметров. Диалог редактирования параметров открывается двойным щелчком на блоке, добавленном в Workspace GRC.
Однако в проекте GRC также имеются специальные блоки, которые автоматически добавляются, когда создается новый проект. Это блок Options, где находятся основные настройки (опции) проекта, и блок Variable, где содержится переменная samp_rate (задает частоту дискретизации потока данных). Откройте двойным щелчком на блоке Options окно диалога редактирования его свойств:
Свойства блока Options, назначенные по умолчанию, можно поменять, чтобы проект удовлетворял Вашим требованиям. Попробуйте удалить одну букву из имени идентификатора блока ID, и ID примет синий цвет. Это означает, что информация параметра редактируется, но новое значение параметра еще не сохранено. Попробуйте изменить параметр Canvas Size в значение 300,300 и кликните на кнопку OK. Вы увидите, что рабочее пространство редактора уменьшилось. Нажмите комбинацию Ctrl+Z, чтобы отменить введенные изменения и вернуться к размеру Workspace по умолчанию.
В диалоге свойств блока Options есть и другие закладки, одна из которых называется Documentation.
Из текста документации (выделенный блок на картинке ниже) можно понять, что свойство ID используется для назначения имени модулю исходного кода файла Python, который генерируется из проекта flowgraph.
Попробуйте теперь удалить полностью строку ID. Обратите внимание, что теперь в нижней части окна диалога параметров блока появится сообщение об ошибке. Кроме того, параметр ID станет красным, что явно указывает на место ошибки.
Теперь поменяйте строку ID на tutorial_two_1, так обычно поступают, чтобы рационально управлять проектами и давать им понятные, документирующие имена. Также убедитесь, что в свойстве Generate Options выбран вариант QT GUI, поскольку мы используем блок QT GUI Sink, а не WX GUI Sink (блоки QT и WX основаны на разных графических библиотеках). Более новые версии пакета GNU Radio по умолчанию используют библиотеку QT GUI.
Примечание: следует иметь в виду, что разработчики в будущих релизах планируют отказаться от визуальных компонентов WX в пользу использования компонентов QT.
Поле ID позволяет нам проще управлять именами файлов проектов. Хотя мы сохраняем GRC flowgraph как имяфайла.grc, генерация и выполнение этого flowgraph создаст другой выходной файл - модуль на языке Python с расширением *.py, имя которого будет создано из значения ID блока Options. GRC это графический интерфейс, который находится поверх рабочего программного окружения GNU Radio, в основе которого лежит язык Python. GRC транслирует flowgraph, который мы создали в GUI GRC, в скрипт Python, который можно запустить как настоящую программу Python. Итак, ID блока Options используется для именования файла Python, и он будет сохранен в ту же директорию, что и файл flowgraph с расширением *.grc file. По умолчанию ID назначается в top_block, так что генерируемый скрипт Python получит имя top_block.py. Изменение ID позволяет нам менять имя сохраняемого скрипта, это помогает повысить качество управления файлами проектов.
Еще один результат связки GRC-Python состоит в том, что в GRC все основано на языке Python. Фактически все параметры и органы управления свойствами блока или переменные, которые мы используем, интерпретируются как программные объекты Python. Это означает, что мы можем установить свойства блока, используя вызовы функций Python, таких как numpy, или других функций GNU Radio. Например, это используется для вызова в filter.firdes инструментария создания фильтра (filter design tool) из GNU Radio, чтобы выполнить сборку коэффициентов нашего фильтра (filter taps).
Еще одно полезное свойство - разными цветами в диалоге параметров обозначаются типы параметров в тех полях, куда вводятся значения. Это деление на типы данных будет более подробно рассмотрено позже. Соответствие цветов типам можно посмотреть через меню Help -> Types.
[Мой первый flowgraph]
У нас уже есть общее представление, как искать нужные блоки, как добавлять их в Workspace, и как редактировать свойства (параметры) блока. Давайте теперь сконструируем flowgraph, состоящий из блока Signal Source (источник синтезируемого сигнала), выходной сигнал которого проходит через блок Throttle, и затем поступает в блок Time Sink (график изменения сигнала во времени, осциллограмма). Блоки соединяются друг с другом путем кликом на их цветных портах out и in:
Назначение блоков Signal Source и Time Sink понятно из названия, однако назначение блока Throttle не совсем очевидно. Он необходим для снижения нагрузки на процессор, когда в качестве источника используется синтезируемый сигнал - блок Throttle регулирует поток данных так, чтобы среднее значение частоты выборок соответствовало заданной.
Тулбар. Верхняя панель окна редактора GRC снабжена кнопками вызова инструментов (так называемый тулбар), повышающими удобство выполнения часто используемых операций (специально для тех, кто не любит пользоваться горячими клавишами). Здесь есть кнопки для генерации выходного скрипта Python, кнопка Generate the flow graph, что соответствует пункту меню Run -> Generate (горячая клавиша F5) и кнопка запуска скрипта на выполнение Execute the flow graph, что соответствует пункту меню Run -> Execute (горячая клавиша F6). Есть также кнопка Kill the flow graph (горячая клавиша F7), которая останавливает выполнение скрипта GRC, и другие кнопки.
Кликните на кнопку Generate (или нажмите клавишу F5), и посмотрите в область терминала (Terminal), находящую в левой нижней части окна редактора GRC. Здесь будет выводится текст с информацией, описывающей генерацию файла Python с тем же именем, которое мы задали в параметре ID блока Options. Терминал отображает важные сообщения, такие как сообщения об ошибках и предупреждения (errors, warnings). Наиболее часто встречающаяся ошибка - когда нет соответствия опции генерации кода с типами используемых визуальных блоков.
Выполнение. После успешной генерации скрипта нажмите на кнопку Execute (горячая клавиша F6), чтобы запустить flowgraph на выполнение. Отобразится примерно такое окно:
Это комплексная синусоида в форме ejwt, где на графике видны две синусоиды, сдвинутые друг относительно друга на фазу 90°. Если Вы пока не знакомы с комплексными сигналами, то можете не обращать внимание на этот факт, понимание придет позднее. Теперь попробуйте остановить выполнение скрипта кнопкой Kill (F7), и окно с графиком блока Time Sink GUI закроется.
Типы данных. Давайте подробнее рассмотрим типы данных, которые в GRC для наглядности обозначаются разными цветами. Цветовую легенду типов можно увидеть с помощью меню Help->Types.
Тип и цвет
Байт
Описание
Complex Float 64
16
Комплексные данные (вещественная I составляющая 64 бита и мнимая Q составляющая 64 бита).
Complex Float 32
8
Комплексные данные (вещественная I составляющая 32 бита и мнимая Q составляющая 32 бита).
Complex Integer 64
16
Комплексные данные (вещественная I составляющая 64 бита и мнимая Q составляющая 64 бита).
Complex Integer 32
8
Комплексные данные (вещественная I составляющая 32 бита и мнимая Q составляющая 32 бита).
Complex Integer 16
4
Комплексные данные (вещественная I составляющая 16 бит и мнимая Q составляющая 16 бит).
Complex Integer 8
2
Комплексные данные (вещественная I составляющая 8 бит и мнимая Q составляющая 8 бит).
Float 64
8
Числа с плавающей запятой двойной точности (аналог long double).
Float 32
4
Числа с плавающей запятой обычной точности.
Integer 64
8
Целые числа со знаком, 64 бита.
Integer 32
4
Целые числа со знаком, 32 бита (int).
Integer 16
2
Целые числа со знаком (short).
Integer 8
1
Целые числа со знаком (char).
Bits
1
Биты (отдельные биты байта).
Message Queue
Очередь сообщений.
Async Message
Асинхронное сообщение.
Bus Connection Wildcard
Подключение к шине.
Видно, что типы данных в основном такие же, как и во многих языках программирования. По умолчанию входы и выходы наших блоков имеют синий цвет, что означает тип данных Complex Float 32, в этом типе данных есть реальная (real) и мнимая (imaginary) части, каждая из которых имеет тип Float 32. Комплексный тип данных мы можем представит как два раздельных канала, в одном из которых данные real, и в другом данные imaginary. Если попробовать поменять тип данных Signal Source на Float (это можно сделать через диалог параметров блока, если поменять Output Type на Float), то мы увидим, что порт Signal Source сменит цвет на оранжевый (такой цвет имеет тип Float 32), и что стрелка линии соединения поменяет цвет на красный. Изменение цвета стрелки на красный сигнализирует об ошибке - на разных концах соединения нет соответствия типов данных. Если теперь попробовать запустить flowgraph, то будет выведено сообщение об ошибке:
Сообщение об ошибке говорит о том, что на указанном соединении не совпадает размерность типов. Причина в том, что наш тип данных на выходе блока Signal Source не совпадает с размерностью данных на входе блока Throttle. GNU Radio не позволяет нам соединять цепочки блоков с разными типами данных.
Поменяйте тип данных на всех входах и выходах блоков на Float. После этого можно сгенерировать и запустить flowgraph, как раньше (также поменяйте ID у блока Options на tutorial_two_2, чтобы был сгенерирван скрипт с новым именем). На этот раз будет отображена одиночная синусоида:
[Более сложный flowgraph]
Теперь мы можем сами создавать более сложные схемы flowgraph со многими специфическими параметрами. Пример flowgraph ниже демонстрирует такие новые концепции в GNU Radio, как использование окон с вкладками и регуляторы QT GUI Range. Обратите внимание, что не все параметры блока отображены в главном окне, поэтому используйте текст ниже (не только скриншот), чтобы установить параметры каждого блока.
Подробное описание изменений параметров:
- Начните новый flowgraph с ID "tutorial_two_3". - Вставьте блок QT GUI Tab Widget, измените его ID на "tab", параметр Num Tabs на 2, Label 0 поменяйте на "Time", Label 1 поменяйте на "Frequency". - Вставьте блок QT GUI Range, ID поменяйте на "samp_rate", Default Value на "5*freq", Start на "0.5*freq", Stop на "20*freq", Step на "200". - Вставьте блок Variable, ID поменяйте на "freq", Value на "2e3" (соответствует 2000 Гц). - Вставьте блок Signal Source, поменяйте его параметр Frequency на "freq", Waveform на "Sine". - Вставьте блок QT GUI Time Sink, поменяйте GUI Hint на "tab@0". Вставьте блок QT GUI Frequency Sink, поменяйте его GUI Hint на "tab@1". - В блоке Throttle, установите Sample Rate на 32e3 (почему так, рассмотрим позже).
После проверки всех изменений выполните Generate (F5) и Execute (F6). Запуститься окно с двумя закладками, на одной из которых показан сигнал в домене времени (time domain), а на другой сигнал в домене частоты (frequency domain). Также должен быть слайдер, который управляет частотой дискретизации sample rate источника сигнала (блок Signal Source) в реальном времени (путем изменения значения переменной samp_rate). Изменение положения движка этого слайдера должно менять отображение синтезируемой частоты в доменах времени (график блока QT GUI Time Sink) и частоты (график блока QT GUI Frequency Sink).
Частота выборок сигнала (sampling rate) - очень интересная тема в GNU Radio, очень важный параметр любой платформы SDR. Подробнее о том, как влияет частота выборок на сигнал и его отображение, см. в статье [4].
[Домашнее задание]
Попробуйте самостоятельно провести некоторую работу, и ответить на возникающие при этом вопросы.
1. Если Вы поместите блоки Signal Source и Abs в проект flowgraph, и соедините их друг с другом, ничего не изменяя, то произойдет ошибка.
1a. Как мы узнаем об ошибке? 1b. Как мы узнаем о том, какая ошибка и где она произошла? 1c. Как исправить ошибку?
1a. Между блоками Signal Source и Abs стрелочка будет красной, потому что по умолчанию тип выходных данных у блока Signal Source будет Complex, а у блока Add тип входных данных Int. 1b. Нажатие на кнопку View flow graph errors покажет окно с подробным описанием ошибки. 1c. У блока Signal Source можно поменять тип выходных данных на Int.
2. Предположим, что у нас есть 2 сигнала в проекте flowgraph, которые нужно перемножить друг с другом.
2a. Как нам найти блок, который перемножает сигналы? 2b. Как мы используем в GRC блок умножения? 2c. Что еще мы можем сделать в плане изменений в этом блоке?
2a. Можно воспользоваться поиском блоков (Ctrl+F), и в строке поиска ввести Multiply. 2b. Блок Multiply можно применить для умножения частот. 2c. По умолчанию у блока Multiply два входа, что позволяет перемножить 2 источника сигнала. Можно увеличить количество входов (параметр Num Inputs), чтобы перемножать большее количество сигналов.
3. Если мы видим, что у блока есть не используемый, помеченный серым цветом входной порт, то каким этот порт мог бы быть?
Это мог быть входной порт, подающий дополнительный сигнал, влияющий на поведение блока. Например, для Signal Source это мог бы быть вход, определяющий параметр Offset (смещение).
4. Если Вы запустили flowgraph и увидели сообщение об ошибке "AttributeError: 'top_block_sptr' object has no attribute 'top_layout'", то что тут не так, и как исправить ошибку?
Возможно, что в графе применен пользовательский блок, при разработке которого была допущена ошибка.
5. Вопросы по обработке сигналов.
• Предположим, что нам нужно обработать голосовые аудиоданные, и у нас есть микрофон, который не выдает частот выше 8 кГц. Какую минимальную частоту выборок (sampling rate) мы должны использовать? • Нам нужно оцифровать радиосигнал в диапазоне от 99.9 МГц до 100.1 МГц. Какова должна быть минимально применимая частота выборок?
• sampling rate должна быть как минимум 16 кГц (2 * 8 кГц). • Полоса частот составляет 200 кГц, поэтому частота выборок должна быть как минимум 400 кГц, если это сигнал в обычном виде (не комплексный), или 200 кГц, если мы делаем комплексную оцифровку сигнала, как это делается обычно в радиоустройствах SDR.