Самодельная мобильная лаборатория из старого мультиметра и подручного телефона

в 8:13, , рубрики: DIY, open source, selectel, Мультиметр, разработка
Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 1

Эта история началась с того, что я допиливал свой пет-проект по обработке данных. В ходе работы мне попался старый, но надежный мультиметр. Я долго им пользовался ранее, изучая электронику. Сам прибор неплохой, но софт под него сильно устарел, да и заточен он только под Windows. Так я занялся реверс-инжинирингом, отладкой обмена сообщениями и сборкой библиотек для телефона. Подробности — под катом!

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 2Используете Terraform? Помогите нам сделать новый сервис лучше. Пройдите короткий опрос — мы выберем самые интересные кейсы и пригласим вас на онлайн-интервью. За участие — плюшевый Тирекс или бонусы на услуги Selectel.

Для подобного проекта можно использовать любую платформу, для которой получится собрать Qt-приложение.

Используйте навигацию, если не хотите читать текст целиком:
Предыстория
О подключении по USB
Немного кода
Автоматизация
Заключение

Предыстория


На первых курсах вуза мне сильно хотелось иметь профессиональное оборудование для работы с электроникой, но стоимость для студента была заоблачной. К счастью, я мог использовать различные приборы на кафедре, но их не унести домой. Так я наткнулся на компактные измерительные устройства Hantek. Они представляли собой плату в металлическом корпусе, с одного торца которого были разъемы для подключения щупов, а с другого — USB-интерфейс.

Блоками Hantek365 и DSO-6204 я надолго оснастил свою домашнюю лабораторию. Оба устройства были все время подключены в ПК, а измерительные щупы находились в стакане для канцелярии. Это позволяло в любой момент открыть софт и провести нужные измерения. Во избежание помех в первый год пользования приобрел USB-изоляторы.

Забавный факт: китайские производители даже предлагали свой аналог NI PXI rack, но большого распространения они не получили.

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 3

Источник.

После переезда на Linux Mint в начале магистратуры мультиметр я практически забросил, т. к. не было софта под него. Заменил его обычным ручным UNI-T.

Спустя лет семь на проекте понадобилось записать изменение тока на электроприводе и я вспомнил про имеющийся прибор. Снял необходимые характеристики и отправил девайс дальше пылиться на полке. И тут я подумал: а почему бы не написать к нему оболочку? С этого и началось веселое приключение на 20 минут.

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 4

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 5

О подключении по USB


По запросу «hantek 365 source» буквально первая ссылка в поисковой выдаче привела меня в нужный репозиторий на GitHub.

При подключении по USB девайс работает по крайне простому протоколу. Как и USB/CDC-устройства, мастер посылает запрос на чтение и ожидает ответ от прибора. Если ответ получен в течение отведенного времени, его можно обработать. Ответ от устройства в виде набора байт выглядит следующим образом:

  • 0 байт — статус измерения,
  • 1 байт — содержит ASCII знак измерения (2B +, 2D -),
  • 2-5 байты — четыре ASCII символа числового значения,
  • 7 байт — позиция десятичной точки,
  • 8 байт — режима измерения,
  • 10 байт — множитель,
  • 11 байт — единица измерения,
  • 12 байт — шкала текущего измерения,
  • 13-15 байты — r n 0x00 — завершение пакета данных.

Анализируя формат сообщения в найденном примере кода, заметил, что выполняется занятная операция вывода:

for (i = 0; i < 4; i++)
          {
            fprintf(stdout, "%c", databuff[i + 2]);
            if ((dpos - 0x30) >> i == 1)
            {
              fprintf(stdout, ".");
            }
          }

То есть устройство содержит готовый ответ измерения в виде ASCII-кода, а разделительную точку — в виде позиции бита седьмого байта. Также биты множителя (10) и единицы измерения (11) хранят информацию в виде позиции бита. Например, так выглядят единицы измерения:

  • 0x01 = 0b00000001 — температура по Фаренгейту, °F;
  • 0x02 = 0b00000010 — температура по Цельсию, °C;
  • 0x04 = 0b00000100 — частота, Гц;
  • 0x20 = 0b00100000 — сопротивление, Ом;
  • 0x40 = 0b01000000 — ток, амперы;
  • 0x80 = 0b10000000 — напряжение, вольты.

