Управляем Icom PCR-1000 при помощи GnuRadio

Пару лет назад, я приобрел свой первый более-менее серьезный радоприемник: Icom PCR-1000. Одной из причин, по которой я выбрал именно его, было управление по RS-232. Итак, получил я его, подключил, погонял под Windows. Красота! Лишь одно омрачало прекрасное будущее, я пользуюсь Linux и FreeBSD, а родного софта от Icom под *nix системы как-то не наблюдалось.
Пошарившись в Интернете, я обнаружил что протокол управления приемником довольно прост, а посему почему бы не попробовать написать программу управления самому? Что ж, расчехляем свой любимый текстовый редактор,  понеслись!
Все самое важное для нас сконцентрированно на странице GM4JJJ о этом приемнике тут.
Внимательно изучаем и выписываем полезные команды, такие как включение-выключение, перестройка по частоте, и прочее. Далее. Нам понадобится графический интерфейс для управления. Признаюсь честно, я решил ваять GUI для PCR1000 используя GnuRadio только потому, что не владею написанием графических приложений под Linux :-) А GnuRadio нам предоставляет готовые блоки. Бери, да строй.
Так же подумаем об архитектуре нашей программы управления. Я решил разнести часть выполняющую непосредственно управление приемником и часть отвечающую за интерфейс.  Связь между серверной частью и клиентской будет реализована через блоки RPCXML Client. Это позволит, если я захочу, управлять приемником через Интернет.

Вот код нашего сервера:

Кстати, код сервера котрый мы написали, полностью GnuRadio-независим, он использует только стандартные модули Питона, и может быть запущен хоть на Raspberry Pi, хоть на Windows-машине.

Теперь, самое сложное — клиент. Сейчас вы поймете почему. :-)
Начну с конца — с показа результата, того что у нас должно получиться.
pcr1000_1Не сказать что дизайн блещет изысками, он был создан для моего личного использования. Итак, что мы тут видим: управление модуляцией, шириной фильтра, громкостью, шумодавом, и сдвигом промежуточной частоты.  Кнопки для включения и выключения AGC, антишумового фильтра и аттенюатора.
Управление частотой немного урезано, отсутствует поле для гигагерц (ну не заглядываю я на столь высокие частоты), и для герц (тоже как-то не сильно требовалось точная подстройка). Частоту можно менять:
а) Полозунком
б) Кнопками «+» и «-«. При этом частота поменяется на выбранное в выпадающем меню слева кол-во мегагерц или килогерц.
в) Прямым вводом значения частоты в поля.

На вкладки «Auto» и  «Programmable» можно не обращать внимания, это я хотел реализовать автоматический и программируемый проход по частотам, но лень-матушка помешала. А вкладки остались.

Теперь посмотрм как это выглядит в GnuRadio. Зажмурьтесь, это страшно :)
pcr1000_2
И это еще на картинке не все убралось. Для полноты ощущений рекомендую скачать граф, и открыть его в GnuRadio (ссылки как обычно внизу статьи).
Сердце и суть нашего графа — это блоки XMLRPC Client (по одному на каждый передаваемый серверу параметр) и блоки Variable Config которые служат нам для хранения и загрузки настроек.

Что, нетерпится проверить как все работает? Так давайте проверим!
Подключаем наш ICOM PCR-1000 к компьютеру, и запускаем серверную часть командой:
$ sudo ./rpcserver.py

Далее запускаем граф клиентской части на выполнение.
Теперь нажмем кнопку «Power» в нашем клиенте, и немного подвигаем полозунок громкости. В этот момент, в консоли где был запущен наш сервер управления, вы должны увидеть управляющие команды передаваемые приемнику:

H101
G000

J405D
J405D
J405B
J405B
J405B
J405B

