суббота, 17 августа 2024 г.

Как добавить поддержку нового мультиметра в libsigrok

Я узнал о Sigrok когда у меня появился простенький логический анализатор. Sigrok предоставляет библиотеки libsigrok (отвечает за поддержку оборудования и форматов ввода/вывода) и libsigrokdecode (отвечает за декодирование протоколов), а также различные фронтенды (PulseView, SmuView, sigrok-meter и sigrok-cli).

Недавно я подключил мультиметр Agilent U3402A к компьютеру и смог получать результаты измерений через последовательный порт. Можно было написать несложный скрипт, который будет периодически запрашивать показания мультиметра и сохранять полученные значения в файл в CSV формате. Далее их можно обработать в табличном процессоре, что-то посчитать и построить графики.

Но есть и более тернистый путь, который потенциально может пригодиться другим владельцам подобного мультиметра - добавить поддержку Agilent U3402A в libsigrok и получить все "плюшки" которые предоставляют его фронтенды.

Важная ремарка, я не знаком с кодовой базой libsigrok и не уверен что всё проделанное является верным. Но тем не менее решил описать свой путь, т.к. наступил на несколько граблей и кому-то это может сэкономить пару часов времени.

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

$ git clone git://sigrok.org/sigrok-util
$ cd sigrok-util/source
$ ./new-driver "Agilent U3402A"

В итоге будет создан файл 0001-agilent-u3402a-Initial-driver-skeleton.patch который нужно импортировать в репозитарий libsigrok.

$ cd ../libsigrok/
$ git am ../sigrok-util/source/0001-agilent-u3402a-Initial-driver-skeleton.patch

Этот патч затрагивает следующие файлы:

  • Makefile.am
  • configure.ac
  • src/hardware/agilent-u3402a/api.c
  • src/hardware/agilent-u3402a/protocol.c
  • src/hardware/agilent-u3402a/protocol.h

 В трёх последних файлах уже объявлен минимальный набор функций и выполнена регистрация нового драйвера.

Компиляция проекта не вызывает сложностей

$ ./autogen.sh
$ ./configure
$ make

Я не ставил все библиотеки, которые перечислены в выводе configure скрипта, а ограничился теми которые нужны для сборки моего драйвера:

  • libglib2.0-dev
  • libserialport-dev
  • libzip-dev
  • zlib1g-dev

В случае успешной компиляции новая библиотека будет находиться в .libs/libsigrok.so.4.0.0. Чтобы фронтенды Sigrok загружали именно этот вариант библиотеки нужно настроить переменную LD_LIBRARY_PATH или LD_PRELOAD. Я делал через LD_LIBRARY_PATH:

$ sigrok-cli -L | grep agilent
  agilent-dmm          Agilent U12xx series DMMs

$ export LD_LIBRARY_PATH=$PWD/.libs

$ sigrok-cli -L | grep agilent
  agilent-dmm          Agilent U12xx series DMMs
  agilent-u3402a       Agilent U3402A

До экспорта переменной LD_LIBRARY_PATH использовалась библиотека libsigrok, которая установилась по зависимостям sigrok-cli, а после - скомпилированная локально, которая добавляет поддержку драйвера agilent-u3402a.

Теперь нужно научить новый драйвер находить поддерживаемый мультиметр. Код добавляется в функцию scan(), которая находится в файле src/hardware/agilent-u3402a/api.c. Я подсматривал в код других драйверов чтобы понять как инициализиовать последовательный порт, записать в него команду и, прочитав ответ, решить подключено ли нужное устройство.

Для этого используется команда "RV\r\n" (без кавычек), которая запрашивает информацию о версии прошивки и модель мультиметра. Ответ должен быть в формате "vX.XX,M" (без кавычек).

Вначале не мог понять почему у меня не выполняется функция scan() если я указываю какой порт использовать драйверу. Оказалось что нужно добавить в функцию config_list() список параметров, которые поддерживает драйвер. После этого драйвер смог правильно опознать устройство:

$ sigrok-cli -d agilent-u3402a:conn=/dev/ttyUSB0 --scan
The following devices were found:
agilent-u3402a - Agilent U3402A v1.39 with 1 channel: P1

В строке идентификации устройства видна версия прошивки и количество каналов.

Следующий шаг - получить значение, которое измерено мультиметром. Для этого буду использовать команду "R1\r\n", которая возвращает последнее показания с основного индикатора. Пример ответа команды "+0.98788E+0" (без кавычек).

Для этого нужно написать реализацию нескольких функций:

  • dev_acquisition_start() в файле src/hardware/agilent-u3402a/api.c
  • agilent_u3402a_receive_data() в файле src/hardware/agilent-u3402a/protocol.c

Функции dev_open(), dev_close() и dev_acquisition_stop() я заменил на std_serial_dev_open(), std_serial_dev_close() и std_serial_dev_acquisition_stop() из стандартной реализации.

Функцию dev_acquisition_start() я "срисовал" с src/hardware/appa-55ii/api.c. А вот над функцией agilent_u3402a_receive_data() пришлось немного повозиться. Сначала добавил пропуск строк, которые возвращает мультиметр после ввода команд (я не нашёл их описания в документации, так что их значение это моя догадка):

  • "=>" (успех)
  • "!>" (ошибка)
  • "*>" (ожидание)

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

$ sigrok-cli -d agilent-u3402a:conn=/dev/ttyUSB0 -C P1 --samples 1
P1: 3.3007 V

Мультиметр на основном индикаторе показывает "3.3007 V DC". Т.е. план минимум уже выполнен, но в коде слишком много подпорок. Как минимум нужно написать определение текущего режима измерения (команда "R0\r\n") и разрядности индикатора. Дальше если не пропадёт интерес можно прикрутить переключение режимов измерений и показания второго индикатора.

Комментариев нет:

Отправить комментарий