А как получены эти значения? Одно из предположений — кто-то из разработчиков прибора выкладывал исходные коды. Или же просто проанализировали трафик интерфейса через Wireshark. Я нередко использовал такой метод поиска необходимых данных при доработке библиотеки для CDC. Таким же методом определил значение последних 4 байт.

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 6

Все байты как на ладони: +0,718 мВ (4=0b100 — три символа после запятой, 0x40 — милли, 0x80 Вольт).

Что внутри

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

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 7

Простая, но эффективная конструкция.

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

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 8

В качестве конвертора интерфейсов на обратной стороне платы располагается STM32F103c8T6 (практически bluepill), который связан с микросхемой-мультиметром FS9922-DMM4 (даташит на эту микросхему) через оптопары. Контакты STM выведены как на интерфейс USB-B, так и на разъем USBXI.

В целом, там всего четыре контакта. При большом желании можно развести собственную плату для рэка из набора разъемов PCIe 1x. Однако несмотря на схожесть разъема и назначения, интерфейс PCIe и USBXI несовместимы! В лучшем случае — сожжете порт на STM32.

Немного кода


Основная логика работы, как и ранее, сделана на Qt C++ и доступна в репозитории. Помимо мультиметра думаю добавить интерфейс для аналогичного осциллографа, например DSO-6022.

В первую очередь убеждаемся, что есть хотя бы одно оборудование из перечня знакомых, и выставляем соответствующее значение.

QtHantek* QtHantek::createDevice(QObject *parent) {
    libusb_context *context = NULL;
    libusb_device **list = NULL;
    int rc = 0;
    size_t count = 0;
    rc = libusb_init(&context);
    if (rc != 0)
    {
        qWarning () << "USB not available!";
        return new QtHantek(0,parent);
    }
    count = libusb_get_device_list(context, &list);
    if (count < 1){
        qWarning () << "Devices not found!";
        return new QtHantek(0,parent);
    }
    if (count>0) {
        for (size_t idx = 0; idx < count; ++idx)
    {
        libusb_device *device = list[idx];
        libusb_device_descriptor desc = {0};
        rc = libusb_get_device_descriptor(device, &desc);
        if (rc != 0)
            continue; // skip if error
        if (desc.idVendor == availableDevices[0][0] && desc.idProduct == availableDevices[0][1]){
                    libusb_exit(context);
                    return new QtHantek365(parent);
         }
    }
    }
    libusb_free_device_list(list, 1);
    libusb_exit(context);
     return new QtHantek(0,parent);
}

Вся работа с мультиметром по USB заключаются в выборе режима работы и считывания буфера с обратным значением.

Так, если все ок, производим стандартную процедуру инициализации интерфейса, выбираем текущий режим (по умолчанию — 60V DC) и направляем его устройству для инициализации работы и старта обработки данных.

int init()
    {
        libusb_device **list = NULL;
        m_husb = libusb_open_device_with_vid_pid(m_ctx, 1155, 22306);
        if (m_husb == nullptr)
        {
            qDebug() << "Cannot open device!";
            return -2;
        }
        if (libusb_claim_interface(m_husb, 0) < 0)
            return -3;
        initTimer();
        emit exceptionSignal(0); // Успешная инициализация
        return 0;
    }