И да, естественно вы должны услышать звук из динамика приемника.
Подвигайте полозунки, меняя частототу, и типы модуляции. Все это должно работать.
А теперь попробуйте понажимать кнопки «+» и «-» для движения повышения и понижения частоты. Хм… А они не работают. Почему? Да потому что в GnuRadio увы не возможно в графическом режиме настроить логику работы этих кнопок. Ведь что эти кнопки должны делать? Они должны брать текущее значение шага частоты из выпадающего списка, и добавлять (или вычитать) его к текущему значению частоты. Ну и попутно отслеживать не получилось ли значение больше 999 или меньше 0.
Но такую логику реализовать чисто графическими методами мы не можем. Но! Выход есть! Как всегда, нам поможет «доработка напильником».
Как я раньше уже упоминал, GnuRadio при запуске создает из  графической схемы блоков Python скрипт, и именно его запускает на исполнение. А что это значит? А то что мы можем внутри этого скрипта дописать свою, какую угодно сложную логику работы.
Идем в каталог с нашим grc файлом для клиента. Так как схему мы уже запускали, то мы видим рядом с grc файлом графа нужный нам питон-скрипт.
Вы можете его запустить щелкнув по нему мышью, или запустив в консоли командой:
$ ./pcrcontrol.py

Давайте создадим копию этого файла, потому что если мы будем вносить изменения в существующий файл, то при следующем запуске он будет опять перезаписан сгенерированным из графа скриптом. Пусть наш скопированный файл называется pcrcontrol_alt.py

Итак, нам предстоит усовершенствовать и доделать следующие вещи:
1) Наладить работу кнопок для передвижения по частоте.
2) Сделать так, чтобы по нажатию кнопки питания приемник сразу включался на нужной частоте. Сейчас кнопка включения только включает :-)

Итак приступим к ковырянию. Открываем наш скрипт в текстовом редакторе.
Нам нам надо модифицировать код для кнопок mhz_up, mhz_down, khz_up и khz_down
Вот как, к примеру, выглядит сгенерированный GnuRadio код для кнопки mhz_up.

Нам надо чтобы эта кнопка увеличивала текущую частоту, добавляя текущее значение выпадающего списка mhz_step к значению поля fr_mhz. Нет ничего проще! Берем и складываем значения возвращаемые функциями get_fr_mhz() и get_mhz_step(), а получившееся значение присваиваем полю fr_mhz используя функцию set_fr_mhz()

Таким же образом модифицируем функции для остальных кнопок:

 

 

Так, с кнопками расправились. Почти. Теперь надо сделать так чтобы значения в полях частот не вылезали за пределы 999 и 0.
Отыщем функцию set_fr_mhz

И добавим  условие в самое начало функции, что если значение получиось больше 999 то оно 0, и наоборот, если меньше 0, то 999.

Теперь подправим функцию set_fr_khz(). Тут чуточку сложнее, ибо нам при выходе за значение 999 надо добавить плюс 1 Мгц.
Было:

Стало:

С кнопками и границами закончили. Теперь делаем так, чтобы при нажатии кнопки включения передавались все настройки из клиента в приемник. Это реализуется тоже легко. Отыщем функцию set_power(), и в ней укажем передать через XMLRPC клиенты все текущие значения параметров.

Берем, и втыкаем передачу значений.

Вот впринципе и все. Все должно работать. Теоретически. Но вот в процессе написания этого поста я наткнулся на неприятный глюк, который я не наблюдал раньше. При нажатии на кнопку «Power» радио включалось, устанавливалсь частота, но вот уровень громкости, шумодава, и прочих вещей не передавались. Причем если нажимать все эти кнопки по отдельности — все отлично отрабатывало, громкость менялась, модуляция менялась. Все работало. Но вот по нажатию кнопки все разом не инициализировалось. Хотя раньше — все было ОК.
Постучавишь пару недель головой о стену корень проблемы был найден. XMLRPC сервер не хотел получать данные так быстро. Пришлось в кнопке реализовать «тормоз» поставив задержку в 1 секунду. В секцию импорта вписываем import time

А посредь вызовов XMLRPC в коде кнопки питания вписываем sleep в 1 секунду.

Вот теперь все! Можете сохранять файл, запускать его, и наслаждаться управлением приемником из GnuRadio. :)

Python сервер для управления ICOM PCR-1000
GRC граф для клиента
Изначальный скрипт клиента
Модифицированный клиент

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">