Модернизация лабораторного оборудования с использованием возможностей IoT с помощью генеративного ИИ

Ari Mahpour
|  Создано: 4 Апреля, 2024  |  Обновлено: 1 Июля, 2024
Модернизация лабораторного оборудования с использованием возможностей IoT с помощью генеративного ИИ

В статье Модернизация вашего старого блока питания для управления смартфоном мы вдохнули новую жизнь в старый блок питания, добавив ему возможности IoT. В этой статье мы рассмотрим более упрощенный способ добавления возможностей IoT ко всем вашим лабораторным приборам (в частности, к тем, которые управляются с использованием VISA). Вместо того чтобы создавать все с нуля, мы будем использовать генеративный ИИ для выполнения большей части работы. Пройдя этот учебник, вы сможете применить эти концепции для создания веб-драйверов для всех ваших лабораторных приборов и также ускорить общую разработку.

Базовые принципы

В этой статье мы сосредоточимся на создании веб-сервиса, который служит посредником между самим прибором и Интернетом. Ниже приведена иллюстрация связи от прибора к интернету (т.е. доступ через веб-сайт).

Блок-схема

Рисунок 1: Связь от прибора к Интернету

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

Я использую блок питания DP832 и электронную нагрузку DL3021 от Rigol. После быстрого поиска на GitHub я нашел библиотеки Python для блока питания DP832, которые содержат все необходимые команды SCPI для начала работы. Альтернативный подход заключался бы в том, чтобы взять список команд SCPI из руководства DP832, передать его крупной языковой модели (LLM), например, ChatGPT или Gemini, и попросить ее сгенерировать функции для меня. Я немного придирчив, поэтому я собираюсь определить свой собственный процесс настройки PyVISA (заключенный в отдельный класс): 

class CommBase:

   USBConnType = Literal["USBTMC", "VISA", "Socket"]

    def __init__(self, usb_conn_type: USBConnType, vid: int = None, pid: int = None, visa_resource_prefix: str = None):

        self.visa_resource_prefix = visa_resource_prefix

        self.usb_conn_type = usb_conn_type

        if usb_conn_type == "USBTMC":

            self.configure_usbtmc(vid, pid)

        elif usb_conn_type == "VISA":

            self.configure_visa(vid, pid)

        elif usb_conn_type == "Socket":

            pass

        else:

            raise ValueError(f"Неверный тип USB соединения: {usb_conn_type}. Допустимые типы: {self.VALID_USB_CONN_TYPES}")

 

    def configure_usbtmc(self, vid: int, pid: int):

        self.inst = usbtmc.Instrument(vid, pid)

 

    def configure_visa(self, vid: int, pid: int):

        self.rm = pyvisa.ResourceManager()

        instrument_list = self.rm.list_resources()

        visa_address = self.find_visa_resource(vid, pid, instrument_list, prefix=self.visa_resource_prefix)

        if visa_address is not None:

            self.inst = self.rm.open_resource(visa_address, read_termination="\n")

        else:

            raise IOError(f'Не найдены VISA устройства с vid "{vid}" и pid "{pid}", однако были найдены следующие VISA устройства: {instrument_list}')

 

    @staticmethod

    def find_visa_resource(vid: int, pid: int, resource_strings: list, prefix: str) -> str:

        hex_vid, hex_pid = f"0x{vid:X}", f"0x{pid:X}"

        dec_vid, dec_pid = str(vid), str(pid)

        for resource in resource_strings:

            parts = resource.split("::")

            if len(parts) >= 4:

                serial_and_more = parts[3]

                if (any(x in resource for x in (hex_vid, dec_vid)) and any(x in resource for x in (hex_pid, dec_pid)) and serial_and_more.startswith(prefix)):

                    return resource

        return None

 

    def query_device(self, command: str) -> str:

        if self.usb_conn_type == "USBTMC":

            return self.inst.ask(command)

        elif self.usb_conn_type == "VISA":

            return self.inst.query(command)

        else:

            raise NotImplementedError(f"Метод запроса для {self.usb_conn_type} не найден.")

 

    def write_device(self, command: str):

        self.inst.write(command)

 

    def close(self):

        self.inst.close()

        if self.usb_conn_type == "VISA":

            self.rm.close()

 

    def id(self) -> dict:

        id_str = self.query_device("*IDN?").strip().split(",")

        return {

            "manufacturer": id_str[0],

            "model": id_str[1],

            "serial_number": id_str[2],

            "version": id_str[3],

        }

Я удалил все комментарии, лишние пробелы и даже некоторые последовательности настройки (например, логирование) для краткости. Как видите, у меня есть некоторые общие функции плюс поддержка как PyVISA, так и USBTMC. Большинство библиотек Python на основе SCPI, которые вы найдете в сети, не будут иметь эту базовую функциональность. Это нормально, потому что я могу расширить этот класс в мой новый класс:

