Интеграция полевых устройств в системы автоматизации производств (Язык описания электронных устройств EDDL)

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!


Рис. с сайта FIELDCOMM GROUP https://www.fieldcommgroup.org/


Интеграция полевых устройств в системы автоматизации производств (Язык описания электронных устройств EDDL)


Хотя до этого я писал только про встроенное ПО, сегодня речь пойдет немного о другом. Я хочу рассказать о языке Electronic Device Description Language (EDDL) и его применении. Общаясь с разработчиками полевых устройств, я выяснил, что в РФ не так много специалистов в этом сегменте, слышал даже такое мнение, что в России всего 3 разработчика на этом языке, и одного из них я знаю лично.


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


Введение


Несмотря на то, что мы живем в цифровом мире, большую долю в промышленной автоматизации занимает старая-надежная аналоговая петля 4-20 mA. Да, промышленный Ethernet продолжает расти (вот тут: Промышленные сети (мировой_рынок)) приводятся данные, что в 2021 году 65% вновь установленных узлов промышленной автоматизации приходится на Ethernet. Но, получается, что 35% новых автоматизаций приходится на старые добрые FF, PB и HART с токовой петлей. А учитывая тот факт, что до недавнего времени токовая петля полностью доминировала на рынке и никто в ближайшем будущем с неё спрыгивать не собирается, то я бы сказал, что доля токовой петли в автоматизации огромна.


Такие сети по-прежнему находят применение в 2023 году. Полевая шина HART и 4-20 мА еще долго будут существовать в промышленных сетях. Так, например, в системах Противоаварийной Автоматической Защиты (ПАЗ) в России можно использовать только токовую петлю и никаких тебе много-точечных подключений. Возможно скоро лед тронется, но пока так.


Так вот, поскольку токовая петля была уже давно, а цифровой век начался неожиданно быстро, то где-то в 80-90х годах люди стали думать, как используя токовую петлю, можно передавать цифровую информацию. И тогда был придуман HART, очень простой, но вполне себе надежный цифровой протокол, накладывающийся на токовый сигнал.


HART медленный, но основная его задача — позволить настроить устройство невылазя из своего кресла, попивая лате.


Хотелось бы заметить, что в высокоскоростных цифровых решениях (Ethernet, например или беспроводка) могут использоваться такие технологии как HART-IP.


Ну дак вот, в какой-то момент, производители оборудования наделали столько устройств с HART (и не только с HART, но и с FF, PF, Profinet и так далее), что интегрировать их в обычную систему становилось просто невыносимо трудоёмко.


И в этот момент инженеры из, по-моему, компании Fisher-Rosemount(могу ошибаться) придумали EDDL (Язык описания электронных устройств) и систему управления полевыми устройствами. Патент за номером DE69726763T2. Про это и хочу сейчас немного рассказать.


Что такое EDDL


Итак, устройств становилось много и каждое устройство нужно было индивидуально настраивать, причём, алгоритмы настройки могли быть совершенно нетривиальными.


К примеру, простая калибровка токовой петли, должна производится в определённой последовательности, вначале установка нуля, а потом уже наклона. И если её нарушить, то можно получить совсем те то, что вы ожидали.


Инженеры ленивы по жизни, немного подумав, они решили, а зачем писать множество драйверов одного датчика для каждой хост системы, когда можно написать один драйвер для устройства, а все системы пусть его используют. Но для этого нужен был единый стандарт и какое-то единое описание устройств. Собственно, поэтому и был разработан язык EDDL, в котором можно было описать логику работы устройства.


Инженеры предполагали, что создание описания с помощью EDDL потребует меньше усилий, чем написание целого программного средства. В википедии про это вкратце написано: Википедия


И поначалу все так и было, и дело дошло даже до стандартизации. Для этого языка есть стандарт EDDL-IEC 61804 и ISA104.


Был создан HART Communication Foundation, в который вошли несколько отечественных компаний, в дальнейшем переименованный в Field Communcation Group (FCG). Этот FCG и стал ответственным за поддержку стандарта языка в актуальном виде.


