tgindex
Довкола автоматики

Довкола автоматики

Статистика
@pupenasanукраинский

Канал про промислову автоматизацію і не тільки (від pupena_san)

Последний пост
13 авг.
Последнее чтение
14 авг.
Постов за неделю
2
Всего постов
21
Тип
открытый
Язык
украинский
В каталоге с
12 авг.
Подписчики
262
+1 за 2 дн.
Сутки
0
0,00%
Неделя
 
Месяц
 
Просмотров на пост
234
21 постов
Вовлечённость
89,3%
к подписчикам
Постов в день
0,3
всего 21
Упоминаний
1
каналов
Охват размещения
оценка
1/24сутки в ленте
243
1/48двое суток
278
1/72трое суток
300

Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.

Посты

  • Сьогодні у 2-й частині 30-го випуску "Довкола автоматики" ми з Єгором завершили обговорення теми "Використання ШІ-агентів у професійній діяльності". Нарешті я отримав відповіді на ті питання, які мене цікавили. Принаймні на сьогодні. Дуже дякую Єгору Смолякову за цікаву та продуктивну розмову! https://youtu.be/F-ukAXYPtmA?si=xm18_IjnkvAAdGSt

  • 12 авг.3051311

    Після тривалої паузи вчора нарешті вдалося записати подкаст "Довкола автоматики" з Єгором Смоляковим про використання ШІ-агентів. Вийшло доволі сумбурно, бо наші з Єгором компетенції в цій темі на відчутно різних рівнях. Я постійно намагаюся його зупиняти, щоб він пояснив те, що для нього вже здається очевидним. Але пояснювати доводиться стільки всього, що, по-хорошому, перебивати його треба було б після кожного речення. Я хоч і зловживаю цим, але явно недостатньо, щоб усе стало зрозуміло. Тому розганялися довго. Хоча навіть після розмови я для себе багато чого ще не прояснив. А найцікавіше, як на мене, почалося вже ближче до кінця. Зрештою вирішили, що продовжимо у другій частині. Сподіваюся, запишемо її ще цього тижня. Перша частина: https://youtu.be/Kot2-k7j5o0

  • У продовження сьогоднішнього ранішнього поста. Є нюанси, але рішення в нас практично однакові. Ось що значить потратити час на навчання ШІ

  • Почав вчити ШІ реалізовувати процедурне керування. Він ніби й навчений загальним правилам, але вони досить теоретичні та розмиті. Тому почали з вводної. Десь година діалогу у форматі "питання - відповідь", причому уточнювальні питання ставив саме він. Чесно кажучи, я прямо відчув грамотного студента по той бік. Питання були такими, що деякі речі доводилося переосмислювати. Мені потрібно, щоб він не просто генерував код, а критично оцінював прийняті рішення, шукав потенційні помилки і, звісно, брав на себе рутинну частину роботи в поточному проєкті. В ідеалі - щоб у майбутніх проєктах він уже приходив із цими знаннями. У проєкті, над яким зараз працюю, процедурне керування потрібне для запуску програм керування потоками у багатомаршрутному виконанні. Для більшості моїх проєктів це не є типовою задачею. Хоча основи ISA-88 я використовую майже всюди, тут дуже доречними виявилися ідеї allocation, розділення ресурсів на shared та exclusive і все, що з цим пов'язано. Востаннє щось подібне робив ще у 2017 році. Але просто "замепити" ISA-88 на цей проєкт не вийшло б. Довелося робити декомпозицію ROUTE → PATH і вже на цій основі формувати концептуальні правила керування та контролю. У процесі діалогу я кілька разів змінював підходи. І щоразу питав: "Добре, а чи не суперечить це тим правилам, які ми вже визначили?" Тут агент хоч інколи й поводився як трохи підлабузливий асистент, але все ж час від часу дискутував. І саме це змушувало ще раз подумати, наскільки вдале те чи інше рішення. Зрештою, усе ще не до кінця перевірено. Але цей пост більше не про результат, а про сам процес взаємного навчання. Викладачі (і не тільки вони) добре знають: коли пояснюєш щось іншому, власні знання теж значно структуруються. Є навіть старий жарт: "Як ви не зрозуміли? Я вже й сам зрозумів!" А коли співрозмовник ще й ставить хороші запитання - це вже взагалі інший рівень. Саме під таким кутом я раніше роботу з ШІ не розглядав. Хоча, як і більшість студентів, його періодично доводиться відправляти до методички. І це трохи дивно на фоні рівня дискусій, бо відправляю до азів. Саме тому поки що досить скептично ставлюся до думки: "Дайте ШІ задачу - і він сам усе зробить." Можливо, на пізніших етапах розвитку агентів так і буде. Може навіть зараз за наявності повного доступу до всіх інструментів це можливо, хоча мені важко представити як це може виглядати на етапі пусконалагодження на об'єкті. Тобто якщо він щось наваяє робоче на моделі, а на етапі налагодження в гарячу правити мені, то ... нє, таке мені не підходить. А поки що над ним доводиться стояти з указкою і час від часу тикати носом у документацію.

  • Давно не писав, бо зараз дуже багато роботи. Хоча насправді є про що розповісти. Спробую згадати найцікавіше, що може вас зацікавити. 1) AI-агенти вже реально економлять час. На днях боровся з однією проблемою в Debian. У цій ОС я не дуже сильний. Порівняно недавно почав активно використовувати Linux, переважно через Raspberry Pi. Тому ШІ тут дуже допомагає. Традиційно почав радитися з класичним ChatGPT. Після години його "балакучих" порад зрештою переключився на exCodex (тепер він теж просто називається ChatGPT). Різниця виявилася разючою: проблему, з якою до цього возилися майже годину, вдалося вирішити приблизно за 20 хвилин. 2) Без AI-агента вже важко уявити щоденну роботу. Він бере на себе багато рутинних задач, добре знаходить помилки, пропонує різні варіанти реалізації. Але всі архітектурні та структурні рішення, як і раніше, залишаються за мною. Час від часу ввожу його в курс справ усіх проєктів, над якими працюю. Тут дуже допомагає викладацький досвід: коли матеріал добре структурований, значно простіше сформулювати завдання. Є ще один цікавий ефект. Іноді агент нагадує мені те, що я вже встиг забути. Він запитує: "А як це зроблено?" А я відповідаю: "Сам подивися і потім мені розкажи." 3) Один великий проєкт усе ще залишається великим проєктом. Зараз веду програмну частину проєкту приблизно на 1500 I/O. Раніше подібні проєкти ми робили втрьох. Якщо оцінювати власні витрати часу, то зараз обсяг роботи приблизно у півтора раза більший, ніж був би, якби команда складалася з трьох людей. Звісно, усе дуже залежить від самого проєкту та команди замовника. На цьому проєкті, наприклад, залучені дуже грамотні технічні спеціалісти, що суттєво спрощує і пришвидшує життєвий цикл розробки. З іншого боку, значну частину часу зараз займає відпрацювання основ нової версії каркасу PFw2. Тому об'єктивно оцінити його ефективність поки що важко. Про кінцеві результати впровадження PFw2 обов'язково напишу після завершення проєкту.

  • Наприкінці грудня 2022 року я проводив вебінар на тему "Автоматизоване керування виробничими операціями". Сьогодні вкотре усвідомив, що багато спеціалістів в Україні навіть не знають про існування програмних продуктів рівня MOM. Тому вирішив ще раз поділитися посиланням на цей вебінар, а також відкрив доступ до практичної частини, де в демонстраційному режимі показую, як працювати з однією з таких систем. Теоретична частина (до речі, в лекції є кілька моїх оговорок 😊. Знайдете - напишіть у коментарях під відео): https://youtu.be/L593ZMPxkRg , практична частина: https://youtu.be/Y2agqEBEND0

  • Сьогодні знову трохи розкажу про будні спільної роботи над проєктом із ШІ-агентом. Наразі він працює як помічник і виконує переважно рутинну роботу. Як я вже писав в одному з попередніх постів, я розробив структуру типового функціонального блоку PLC для одного з механізмів. Попрацював із агентом як із порадником, щоб відшліфувати структуру, протестував на імітаторі з використанням HMI, а тепер прошу за цим шаблоном робити інші блоки. По суті, агент виконує все те, що мені довелося б робити механічно. Тобто генерує код, який, за ідеєю, мав би написати я сам, тільки швидше і без механічних помилок. Що мені дуже подобається - цей код добре мною читається. По суті, це мій власний стиль програмування, просто відтворений агентом. Поки що переношу код у PLC вручну, хоча він уже навчився генерувати PLCopen XML для імпорту (на першій ітерації саме так і завантажувався). Як не дивно, ручне перенесення майже не сповільнює роботу, зате дає змогу ще раз усе переглянути й проконтролювати. Окремо хочу відзначити, наскільки агент допомагає із систематизацією та пошуком помилок. Учора, наприклад, довелося робити другу велику ітерацію оновлення майстерданих. Проєктант не захотів працювати з моїм форматом (і має на це повне право), тому продовжував змінювати свої "майстердані", але не позначав, що саме змінилося. У будь-якому випадку структура там теж була, тому агент досить швидко зробив меппінг між двома форматами. Рік тому я б писав окрему програму, яка приводила б обидва формати до спільного вигляду і порівнювала їх. Зараз цього робити вже не потрібно. ШІ досить добре працює навіть із не повністю структурованими даними. Звісно, без проблем не обійшлося. Десь змінили назви, десь були неправильні позначення, десь просто не збігалися структури. У результаті повної відповідності я так і не отримав і довелося переключитися на іншу задачу. Але в процесі було знайдено багато невідповідностей, на пошук яких вручну пішло б дуже багато часу. Поки що я не довіряю агенту самостійно вносити зміни в майстердані. По-перше, правила роботи з майстерданими PFw2 ще самі перебувають у процесі формування. Важко пояснити іншому те, з чим сам ще експериментуєш. По-друге, я побоююся вартості невдалих спроб. Він працює недостатньо швидко, щоб після автоматичних змін ще все перевіряти і, якщо потрібно, робити відкат. Якщо ж задача ітераційна і добре вкладається в певний шаблон, то використовую інший підхід: один раз разом із ШІ пишу код або тулзу, а потім використовую її стільки разів, скільки потрібно. До речі, складається враження, що й самі агенти працюють приблизно за таким принципом. Принаймні, коли вони "думають уголос", дуже схоже, що постійно намагаються знайти або побудувати відповідний шаблон. Зараз якраз планую навчити агента генерувати XML для об'єктів Plant SCADA. У редакторі це робиться досить довго, хоча сама структура повністю формалізована. Потрібно створювати багато тривог, для кожної формувати текст. На мою думку, саме така інформація і повинна жити в майстерданих. Тому тут, швидше за все, з'явиться ще одна тулза в моєму проєкті Node-RED. Саме цим я і займався сьогодні. Почав формувати записи в майстерданих для тривог. Після кількох годин роботи зрозумів, що не пройшов навіть третини типових тривог відмови каналів (а є ще технологічні тривоги). А якщо врахувати, що типів обладнання вже 46, то перспектива ручного заповнення виглядає не дуже оптимістично. І саме в цей момент я зупинився і подумав: щось, мабуть, я роблю не так. ;-) Якраз на цьому місці і вирішив написати цей пост, щоб трохи відволіктися. P.S. Ще помітив одну цікаву річ: агенти дуже люблять Markdown. Отже не дарма я його студікам вже більше 5 років даю на першому курсі (разом з Node-RED, Git, GitHub і ще багато чого)

  • Я вже написав кілька постів про основи PACFramework та зміни цих основ у PFw2. Хоча, як уже зазначав раніше, PFw2 ще далекий від завершення. Він не буде завершений навіть після реалізації на першому (теперішньому) проєкті, і на це є кілька причин. Тим не менше про те, що вже викристалізовується, я потроху розповідаю, а потім передаю ці матеріали ШІ-агенту, щоб він фіксував їх у своїй базі знань. Мої пости також вичитує редактор ChatGPT, вирізає з нього рок-н-рол, а я потім після нього знову повертаю його назад. Сьогодні хочу розповісти про, мабуть, найважливішу функцію в обох версіях каркасу - PLCFN. Нагадаю, що PACFramework розроблявся як універсальний платформонезалежний набір правил та бібліотек. Перенесення на іншу платформу або інший тип ПЛК мало зводитися до своєрідного "пересипання" проєкту. Це можливо лише за наявності проміжного шару, на якому базуються всі інші бібліотечні функції. Подібний підхід використовується в багатьох програмних середовищах. Навіть операційні системи побудовані за схожим принципом. Саме раннє знайомство з внутрішньою архітектурою Windows (дякую Джефрі Ріхтеру) колись наштовхнуло мене на цю ідею. PLCFN забезпечував (і досі забезпечує) каркас такими ресурсами, як системний час, бітові меандри та імпульси різної тривалості. Саме завдяки цьому в каркасі вдалося практично повністю відмовитися від класичних таймерів та платформозалежних функцій роботи з датою і часом. Ще в "передкаркасний" період (2014–2015 роки) ця функція почала вирішувати й інші задачі. Зокрема, вона збирала статистику по тривогах різних класів. Одним із важливих завдань було виявлення появи нової тривоги для ввімкнення сирени. Це дозволило позбутися постійного головного болю з додаванням нових тривог та написанням довжелезних виразів через OR. Достатньо було просто включити нову тривогу до відповідного класу. Пізніше до цього додалися узагальнені статуси на кшталт: є хоча б одне форсування; є хоча б одна змінна в ручному режимі; є хоча б одне блокування. Згодом ці показники еволюціонували від простого факту наявності до кількісної статистики. Ця ж функція почала відповідати за системні та широкомовні команди. Наприклад, дуже зручною виявилася команда скидання всіх форсувань, коли не потрібно вручну шукати, де ти забув прибрати галочку. З проєкту в проєкт PLCFN та структура PLC_CFG обростали новими можливостями. З'явилися механізми керування змінами, статистика типів каналів та інші допоміжні функції. Зрештою на проєктах із багатозадачністю виявилося, що класична реалізація каркасу до такого сценарію, м'яко кажучи, не дуже готова. Одночасно з'явилася потреба розділяти статистику та тривоги за зонами відповідальності. Ці питання так і залишилися невирішеними в класичному PACFramework, хоча загальні підходи до їх вирішення вже були напрацьовані. PLCFN виявилася настільки вдалою, що я використовував її практично в усіх проєктах, навіть там, де сам PACFramework із тих чи інших причин не застосовувався. Це просто зручно: звичний набір інструментів завжди знаходиться під рукою незалежно від платформи та архітектури проєкту. Однак, як я вже згадував, класичний PLCFN має генетичні обмеження, пов'язані насамперед із багатозадачністю. Саме тому роботу над PFw2 я почав значною мірою з переосмислення цього функціонального блоку. Частину своїх бачень я свого часу виклав у вебінарі, посилання на який залишу в коментарях разом з посиланням на опис класичної версії. Втім в поточному проєкті немає потреби в багатозадачності, і поки не було потреби в зональності, тому велика пауза між тим відео і стартом теперішнього проєкту дала про себе знати - я просто обламався зараз це реалізовувати (як кажуть "не на часі"). Натомість я значно "полегшив" функцію і викинув звідти опціональні речі, які можна спокійно винести в інший функціональний блок. На цьому поки все. Далі буде... П.С. Мій редактор сказав що треба написати "PLCFN — це не просто функція каркасу, а його операційна система". Як на мене гарно, але дуже пафосно. Тому - ніт.

  • Трохи поділюся враженнями про свою нову реальність програмувальника АСКТП з ШІ-агентами. Використовую Codex, поступово навчаю його правилам PFw2 і прошу кодити мені тулзи на Node-RED. Одну таку тулзу ми вже кілька тижнів тому доробили. Вона працює з майстерданими…

  • Трохи поділюся враженнями про свою нову реальність програмувальника АСКТП з ШІ-агентами. Використовую Codex, поступово навчаю його правилам PFw2 і прошу кодити мені тулзи на Node-RED. Одну таку тулзу ми вже кілька тижнів тому доробили. Вона працює з майстерданими в Google Sheets: забирає їх звідти, генерує код для PLC та формує експортний варіант проєктних даних для SCADA. Починав її робити я сам, але потім подумав, що з агентом буде швидше. Намагаюся контролювати структуру програми, благо Node-RED добре цьому сприяє завдяки візуальному представленню. Завжди можна подивитися, що він там наробив, продовжити роботу або щось виправити, якщо токени того, або ШІ трохи заплутався. Ця тулза вже виконує свою роботу, тому ітерації змін у майстерданих мене більше не надто бентежать. Учора почали писати на Node-RED IoT Gateway (налагодження, збір даних, віддалений моніторинг). І тут уже він працює більше, ніж я. Для старту я "вскормлював" йому свій старий пілотний недороблений проєкт. Тепер задаю структуру, пояснюю ідею, а він досить добре справляється з реалізацією. Особливо виручає мене з Web UI, де я відверто почуваюся не дуже впевнено. Для роботи, окрім завдань та правил, які він постійно оновлює за моїми вказівками, я залишаю в проєкті експортний варіант PLC-програми у форматі PLCopen XML. Працювати з ним агент навчився ще тоді, коли генерував код для PLC. Не знаю, чи він уже вмів це робити сам, чи навчився на моїх старих тулзах, але виходить у нього досить добре. Більше того, інколи після аналізу проєкту він сам натякає, що я десь налажав, ще до того, як я прошу його щось доробляти для ПЛК. Думав долучити його і до рисування в SCADA (Plant SCADA/Citect). Але там векторна графіка зберігається у пропрієтарному форматі. Я трохи намагався його "нагодувати" цими файлами, але швидко зрозумів, що пояснювати йому нюанси буде довше, ніж намалювати самому так, як потрібно. Тому поки що графікою займаюся власноруч. Тепер про плани. Хочу сам довести кілька елементів до більш-менш завершеного вигляду, проговорити з агентом їхню структуру та сформувати повноцінні описи. Після цього планую аналогічно описати й інші типи об'єктів. Щоб пришвидшити процес, зараз витягую текстові транскрипти зі своїх відеоконференцій. З них хочу сформувати окремий набір знань для агентів. Шкода лише, що я не записував усі такі обговорення. На основі цих матеріалів, а також даних із майстерданих, планую сформувати базу знань, за якою вже можна буде генерувати функції для програм усіх інших об'єктів. Ціінність ШІ для мене не тільки в тому, що він пише код, а і в тому, що він допомагає масштабувати власний досвід на значно більшу кількість типових задач.

  • Щодо візуалізації з використанням LVL2 все стало набагато простіше ще в класичному PACFramework. Усі HMI змінні обладнання групуються в структури навколо нього, що спрощує візуалізацію. У PFw2 змінився механізм конфігурування, так як буфери перестали бути…

  • Щодо візуалізації з використанням LVL2 все стало набагато простіше ще в класичному PACFramework. Усі HMI змінні обладнання групуються в структури навколо нього, що спрощує візуалізацію. У PFw2 змінився механізм конфігурування, так як буфери перестали бути залоченими (писав вже про це), а LVL2 взяли на себе функції керування форсуванням та конфігурування LVL1, які йому належать. Далі буде...

  • Знову про перехід до PFw2. Сьогодні - про верхній рівень об'єктів керування (CM в ISA-88), LVL2. Його назва з часом змінювалася: спочатку це був рівень виконавчих механізмів, пізніше - рівень пристроїв. Суть залишалася незмінною: агрегувати змінні (LVL1) в один цілісний об'єкт і зосередити в ньому всю логіку керування обладнанням (а ще тривоги, симуляція, відлов змінних-заглушок). Є ще логіка керування процесом, яка реалізується в процедурах, але це тема для окремого поста, а швидше за все навіть для кількох. Об'єкти LVL2 постійно змінювалися як за переліком класів, так і за підходами до реалізації. Нові проєкти вносили суттєві зміни навіть у типові класи, оскільки специфіка електричної обв'язки виявилася настільки різноманітною, що стандартизувати все було вкрай важко. Тому ще до появи ідеї PFw2 на одному з об'єктів я вирішив змінити сам підхід до реалізації. На тому проєкті PACFramework не використовувався (окрім PLCFN, про який розкажу наступного разу), однак основні ідеї були ті самі. Одним із головних нововведень стало створення окремого рушія автомату станів. Він був реалізований як явно виділений пасивний спостерігач із матрицею переходів. Така жорстка архітектурна вимога, коли логіку керування заборонено вбудовувати безпосередньо в логіку автомату, зробила реалізацію набагато чіткішою та прозорішою. Одразу проявилися підступні ситуації, які раніше легко залишалися непоміченими. Наприклад, коли код сам визначає свій поточний стан і тут же сам собі наказує, у який стан потрібно перейти далі. Матриця переходів потенційно дозволяє формалізувати логіку автомату в рамках математичного апарату. Поки що я цим не користувався, але сама можливість мені подобається. До речі, схожий підхід раніше був реалізований у рушії етапів (фаз), але це вже окрема тема. Другим нововведенням, яке я спробував і яке мені сподобалося, стало явне винесення імітатора пристрою за межі основної функції реалізації. При цьому інтерфейс залишився тим самим. У результаті код став читабельнішим, а його структура - логічнішою. У PFw2 я вирішив взагалі не стандартизувати перелік класів LVL2. На мою думку, в цьому немає особливого сенсу. Натомість стандартизуються підходи до взаємодії з LVL1, HMI, буферами та загальні принципи побудови інтерфейсів. Про щось із цього я вже писав раніше, про інше ще напишу. У будь-якому випадку багато функцій, які раніше знаходилися на LVL0 та LVL1, поступово переїхали саме на рівень LVL2. Рушій автомату станів з останньої реалізації неPACFrfmeworkовської програми також перекочував сюди. Імітацію я теж виніс в окрему "дзеркальну" функцію. Поступово намагаюся стандартизувати й типові блоки обробки. Щодо реалізації таких блоків у вигляді універсальних функцій, досвід виявився не надто вдалим. Колись цей підхід привів до появи великої кількості проміжних "універсальних" типів та допоміжних функцій-перетворювачів. У підсумку складність тільки зросла, а очікуваної універсальності отримати не вдалося. Тому цього разу вирішив не повторювати старих помилок. Усі ніші ідеї залишилися з PACFramework. Це агрегація тривог, станів, режимів з підлеглих CM нижнього рівня: стани по OR, кількісний підрахунок та обробка команд. Цікавим і практичним виявився підхід змінних заглушок. Це коли ти робиш інтерфейс з максимальною кількістю можливих змінних. Наприклад клапан з двома датчиками кінцевого положення. Якщо одного з них немає (тимчасово, або постійно) замість реальної змінної підключається змінна заглушка цього ж типу. Враховуючи що це структура з відповідним бітом "DISABLE" алгоритм реалізації клапану розуміє, що по факту датчика немає, і працює по алгоритму керування клапаном з одним датчиком. Якщо змінна дійсна, а датчика немає, технік може помітити змінну як DIASABLE, і зробити схему робочою.

  • До речі, якщо вам цікава тема економії тегів, про яку писав вище, можете ознайомитися з результатами дослідження, яке свого часу ініціював Володимир Полупан, ну і ми з колегами трохи прийняли участь: https://journals.uran.ua/eejet/article/view/309029. На скриншоті показано вікно конфігурування та налагодження одного з проєктів 2017-го року.

  • Наступна серія постів про PACFramework та перехід до PFw2. Тема цього поста зумовлена одним із коментарів. Лекція стає цікавою для викладача, коли студенти ставлять питання по темі. Так само і в мене: бажання про щось розповідати зростає в рази, коли в читачів виникають запитання. Отже, сьогодні розкажу про розділення змінних на конфігураційні (CFG) та HMI, про які я трохи згадував у попередньому пості. Ідея такого розділення виникла десь у 2014–2015 роках, які я називаю передкаркасним періодом. Каркас уже активно формувався, але ще не був усвідомлений саме як каркас. В одній з інжинірингових компаній виникла задача майбутньої інтеграції АСКТП із рівнем MES. Це привело до потреби уніфікації інтерфейсу між системами. Вимоги зверху були досить чіткими, а моїм завданням була розробка такого стандартного інтерфейсу. Задачу я "успішно" провалив. Наскільки пам'ятаю, замовник вважав, що я заклав надто високі вимоги до реалізації, тому дарма скіпанувся. Але це вже історія. Головне, що саме під час роботи над цією задачею сформувалися деякі ідеї, які пізніше стали частиною PACFramework. Тепер до суті. Коли я аналізував набір даних для передачі між системами, то вперше усвідомив одну важливу річ. Дані мають спільний об'єктний контекст, тобто групуються навколо обладнання, але водночас мають зовсім різне призначення. Наприклад, маємо двигун. У нього є: стани (увімкнений, вимкнений); режими (ручний, автоматичний, заблокований тощо); числові параметри (струм, частота та інші); тривоги; налаштування; параметри відображення; коефіцієнти масштабування; мотогодини, статистика та інші службові дані. І все це потрібно було передавати через Modbus (в т.ч. Modbus RTU). Той, хто працював із Modbus або подібними протоколами, добре розуміє важливість групування змінних. Я досить багато часу приділив вивченню мережевих протоколів, тому перше питання, яке поставив собі: наскільки швидко весь цей "поїзд" із даними буде рухатися мережею? Адже дані реального часу становлять менше половини від загального обсягу інформації. Решта - це конфігураційні та сервісні дані, які змінюються значно рідше. З одного боку, змінні потрібно групувати навколо обладнання. Для цього існує багато вагомих причин, про які можна написати окремий пост. З іншого боку, дані реального часу та конфігураційні дані мають принципово різні вимоги до передачі. Дані реального часу потрібно передавати постійно, а конфігураційні - лише за потреби. Якщо змішати їх в одному потоці, то конфігураційні дані будуть зайвий раз навантажувати мережу та затримувати передачу дійсно важливої інформації в даний момент часу. У той самий час я усвідомлював ще одну важливу проблему - потреба в економії тегів у SCADA. Конфігураційних даних завжди дуже багато, а кількість ліцензійних тегів майже завжди обмежена. Десь за рік до цього, аналізуючи один із проєктів невідомого мені автора (до речі з тієї ж інжинірингової компанії), я вперше побачив використання буферів. Не знаю, звідки він узяв цей підхід, але ідея мені дуже сподобалася, хоча активно використовувати її я почав трохи пізніше. І, мабуть, саме тоді все склалося в єдину картину. Дані реального часу повинні передаватися постійно окремим потоком. Конфігураційні дані повинні передаватися окремо й лише за запитом. А якщо кожен тег має свою ціну, то чому б не передавати конфігураційні дані через універсальний буфер? Таким чином одним рішенням вдавалося вирішити одразу дві задачі: зменшити мережевий трафік і скоротити кількість тегів вводу-виводу в SCADA/HMI. Саме так поступово сформувався підхід із розділенням CFG та HMI-даних, який згодом став одним із базових принципів PACFramework, ну і частково перекочував і в PFw2. Крім того, таке розділення дало можливість стандартизувати інтерфейс обміну з HMI (відмова від bool, вирівнювання, тощо), водночас зменшивши вимоги до стандартизації внутрішньої логіки та механізмів, що працюють у фоновому режимі. Навіть з точки зору кібербезпеки це потенційно дає додаткові можливості.

  • Попри те, що рівень технологічних змінних виявився доволі стійким і добре переносився між платформами та типами обладнання, у PFw2 я вирішив його суттєво переглянути. По-перше, я прибрав із нього більшість функцій, які сильно залежать від конкретного проєкту. Це дозволило значно спростити як конфігураційні структури (CFG), так і інтерфейсні структури (HMI). До речі, тему розділення CFG та HMI я ще окремо не висвітлював. Якщо коротко, CFG-структури призначені для внутрішньої роботи ПЛК, а для SCADA/HMI використовуються окремі HMI-структури - значно компактніші та максимально платформонезалежні. Так от. У результаті в технологічних змінних залишилися лише базові функції: масштабування, інверсія (для дискретних сигналів) та фільтрація. Усі тривоги та специфічні функції на кшталт нелінійного масштабування були прибрані. Якщо вони потрібні конкретному проєкту, їх завжди можна реалізувати окремо. Тривоги ж повністю переїхали на рівень LVL2 і вище. По-друге, і це вже зовсім свіже рішення, я вирішив взагалі не надавати технологічним змінним прямого доступу до HMI. Колись мене довго бентежило питання, як зробити так, щоб змінні були складовою обладнання LVL2 і вище та не дублювалися в SCADA/HMI. Тепер не бентежить, бо у більшості випадків SCADA/HMI вони просто не потрібні. Єдиний аргумент, який довго стримував мене від такого рішення - це можливість налагодження. Але зараз я експериментую з перенесенням функцій форсування та інших сервісних можливостей із LVL1 HMI безпосередньо в LVL2 HMI. Поки що цей підхід виглядає навіть зручнішим. Більше того, багато функцій тепер реалізуються взагалі без використання буферів. Залишається одне невирішене питання - робота з резервними змінними. Поки що воно не є критичним, оскільки стосується радше зручності, ніж необхідності. Так, у PACFramework така можливість є. Але навіть якщо я не знайду елегантного способу реалізувати її в PFw2, це точно не той аргумент, який змусить мене відмовитися від нового підходу. Далі буде...

  • Якщо вас зацікавив серіал про перехід до другої версії каркасу PFw2, то цей пост є його черговою серією. Сьогодні розкажу про технологічні змінні. У PACFramework змінні є основою інформаційної моделі каркасу. Варто зауважити, що він значною мірою базується на стандарті ISA-88, де нижнім рівнем моделі обладнання є так звані Control Modules, які виконують базові функції. У каркасі цей рівень розділений на три підрівні: канали, технологічні змінні та пристрої (див. рисунок). Про канали я вже розповідав - вони слугували рівнем абстрагування від конкретної платформи (у PFw2 цей рівень уже відсутній). Про пристрої ще розкажу в наступних серіях. Технологічні змінні - це саме ті об'єкти, які забезпечують систему всією інформацією про об'єкт автоматизації та є посередником для керуючих дій. Коли ви дивитеся на схему автоматизації або P&ID, то майже все, що вимірюється та керується, і є технологічними змінними. Вони працюють в інженерних одиницях, забезпечують масштабування, перетворення даних у потрібний вигляд, фільтрацію, інверсію, контроль неадекватної поведінки сигналів тощо. Як і канали, вони підтримують форсування та надають повну інформацію про джерело даних. Крім того, саме на рівні змінних реалізовувалися прості тривоги типу HI, HIHI та подібні. Хоч особливих претензій до самої ідеї технологічних змінних у мене не було, існувала низка проблем, які постійно "муляли". По-перше, самі змінні здебільшого не є суб'єктними об'єктами. Вони практично завжди обслуговують об'єкти LVL2, однак уваги та ресурсів їм виділялося непропорційно багато. Одна з головних ідей PACFramework - завжди мати все під руками, навіть якщо на початку це не потрібно. У результаті змінні на кшталт AIVAR, які відповідають за обробку аналогових входів, тягнули на собі величезну кількість функцій, що в більшості проєктів ніколи не використовувалися. Причому кількість цих функцій і сама структура змінної збільшувалися від проєкту до проєкту, адже накопичений досвід хотілося переносити далі. Логіка була проста: якщо функцію зараз не включити, то потім її вже не використаєш, а ніколи не знаєш, що знадобиться в найневдаліший момент. Той, хто працював із різними PLC-платформами, добре розуміє, наскільки проблмеатично змінювати структуру змінної на працюючому об'єкті, не зупиняючи ПЛК і не перекомпоновуючи всю програму. Відповідно, і структура буферів поступово підлаштовувалася під такі можливості. Другою проблемою було керування тривогами. З одного боку, зручно мати можливість налаштувати будь-яку технологічну змінну на будь-яку класичну тривогу без перепрограмування ПЛК. Але для більшості процесів тривоги потрібно вмикати лише на певних етапах технологічного циклу, а це вже точно не завдання LVL1. Я вже не кажу про значення уставок, які в Batch-процесах можуть змінюватися залежно від рецепта. Через це почали з'являтися додаткові біти стану на кшталт "тимчасово вимкнути тривоги", а сама змінна дедалі більше перетворювалася на носій уставок, а не на універсальний інструмент роботи із сигналом. Третя проблема, точніше незручність, стосувалася механізму форсування. Наявність функції форсування сама по собі дуже корисна. Але щоб нею скористатися, потрібно було знайти змінну в довгому списку, завантажити її в буфер, перевести в режим форсування і вже після цього задавати значення через буфер. Для каналів це ще було прийнятно, оскільки форсування зазвичай використовувалося для перевірки конкретного входу або виходу. Але для технологічних змінних форсування здебільшого потрібне під час налагодження алгоритмів, тобто на рівні LVL2. У такому випадку хочеться бачити всі потрібні змінні безпосередньо в контексті обладнання та працювати з ними одразу. Різні спроби вирішити це питання залишалися локальними доробками й не усували проблему на рівні архітектури.

  • Сьогодні розкажу про еволюцію буферів від PACFramework до PFw2. Буфер - це об'єкт, який забезпечує перегляд та зміну конфігураційних даних об'єктів у ПЛК. Враховуючи велику кількість таких даних, виникає банальна потреба в економії тегів у SCADA/HMI, оскільки їх кількість або просто обмежена, або кожен тег коштує додаткових грошей. А виявляється, що конфігураційних даних часто більше, ніж даних реального часу. З огляду на те, що читати та записувати їх потрібно лише за потреби, така собі універсальна "коробка" для перенесення будь-яких даних значно зменшує кількість тегів вводу-виводу. Крім того, така реалізація часто потребує менше рутини. Працює це так. Виділяється група тегів під буфер. Коли потрібно конфігурувати якийсь об'єкт, він займає буфер, і в цей момент усе, що в ньому знаходиться, стосується саме цього об'єкта. Коли потрібно записати конфігураційні дані, значення з буфера записуються в об'єкт на ПЛК, а коли прочитати - навпаки, дані об'єкта копіюються в буфер. Ідентифікація об'єктів проводиться за ID та CLSID, про які я писав минулого разу. Протягом розвитку першої версії каркасу було багато експериментів із буфером. Але його найбільша підступність полягала в тому, що за наявності кількох HMI-клієнтів для одного ПЛК буфер "перехоплювався", що створювало незручності, а інколи й призводило до помилок. Доводилося або забороняти кілька конфігураційних клієнтів одночасно, або придумувати механізм блокування "відбору" буфера. Другою незручністю, пов'язаною із самою природою буфера, була наявність конфігураційних даних лише в ПЛК, оскільки буфер був лише тимчасовим вікном до цих даних, а в SCADA нічого не залишалося. Не завжди цього достатньо, адже деякі параметри використовувалися для відображення та анімації графічних символів. Цю проблему було вирішено ще на ранніх етапах розвитку, у 2017 році. Було реалізовано фонову передачу даних від PLC до SCADA, яка за кілька хвилин оновлювала всю базу SCADA. Однак гарантій за часом для такого обміну дати не можна, оскільки інтервал підбирався експериментально. Рішення проблеми "ексклюзивності" буфера здавалося простим і лежало на поверхні. Потрібно було просто копіювати дані з буфера в локальну базу SCADA і більше його не утримувати. А за потреби - "викликати" буфер і записувати через нього дані в PLC. Усе виглядало чудово, але проблема крилася в забезпеченні консистентності даних. Далеко не всі SCADA/HMI можуть гарантувати консистентність структур, а в деяких засобах поняття структури взагалі не існує. Нагадаю, що PACFramework розроблявся (та й досі залишається) платформонезалежним каркасом, бо таке вже в нас, фрилансерів, життя: то Schneider, то Siemens, то ще якісь засоби. У PFw2 я все ж вирішив використати буфер без механізму заволодіння, а проблему консистентності вирішити комплексом заходів. Таким чином буфер перестає бути ресурсом, яким потрібно володіти, і перетворюється на транспортний механізм для обміну даними. По-перше, на початку та в кінці буфера розміщується однакове контрольне значення. Багато SCADA-систем і драйверів під час читання автоматично об'єднують суміжні адреси в один запит, але при записі часто виконують кілька незалежних транзакцій. У результаті в певний момент часу частина буфера вже може містити нові дані, а частина - ще старі. Перевірка контрольного значення на початку та в кінці дозволяє виявити такі проміжні стани. Це ж значення одночасно використовується як ідентифікатор запиту, що дозволяє відрізняти нові дані від застарілих. По-друге, для перевірки цілісності використовується хеш, який передається в буфері. Поки всі перевірки не будуть успішно пройдені, приймаюча сторона не приймає дані. Поки що ця технологія тестується в домашніх умовах. Можливо, ще вилізе щось неочікуване. У будь-якому разі завжди можна повернутися до старого перевіреного підходу. Далі буде... В коменті даю рисунок, бо телега не їсть все разом.

  • Продовжую свою розповідь про зміни в PFw2 (вже не пояснюю, що це таке, бо це не перша серія цього серіалу, тому кому цікаво - читайте попередні). Сьогодні розкажу про ідентифікацію об'єктів. У "класичному" PACFramework кожен об'єкт має числові ID (ідентифікатор об'єкта) та CLSID (ідентифікатор класу). Почну з CLSID. Він давав можливість кастомізувати універсальні об'єкти. Наприклад, графічне представлення панелі налаштування могло змінюватися залежно від CLSID (наприклад, чи це конфігурування аналогової змінної, чи дискретної). Або виконання функції могло змінювати частину алгоритму залежно від класу (наприклад, мережні змінні не прив'язуються до каналу) тощо. Водночас кожен об'єкт мав мати унікальний ID лише в межах свого класу. На ID базується буферний обмін, про який, як і обіцяв, розкажу в наступних серіях. Зараз лише скажу, що ідея полягає в тому, що конфігураційні дані передаються між SCADA та PLC тільки за потреби, а ідентифікація об'єкта призначення відбувається за ID. Це дещо схоже на словник об'єктів у CANopen, якщо ви мали справу з цією мережею. При цьому все інше в самій SCADA та PLC працює із символьними ідентифікаторами змінних. У PFw2 я відмовився від CLSID, і на це є кілька причин. По-перше, для кастомізації в межах групи класів є й інші механізми, наприклад бітові параметри. Щодо міжкласових особливостей, то вони й раніше використовувалися не дуже часто, а зараз - тим більше. По-друге, CLSID займають додаткову пам'ять, хоча далеко не завжди використовуються. З ID були інші проблеми. За ними потрібно було слідкувати, коли з'являлися нові об'єкти або зникали старі. Ітераційний процес розроблення постійно вимагав зміни ID, хоча саме значення ID не несло жодного змісту - потрібна була лише унікальність. До того ж у багатьох випадках ID доводилося прописувати і в PLC, і в SCADA, оскільки цього вимагав буферний обмін. У результаті доводилося постійно тримати разом числові ID та символьні назви, і тут дуже допомагали інструменти автоматизації розроблення коду. Нарешті я знайшов рішення, як поєднати символьні та числові ідентифікатори так, щоб більше не доводилося за ними слідкувати. Допомогли набуті знання в ІТ, зокрема ідея хешів. Тепер ID генерується з хешу імені об'єкта, і лише зміна назви призводить до зміни ID. Взагалі хеші в PFw2 мають ще кілька додаткових призначень, але про це напишу пізніше. З мінусів - тепер на ID виділяється 4 байти замість двох. Але, враховуючи, що зникла необхідність ідентифікації на LVL0 (канали, бо їх у PFw2 немає, як писав минулого разу) та LVL1 (змінні, оскільки змінилися правила їх конфігурування, про це ще напишу), це вже не виглядає суттєвими накладними витратами. Далі буде..

  • Ще рано говорити про кінцеві результати, але одне можу сказати точно: інколи потрібно відмовитися від старого, якщо хочеш отримати щось якісно нове. Хоча це майже завжди потребує додаткових зусиль і часу. І в мене такі зміни відбувалися практично на кожному проєкті, що певною мірою суперечить самій ідеї каркасів. Але така крута зміна в каркасі вперше, тому очікування також вищі. Є ще один важливий момент - раніше я враховував необхідність командної роботи і потенційні потреби інших користувачів, хто може користуватися каркасом. Сьогодні я усвідомив, що більш цінними є концепції, прийоми, технології, які вдало використані на прикладі. Сам каркас - це набір заготовок та інструкція для їх поєднання (наразі останнє більше для ШІ а не для команди). Кому цікаво - може розібратися і адаптувати під себе. Це і є свобода, а не догми використання. І чим більше буде свобод, тим гнучкіше буде у використанні каркас. Далі буде... У коменті рисунок, бо для телеги великий текст з рисунком це перебір