from base.CommBase import CommBase

class DP(CommBase):

    def channel_check(self, channel):

        assert NotImplementedError

    def get_output_mode(self, channel: int) -> str:

        self.channel_check(channel)

        return self.query_device(f":OUTP:MODE? CH{channel}").strip()

    # … Код был удален для краткости

    def measure_current(self, channel):

        self.channel_check(channel)

        meas = self.query_device(f":MEAS:CURR? CH{channel}").strip()

        return float(meas)

    def measure_voltage(self, channel):

        self.channel_check(channel)

        meas = self.query_device(f":MEAS? CH{channel}").strip()

        return float(meas)

    def measure_all(self, channel):

        self.channel_check(channel)

        meas = self.query_device(f":MEAS:ALL? CH{channel}").strip().split(",")

        return {

            "voltage": float(meas[0]),

            "current": float(meas[1]),

```html

            "мощность": float(meas[2]),

        }

 

class DP712(DP):

    def channel_check(self, канал):

        assert канал in [1, ""], f"Выходной канал {канал} не поддерживается"

 

class DP821(DP):

    def channel_check(self, канал):

        assert канал in [1, 2, ""], f"Выходной канал {канал} не поддерживается"

 

class DP832(DP):

    def channel_check(self, канал):

        assert канал in [1, 2, 3, ""], f"Выходной канал {канал} не поддерживается"

Я взял несколько разных примеров в интернете и передал их в ChatGPT. Я попросил его:

  1. Преобразовать файл в класс
  2. Добавить блоки комментариев в стиле docstring для каждой функции
  3. Написать тесты для проверки этих функций (в виде отдельного класса)

Использование генеративного ИИ для этой задачи сократило многочасовую работу до 60 секунд. Также я очень быстро смог проверить драйверы, найденные в интернете, запустив автоматически сгенерированные тесты, которые написал для меня ChatGPT. Например, я очень быстро обнаружил, что одна из команд SCPI для DL3021 для установки режима работы электронной нагрузки была на самом деле неверной. Наблюдая за тестами в реальном времени, я заметил, что режим на моем приборе не меняется. Быстрый поиск в руководстве SCPI, и я смог это исправить.

Веб-сервис

На этом этапе у нас есть хорошая основа для нашей библиотеки Python для управления нашими приборами. Теперь цель - разместить веб-сервис перед библиотекой приборов, давая нам возможность управлять ими через веб. Предполагая, что я ничего не знаю о веб-фреймворках, я могу просто попросить ChatGPT (или любой LLM) выполнить всю функцию за меня. Вот запрос, который я использовал для начала:

Мне нужно создать веб-сервис, который будет управлять моим прибором с использованием базовых URL (через веб-браузер). Я не знаю много о веб-сервисах или фреймворках, но я знаком с Python. Напишите полный код Python для выполнения этой задачи.

Вот класс, который управляет моим прибором:

<pre><code>```

{код сверху}

```

</code></pre>

И (частичный ответ):

```

Ответ ChatGPT на запрос

Рисунок 2: Ответ на запрос ChatGPT

Моя любимая часть в использовании продвинутых (платных) LLM заключается в том, что они действительно разбивают задачу на части, обучают тебя и предоставляют довольно хорошее решение в качестве первой итерации. В Gemini против ChatGPT: Кто пишет лучший код? я сравнил две LLM между собой и (спойлер) обнаружил, что последняя, наиболее продвинутая версия Gemini от Google была действительно неплоха (если не наравне с ChatGPT 4). Использование любой из этих LLM даст результат, подобный показанному выше.

Если я хочу поместить это в класс или переформатировать, я могу просто ответить в чате и сделать свой запрос. Хотите, чтобы ваш код был прокомментирован? Нет проблемы, просто спросите!

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

Запрос ChatGPT

Рисунок 3: Следующий ответ на запрос ChatGPT

Тестирование

Теперь, когда мы попросили Generative AI создать модуль Python, мы можем либо попросить его написать для нас тесты, либо показать, как тестировать вручную:

Тестовый URL

Рисунок 4: Ручной тестовый URL от ChatGPT

Автоматизированный тест

 Рисунок 5: Автоматизированный тест, написанный ChatGPT

После запуска (или корректировки, а затем запуска) этих тестов мы должны быть в состоянии проверить наш новый модуль Python, который взаимодействует между вебом и нашим прибором. 

Заключение

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

Весь исходный код, использованный в этом проекте, можно найти по адресу: https://gitlab.com/ai-examples/instrument-controllables.

Об авторе

Об авторе

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

Связанные ресурсы

Связанная техническая документация

Вернуться на главную
Thank you, you are now subscribed to updates.