Чтобы не томить вас, ниже показан пример кода с описанием переменных и методов на таком языке(взято из открытых источников 130 страница TS62769-2 :


Пример кода на языке EDDL
VARIABLE device_var1
{
    LABEL "device var1";
    HELP "";
    CLASS DEVICE;
    HANDLING READ & WRITE;
    CONSTANT_UNIT "constUnit";
    TYPE INTEGER;
    PRE_EDIT_ACTIONS
    {
        PreEditAction1
    }
    POST_EDIT_ACTIONS
    {
        PostEditAction1
    }
}

VARIABLE process_value
{
    LABEL "Level";
    HELP "";
    CLASS DYNAMIC;
    HANDLING READ;
    CONSTANT_UNIT "m";
    TYPE FLOAT;
}

VARIABLE newI
{
    LABEL "new i";
    HELP "new value of i";
    CLASS DEVICE;
    HANDLING READ & WRITE;
    TYPE INTEGER;
}

VARIABLE newJ
{
    LABEL "new j";
    HELP "new value of j";
    CLASS DEVICE;
    HANDLING READ & WRITE;
    TYPE INTEGER;
}

METHOD UIReqRespCategories
{
    LABEL "Request Response Categories";
    HELP "This method demonstrates different categories of messages that are passed
    between server and client during a method execution";
    DEFINITION
    {
        int i, j, k, selection;
        add_abort_method(AbortMethod);
        //Acknowledgement
        ACKNOWLEDGE("Please hit OK to acknowledge the start of this method");

        i = 5;
        PUT_MESSAGE("i = %{i}"); //Info 
        j = 10;
        PUT_MESSAGE("j = %{j}"); //Info 
        k = i+j;
        DELAY(5, "k = %{k}"); //Delay 
        GET_DEV_VAR_VALUE("Enter new value for the %[L]%[U]{device_var1}%[U]",device_var1); //Input 
        selection = SELECT_FROM_LIST("Is the value entered, correct? ", "YES;NO");
        //selection 
        if (selection == 1)
        {
            device_var1 = 0;
            abort(); //abort --- this will trigger the AbortMethod as well; 
        }
        k = k + device_var1;
        if (k == i + j)
        {
            display_comm_status(2);//Error – 2 == "Buffer Overflow" -- HART;           
        }
        display("Current level is %{process_value}%[U]{process_value}!");
        MenuDisplay(MethodMenu,"APPLY;DISCARD",selection); //UIDMessage 
        if(selection == 0)
        {
            i = newI;
            j = newJ;
            ACKNOWLEDGE("new value of k = %{k}"); 
        }
        ACKNOWLEDGE("This concludes the method !!"); 
    }
}

METHOD AbortMethod
{
    LABEL "AbortMethod";    
    HELP "This is a simple Abort Method";
    DEFINITION
    {
        ACKNOWLEDGE("Method was aborted due to a call to abort()"); 
    }
}

METHOD PreEditAction1
{
    LABEL "Action1";
    HELP "This is a simple Pre Edit Warning";
    DEFINITION
    {
         ACKNOWLEDGE("Do you really want to edit this variable"); 
    }
}

METHOD PostEditAction1
{
    LABEL "Action2";
    HELP "This is a simple Post Edit Message";
    DEFINITION
    {
        ACKNOWLEDGE("You actually edited the variable now!!!"); 
    }
}

MENU FDIActions
{
    LABEL "FDI Actions";
    HELP "This menu contains methods for verifying FDI UID contents";
    ITEMS
   {
        MethodMenu,
        UIReqRespCategories
   }
}

Но обо всём по порядку.


Начало


Если вы представляете время, когда всё это начало задумываться, то это была эпоха зарождения интернета — html странички и все такое.


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


Идея аля web странички 90х. Примерно так инженеры представляли себе систему работающую с EDD.



Это должно было упростить работу для интеграторов полевых устройств. Производитель, разрабатывает устройство, создает к нему EDD, интегратор встраивает устройство в систему, скармливает EDD хост системе, которая умеет интерпретировать EDD и получает полное господство над управлением устройством, наслаждаясь красивыми картинками.



Хосты могли отличаться друг от друга, но в целом, они выдавали примерно одно и тоже для пользователя:



EDDL был эдаким языком разметки и описания данных, а для сложных алгоритмов или последовательности работы с устройством и, вообще, для организации специальной логики работы, использовался скрипт. Т.е. все как сейчас в web — html + css + JavaScrtipt или TypeScript только для промышленности.


Проблема была в том, что, во-первых, тогда все эти html были ещё в зачаточном состоянии, а во-вторых, нужно было это дело умещать в древних устройствах, типа HART коммуникатора HC-275 на 16 битной мотороле MC68, а вы помните что язык транслируемый.
Поэтому, в качестве скриптового языка, был выбран… Си (стильно, модно, молодёжно). Собственно тело метода можно было наблюдать в самом первом примере, но на всякий случай еще раз покажу его здесь:


DEFINITION
{
    int i, j, k, selection;
    add_abort_method(AbortMethod);
    //Acknowledgement
    ACKNOWLEDGE("Please hit OK to acknowledge the start of this method");

    i = 5;
    PUT_MESSAGE("i = %{i}"); //Info 
    j = 10;
    PUT_MESSAGE("j = %{j}"); //Info 
    k = i+j;
    DELAY(5, "k = %{k}"); //Delay 
    GET_DEV_VAR_VALUE("Enter new value for the %[L]%[U]{device_var1}%[U]",device_var1); 
    //Input 
    selection = SELECT_FROM_LIST("Is the value entered, correct? ", "YES;NO");
    //selection 
    if (selection == 1)
    {
        device_var1 = 0;
        abort(); //abort --- this will trigger the AbortMethod as well; 
    }
    k = k + device_var1;
    if (k == i + j)
    {
        display_comm_status(2);//Error – 2 == "Buffer Overflow" -- HART;           
     }
....

Не ищите смысла в этом коде, это просто метод для показа возможности языка.


Получился такой гибрид, язык описания разметки и данных EDD + скриптовый язык на Си, не ну а что.


В итоге, концепция для интеграции в систему сводится к следующим шагам:



Обработка происходит как во взрослых языках:


  • Код пишется в любом текстовом редакторе (конечно сейчас уже можно купить редактор с подсветкой синтаксиса, но в те времена всё было очень аскетично, только hardcode только блокнот)
  • Отдельная утилита, именуемая токенайзер, проверяла синтаксис языка и конвертировала все конструкции языка в специальные сущности, называемые токены, а также формировала двоичный файл, содержащие эти токены.
    Надо сказать, что изначально предполагалось, что файлы должны были передаваться по медленному протоколу от устройства, а также, что формат должен быть кросс-платформенным, поэтому была сделана попытка описать эти структуры данных в нотации ASN.1. Но в итоге что-то не срослось и получился собственный формат. Токенайзер также проверяет синтаксис языка, правда не всегда хорошо, а методы так вообще почти не проверяются. Собственно поэтому, мы можем уронить хост систему, а некоторые хост системы так и вообще имели дыры в безопасности Касперский сообщает.
  • Двоичный файл отдается хост системе, где он парсится во внутренние конструкции и происходит интерпретация как этих конструкций, так и методов.
  • Точно также интерпретируются и конструкции пользовательского интерфейса, на основании которых строится динамический интерфейс пользователя.
  • В конце концов пользователю предоставляется конечный результат работы всего этого дела в виде дружелюбного и унифицированного интерфейса.

Кстати, двоичные файлы EDD (*.fm8), которые можно скачать тут Зарегистрированные DD, хранят текст метода как есть в иcходном Си коде.



Ребята с Fisher-Rosemount смогли запихать обработку и трансляцию этого языка в портативный HART коммуникатор HC-275 с ЖКИ. Для своего времени это был прорывной продукт, 16 битный микроконтроллер моторолла, специально разработанный портативный модуль памяти Fisher-Rosemount data pack 100 и инновационная сменная батарея. Эдакий IPhone в мире автоматизации.


Казалось, что все работает хорошо, но как это бывает, базовых конструкций стало не хватать.


Язык


Итак, изначально язык имел небольшой набор простых конструкций. На всякий случай, сейчас в языке порядка 30 конструкций, например, Переменные, Массивы, Меню, Списки, Коллекции, Графики, Команды и так далее.


Описание переменных выглядит следующим образом:


VARIABLE LevelUnits
{
    LABEL “Level Units”;
    TYPE ENUMERATED
    {
        1, “meters”;
        2, “Inches”;
    }
    VALIDITY TRUE;
}

У пользователя такая переменная будет отображаться следующим образом:



В данном случае у переменной есть:


  • Имя — LevelUnits — это то как к ней можно обращаться в самом EDDL языке, в том числе и из скрипта на языке Си.
  • Метка — Level Units — это то, как она отображается на экране у пользователя.
  • Тип — Это её тип. Типов не так много, FLOAT, ASCII, INTEGER(разной длины) и еще штук 10, в данном случае это перечисляемый тип.
  • Валидность — означает, что данная переменная валидна

Но это урезанное описание, потому как в последней спецификации переменная содержит уже более 20 полей, например, есть такие поля как HELP, PRE и POST_EDIT_ACTIONS и так далее.


Заметили что у переменной есть атрибут VALIDITY — валидность? Так вот устройств было много и у каждого были свои особенности, например, некий производитель мог выпустить Уровне-Расходомер. Бред, но так бывает, в один момент времени он может измерять что-то одно либо расход, либо уровень. И переменная расход может быть не валидна когда устройство работает как уровнемер, и наоборот. Хост должен об этом как то узнать, чтобы показывать пользователю только валидную переменную.


И тогда в язык добавили conditions-условия и выглядит это так:


VARIABLE LevelUnits
{
    LABEL “Level Units”;
    TYPE ENUMERATED
    {
        1, “meters”;
        2, “Inches”;
    }
    VALIDITY
    {
        IF (DeviceType == LEVEL)
            TRUE;
        ELSE
            FALSE;
    }
}

Язык разметки и описания данных EDDL начинает содержать логику. Таким образом, хост система должна интерпретировать не только Си методы, но еще и сам EDDL и всё это должно быть связано, потому что из методов на Си можно обращаться к переменным, которые описаны на другом языке, да еще и содержат логику. Теперь каждый раз при обращении к любому атрибуту переменной, например, того же LABEL, необходимо, чтобы движок пересчитывал её значение.


Появились и более странные вещи, например, есть такая конструкция Reference Array, которая может содержать ссылки на разные другие сущности. Из скрипта на языке Си обращение к Reference Array происходит так же как к обычному массиву через оператор [] — ведь это Си.


Так вот, элементы этого массива могут ссылаться на сущности разных типов. Но даже один элемент может запросто меняться и при определенных условиях, начинать ссылаться на сущность другого типа. Т.е. вначале ссылка была на переменную типа float, а затем может стать ссылкой на тип int, или вообще какую-нибудь коллекцию, например единиц измерения. Такое возможно потому, что все ссылки в языке EDDL это просто целочиcленные идентификаторы переменных (каждая переменная получает свой идентификатор во время работы токенайзера).


А еще замечательнее то, что индекс и количество элементов reference массива может также меняться прямо на лету, в зависимости от неких условий.


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


ARRAY ExpressionParserTest0
{
    LABEL "Test Expression Parser";
    HELP  "REFERENCE_ARRAY with conditions to test Expression Parser";
    ELEMENTS 
    {
       1, var_float;
       2, var_int;
     }      

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


В нём тип и количество элементов массива может меняться на ходу. Некоторые элементы массива могут просто отсутствовать при определённых условиях. И мы запросто можем получить массив с дырками, когда будет существовать элемент массива 1, 2 и 4, а элемент номер 3 будет отсутствовать — такой массив Шредингера, никогда не знаешь, что он такое, пока не обратишься к его элементу. Что за "идиотская" структура подумал бы обычный программист, но только не программист на EDDL языке.


ARRAY ExpressionParserTest0
{
    LABEL "Test Expression Parser";
    HELP  "REFERENCE_ARRAY with conditions to test Expression Parser";
    ELEMENTS 
    {
        IF((var_uint + var_float) * 3 - 50 > 0)
        {
            1, var_float;
        }

        IF(var_uint + var_float * 3 - 50 > 0)
        {
            2, var_float;
        }

        IF((var_int_1 == 1) > (var_int_2 != 2))
        {
            3, var_float;
        } 

        IF(var_int_1 == (1 > var_int_2) != 2)
        {
             4, var_float;
        } 
        ELSE
        {
             4, var_int 
        }       

        IF( 1 << 3* var_int + 1 - 5 / 7)
        {
            5, var_float;
        }       

        IF( (var_int == 1 && var_uint == 2) || var_float + 3 < 4)
        {
            6, var_float;
        }       

        IF( var_int == 1 && (var_uint == 2 || var_float + 3 < 4) && 2*(var_int_3 - 4) > 3)
        {
            7, var_float;
        }       

        IF((var_int & 1 << var_uint + 3 || var_int_1 & 27 >> var_float * 2 - 4) && var_int_2 >> 1 + 2)
        {
            8, var_float;
        }

        IF(listOf_var_int.COUNT > 8 && listOf_var_int.FIRST == 4 && listOf_var_int.LAST == 7 && listOf_var_int.CAPACITY > 10)
        {
            9, var_float;
        }

        IF(var_int.DEFAULT_VALUE > 4)
        {
            10, var_float;
        }

        IF(/*Axis1.VIEW_MIN > 4 &&*/ Axis1.VIEW_MAX > 7) // TODO токенайзер путает VIEW_MIN с LAST
        {
            11, var_float;
        }
    }
}

Представляете боль разработчика транслятора этого языка?


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


Понятно, что ни один хост не смог полностью обработать такие вещи, например, Simatic PDM, который транслирует прямо исходный код EDDL без предварительной обработки токенайзером падает при любой возможности упасть. Многие вещи не поддерживает вообще ни один хост и даже сам токенайзер языка.


Забегая вперёд, стоит сказать, что задача решаема, а некоторые немецкие студенты, по всей видимости на практике в Siemens, даже делали курсовые на предмет того, как можно сделать парсер языка:
PhD student at TU Munich и его заготовка парсера под lex/yacc


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


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


Эволюция


Для того, чтобы было проще построить host систему, FCG сам разработал движок EDDL языка. Поначалу этот движок поставлялся в составе "идеальной" хост системы SDC625 (Для тех у кого есть лишние 75 000$.
Надо сказать, что она не такая уж и идеальная. Многие конструкции она не поддерживает, да и работает только под управлением Windows и падает не реже Simatic PDM.


У SDC625 есть модуль который можно встроить прямо в ваше приложение, и тогда оно сможет поддерживать все HART устройства. Таким путем пошел Элемер, собственно Hart Manager и построен на его базе. Но насколько я понимаю, Элемер, блокирует поддержку сторонних EDD.


Время шло, технологии развивались и FCG выпустил платформа-независимый FDI EDD Engine X Распродажа за пол цены, который умеет парсить бинарные EDD файлы и создает Информационную модель устройства.


Но даже он не поддерживает все конструкции языка и может падать на фишках, типа причуд с Reference array. Кроме того, это не совсем законченный продукт, UI и остальные сервисы (например, коммуникацию) придется допиливать самим.


На основе этого движка FCG создала второй "идеальный" хост RRTE. Он уже конечно намного надежнее, и его действительно можно использовать как reference хост для проверки своих EDD.


Этот движок также используется в приложениях типа этого: Android приложение за 900$


FCG фонд пошел дальше и разработал технологию интеграции устройств FDI (Field Device Integration). Смысл её в том, что, базируясь всё на том же языке описания устройств EDDL, теперь производитель мог дополнительно добавлять в пакет интеграции документы на устройства, дополнять новые фишки пользовательского интерфейса (так называемыми UI Pluggins). Каждый такой пакет подписывается производителем, что исключает загрузку поддельных описаний устройств.



Теперь интеграция полевых устройств меняется кардинально. Всё взаимодействие происходит через открытый интерфейс OPC UA, интерпретация EDDL файлов происходит на FDI Server OPC UA и это открывает огромные возможные в интеграции устройств в существующие системы управления (SCADA).


Архитектура


Общая внутренняя архитектура взаимодействия показана на рисунке, взята отсюда Страница 12 из TS62769-2



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


Можно сюда добавить еще и облако и тогда, сидите дома за чашечкой лате и наблюдаете за процессом в ядерном реакторе (утопия конечно).



Основные компоненты системы:


  • DD OPC Server — ОРС UA сервер, транслирующий описания на EDDL языке, формирует ОРС информационную модель устройства в соответствии со спецификацией Field Device Integration (FDI).
  • DD Storage — Хранилище бинарных DD файлов.
  • HART OPC Сервер — ОРС UA Сервер реализующий профайл HART протокола в соответствии со спецификацией Field Device Integration (FDI)
  • SCADA — Любая SCADA система, поддерживающая OPC UA для мониторинга данных с HART датчиков
  • DD ОРС клиент — ОРС UA клиент, содержащий движок пользовательского интерфейса, в том числе механизм запуска методов в соответствии со спецификацией Field Device Integration (FDI).
  • OPC клиент — любой OPC UA клиент.
  • HART модем — Любой HART модем поддерживающий виртуальный COM порт.
  • Полевое устройство — любое HART полевое устройство, для которого производитель разработал DD описание.

На данный момент существует несколько зарубежных хост-систем с поддержкой EDDL:


  • Siemens – Simatic PDM
  • Emerson — AMS Device Manager,
  • Honeywell — Field Device Manager,
  • Yokogawa — Plant Resource Manager,
  • Automation Solution Rockwell — FactoryTalk AssetCentre,

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


Об этом я попробую рассказать в другой раз.


Будущее


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


Помимо FDI существует еще одна подобная технология FDT. Её основой являются файлы DTM Хорошее общее описание от Yokogawa для чего оно нужно. Существуют также средства перевода EDD в DTM. И если, вам понравится эта статья, я могу написать о том, что такое FDT и DTM.


В заключение хотелось бы сказать, что уже сейчас ведутся работы по объединению технологии FDI с FDT. FDI 2.0 и FDT 3.0 построены на кросс-платформенной архитектуре, где интеграция строится на открытой технологии OPC UA и это огромный шаг вперед.

Источник: https://habr.com/ru/articles/734874/


Интересные статьи

Интересные статьи

Многие компании оказались отрезаны от ключевых зарубежных инструментов. Это коснулось и стека, который red_mad_robot использует для решения задач, поставленных перед продуктовыми аналитиками...
Олимпиада — это не просто соревнования. Это главное спортивное событие мира, неизменно привлекающее многомиллионную аудиторию. Трансляция Олимпиады — крайне сложный технический процесс, в который вовл...
В один момент мы задумались с товарищем, а почему бы не попробовать сделать свое домашнее IoT-устройство? Недолго думая, мы остановились на концепции устройства, которое ...
Если, работая в Linux, нужно быстро взглянуть на сведения о работающих процессах — можно воспользоваться командой top, или — что немного лучше — командой htop. А как быть, если надо получ...
Яркость дисплеев обычно регулируют с помощью ШИМ-сигнала. Технология простая и дешевая, но вызывает мерцание экрана, что сказывается на здоровье глаз. Расскажем, какие есть альтернативы, как они ...