Как и в случае с CDC, запускаем таймер. Каждый тик (100 мс) проверяем значение интерфейса и, если первый байт 0xA0, выставляем сигнал, что данные готовы. Далее этот сигнал можно обрабатывать UI-интерфейсом. В связи с тем, что данные приходят сразу в готовом виде, я использую две переменные для хранения результата.

        if (databuff[0] == 0xA0 && actual == 15)
        {
            int value = 0;
            int afterPoint = 0;
            uint8_t dpos = databuff[7];  // десятичная точка
            uint8_t mult = databuff[10]; // Множитель
            uint8_t unit = databuff[11]; // Единица измерения
            // преобразование в число
            for (int i = 0; i < 4; i++)
            {
                afterPoint = afterPoint * 10 + (databuff[i + 2] - 0x30);
                if (dpos & 1 << (4 - i))
                {
                    value = afterPoint;
                    afterPoint = 0;
                }
            }
            if (databuff[1] == 0x2D)
                value *= -1;
            emit messageAvailable(value, afterPoint, getMultiplierString(mult), getUnitString(unit));

Для «связывания» интерфейса пользователя и подпрограммы обработки данных приборов используем setContextProperty.

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

   Connections {
            target: hantekDevice
            onMessageAvailable:{
                valueDisplay.text = value+"."+afterPoint;
                dimensionLabel.text = mult + unit;
                if(modeSelector.sIndex>8){
                    if (acdcSwitch.checked)
                    {dimensionLabel.text += " AC";}
                    else {dimensionLabel.text += " DC";}
                }
            }
        }

QML-скевоморфизм

Пообщавшись со знакомыми разработчиками, мы создали публичный репозиторий с элементами QML. Актуальную версию селектора можно скачать оттуда.

Для реализации привычного интерфейса мультиметра решил сделать собственный элемент — селектор режимов. Он состоит из окружности, вокруг которой расположены части дуги с цветовыми метками режимов и названия каждого возможного режима работы.

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 9

Физическое и программное воплощение одного устройства.

Из интересного — добавил обратную связь через QtFeedback. Примеры применения можно найти в документации Ubuntu Phone. В целом, применение очень простое: создаете компонент и по необходимости его вызываете. Под капотом данный элемент передает необходимый запрос через DBus интерфейсу com.nokia.NonGraphicFeedback. Следующий пример по нажатию кнопки вызывает вибрацию на 100 мс:

import QtQuick 2.0
import Sailfish.Silica 1.0
import QtFeedback 5.0
Page {
   objectName: "mainPage"
   allowedOrientations: Orientation.Portrait
   // HapticsEffect для вибрации
   HapticsEffect {
       id: rumbleEffect
       duration: 100
   }
   Button {
       text: "DRILL!!!"
       width: parent.width
       height: parent.height
       onClicked: rumbleEffect.start();  // plays a rumble effect
   }
}

Интересный нюанс: если выключена вибрация клавиатуры, то и здесь она не сработает.

Для отображения графика на планшете в этот раз использовал ChartJs2QML из примеров ОМП. Этот вариант удобнее в плане интерфейса для разработки, но отображаются артефакты при обновлении графиков. Чтобы интерфейс с графиком отображался только на планшетах, создал новую qml-страницу и прописал условие вызова в главном файле:

initialPage: getWidthBasedPage() 
…
    function getWidthBasedPage() {
        if (Screen.width > 720) {return Qt.resolvedUrl("pages/TabletMainPage.qml");
        } else { // Для маленьких экранов
            return Qt.resolvedUrl("pages/MainPage.qml");
        }

Автоматизация

Инсайдерская информация! Компания ОМП готовит значительное обновление системы. В частности — компонентов управления USB-устройствами и доступам к ним. В скором времени при разработке ПО пропадет необходимость подключать статическую библиотеку libusb и прописывать ручками права на устройство в консоли. Вместо этого, начиная с Аврора ОС 5.2, появится возможность запросить разрешения на интерфейс в ОС после соответствующей настройки в проекте.

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

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 10

Эту проблему решил пересборкой библиотек статически. Чтобы не пересобирать их каждый раз, сделал пайплайн, который автоматически собирает libusb. В общем виде пайплайн скачивает исходный код библиотеки, конфигурирует проект с указанием «собирать статические библиотеки» и выполняет сборку проекта для каждой необходимой архитектуры. Все архитектуры прописаны в «матрице», переменной arch:

jobs:
 build:
   name: Сборка библиотеки
   runs-on: psdk
   strategy:
     matrix:
       arch: [aarch64, armv7hl]
   steps:
  …
   - name: Сборка для каждой архитектуры
     run: |
       cd libusb
       ${{ env.psdkPath }}/sdk-chroot sb2 -R -t ${{ env.aurora_tag }}-${{ matrix.arch }}.default make
…

Собранный пакет автоматически пушится на следующем этапе в общий публичный репозиторий пакетов и доступен всем по ссылке. При дальнейшей сборке достаточно выбрать нужную библиотеку, стянуть архив и распаковать решение для целевой архитектуры приложения.

Самодельная мобильная лаборатория из старого мультиметра и подручного телефона - 11

Заключение


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

Автор: VRyabchevsky

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js