Автономні світлові ефекти DigiLight
В цій статті буде багато букв, мало картинок і одне відео (з перегляду якого варто почати). Але якщо ви зацікавились проектом DIGILIGHT - прочитайте, це напевно буде вам корисно!
\nПотреба в автономних, тобто не пов'язаних з музичним сигналом, світлових ефектах виникає досить часто, але пристрої з жорстко прописаними алгоритмами перемикання вогників швидко втомлюють, а переробляти або перепрограмувати їх - це ж така морока! \"Стоп, чому морока? Це ж можна зробити легко і приємно\" - подумав я і зробив відповідний модуль для світломузики DIGILIGHT, про яку писав раніше.
\n\nМодуль - це чисто програмно реалізована фішка, тобто ніяких додаткових апаратних пристроїв (не рахуючи адаптера SD-карти, звісно) не вимагає. Сенс його роботи в тому, що він зчитує з SD-карти файли сценаріїв, що описують на спеціально мною придуманій мові світловий ефект, і реалізує цей ефект. Коли сценарій закінчується, зчитується наступний файл і так до останнього, що є на SD-карті, після чого знову все повторюється з першого. Таким чином, кількість відтворюваних ефектів стає практично необмеженою (насправді їх може бути не більше 65535, що, погодьтесь, теж немало), а заміна надоїлих робиться в три кліки мишкою на комп'ютері. І основна задача, яку користувач повинен вирішити самостійно, полягає саме в написанні файлів-сценаріїв з бажаними ефектами.
\nДля полегшення цього процесу я розробив спеціальну програму DIGILIGHT Script maker (DSM), яка дозволяє не тільки зручно писати сценарії, але також перевіряти їх у дії без використання DIGILIGHT, тобто застосовується програмна симуляція апаратури. Але перш ніж приступити до її опису, слід пояснити прийняту термінологію.
\nКожен з світлодіодів WS2812b, якими керує DIGILIGHT, прийнято називати пікселом. Пікселів, як ви вже знаєте, може бути від 16 до 128. Однак описана програма призначена для симуляції тільки 32 пікселів - оскільки для описання світлових ефектів використовується в більшій мірі алгоритмічний підхід, це не є обмежуючим фактором, до того ж я вже працюю над вдосконаленою версією, - але це я знову побіг попереду паровоза... Отже, кожен піксел характеризується трьома параметрами: COLOR - RGB значення кольору піксела, BRIGHT - яскравість піксела, FADE - швидкість автоматичного зміни яскравості. Останній термін потребує додаткового пояснення. Ті, хто встиг покопатися в джерелах DIGILIGHT, напевно, вже в курсі, що кожен піксел, будучи єдиноразово засвіченим, потім без яких-небудь додаткових зусиль кожні 10 мілісекунд може змінювати свою яскравість, зменшуючи або збільшуючи її на величину FADE. Причому, якщо FADE має позитивне значення, яскравість піксела буде зменшуватися, а якщо негативне, то яскравість буде збільшуватися до граничного значення, а потім знак FADE автоматично зміниться на протилежний, і піксел почне з тим же темпом втрачати яскравість. Усі параметри, як і взагалі всі числові значення в сценаріях, однобайтові й записуються в HEX-форматі. Від'ємні числа в цьому випадку представляють певну незручність, але це вимушена жертва заради швидкості виконання сценарію.
\nОтже, приступимо до практичного процесу створення сценарію, що реалізує ось такий ефект (я назвав його \"комета\"), як на картинці нижче (клікніть на прев'ю, щоб толком розглянути анімацію).
\nСкачуємо і запускаємо DSM, і вводимо в відкритому вікні показаний на рисунку текст
\nСразу інформую, що при натисканні Ctrl-Space відкривається вікно з алфавітним списком усіх команд сценарію, які можна вводити - будь-які інші символи будуть сприйняті, як коментар. Якщо натиснути на палітру - відкриється вікно-помічник для вибору кольору, якщо вибрати і натиснути ОК, то прямо в тексті сценарію з'явиться відповідне RGB значення цього кольору - зручно вводити параметр COLOR. Табуляції - це для зручності. Головне - сценарій завжди повинен закінчуватися порожнім рядком - не помиляйтесь!
\nОтже, сценарій введено, натискаємо на \"червоного жучка\" і бачимо нове вікно \"відладчика\" наступного вигляду:
\nПри цьому і вікно редактора трохи змінюється: перша стрічка сценарію виділяється синім кольором, активуються раніше недоступні команди в меню Debug і відповідні їм кнопки.
\nЗабігаючи вперед, повідомляю, що виділяється синім стрічка сценарію, яка готова до виконання в режимі симуляції. Натискайте одразу на \"ракету\", зсувайте з'явившийся \"регулятор\" вправо до відмови, і спостерігайте за тим, як на чорному фоні демонструються 32 віртуальних світлодіода під дією тільки що написаного сценарію. Вражає? Кнопка \"паузи\" зупинить симуляцію, після чого натискаючи F8 (або кнопочку зі стрілкою \"в обхід\") можна буде виконувати команди сценарію в покроковому режимі, а повторне натискання на \"жучка\" знову поверне програму в режим редагування сценарію.
\nА тепер докладно про те, що ж саме зроблено і як воно взагалі працює.
\nПерша стрічка сценарію містить команду CLR - CLEAR, тобто очистка. Ця команда встановлює \"внутрішні піксели\" в вихідний стан, скидаючи їх колір у \"чорний\", встановлюючи яскравість на максимум (чорний - це відсутність світіння, так що хоч при якій яскравості нічого світитися не буде), а FADE в нуль. У вікні відладчика вміст усіх \"внутрішніх\", тобто використовуваних сценарієм, але невидимих, пікселів ви можете спостерігати у верхній його частині. З цієї команди рекомендується завжди починати будь-який сценарій.
\nКоманда у другій стрічці називається PAINT COLOR, або, скорочено, PC - колір малювання. Як бачите, ця команда після знака рівності містить значення RGB складових кольору - спробуйте змінити його і перезапустити симуляцію в автоматичному режимі (кнопка \"ракета\") - \"комета\" з пікселів змінить колір. Майте на увазі: ні в одній команді недопустимо використовувати пробіли - такі команди будуть сприйняті, як коментарі, тобто не будуть виконуватися. Команда PC сама по собі не вплине на жоден піксел, вона задає колір, яким на піксели буде впливати інша команда - PM, про неї далі. Поточне значення кольору ви можете контролювати в правій середній частині вікна відладчика, де, до речі, відображаються й інші два параметри \"малювання\" - BRIGHT і FADE.
\nТретя стрічка містить команду PF. Ви, напевно, вже здогадуєтеся, що це PAINT FADE, тобто затухання для малювання. Як і PC, ця команда просто встановлює текуще значення для команди PM. Аналогічно буде діяти і... правильно, PB (PAINT BRIGHT), але в цьому сценарії ми нею не користуємось, задовольняючись гранично можливим значенням FF, задаваним командою CLR.
\nКоманда RPT в четвертій стрічці - це REPEAT, або початок області повторення. Інакше кажучи, ця команда позначає початок області команд сценарію, які будуть повторюватися один або більше разів. Кінець циклу позначається командою LV0 або INF (є і інші команди, але всі я перераховувати в статті не буду, оскільки додав PDF файл з повним описом усіх команд - читайте самостійно). Логіку роботи цих команд розглянемо пізніше.
\n\n\n\n\nКоманда V0=TP представляє собою операцію призначення значення внутрішньої змінної. Скрипт-машина (умовимося так називати інтерпретатор DIGILIGHT) окрім внутрішніх пікселів і поточних параметрів \"малювання\" містить ще й 16 вбудованих \"змінних\", позначених V0, V1, V2 і так далі до VF. Як ви вже помітили, всі числа в сценарії завжди вводяться двома шістнадцятковими цифрами, тобто ніколи 9, але завжди 09. Назви змінних завжди займають 2 позиції. І це не просто так: у будь-якому місці, де в сценарії потрібно число, можна вказувати замість нього ім'я змінної, і тоді буде використовуватися її значення замість явно вказаного числа. Тобто замість PC=FF0000 ми цілком могли б написати PC=V5V6V7, якби заздалегідь потурбувалися про те, щоб змінні V5, V6 і V7 містили потрібні нам значення кольорових складових. Але, як бачите, в команді в змінну вноситься не число, і не значення іншої змінної, а... що?
\nВ доповнення до описаного, скрипт машина має і 3 \"функції\" - TP (TOTAL PIXELS), RD (RANDOM DATA) і RP (RANDOM PIXEL), які використовуються завжди, коли потрібно отримати загальну кількість пікселів, випадкове значення числа в діапазоні від 00 до FF або випадковий номер піксела з числа доступних. Функції, як і змінні, можуть використовуватися в усіх місцях сценарію, де потрібно число. Так що в п'ятій стрічці в змінну V0 поміщається кількість доступних пікселів - в DSM це буде 32, а в справжній DIGILIGHT те значення, яке ви встановите в налаштуваннях GROUP OF WS2812. Таким чином, наш сценарій буде однаково виконуватись на будь-яких системах, не вимагаючи корекції.
\nУ шостій стрічці ми знову бачимо команду початку циклу, тобто цей цикл виявляється вкладеним в попередній, що візуально виділено табуляціями - для зручності, не більше.
\nА ось у сьомій стрічці, нарешті, зустрічається вже згадувана команда PM - PAINT MAP, тобто \"карта малювання\". Після знака рівності в цій команді вводяться номери пікселів, які слід \"розфарбувати\" поточними параметрами COLOR, BRIGHT і FADE. У нашому випадку розфарбовується єдиний символ, номер якого зберігається в змінній V0.
\nЯкщо ви під час читання не лінувалися натискати кнопку F8, ви до цього моменту вже побачили, що виконання цієї команди змінило внутрішній піксел у вікні відладчика. Але, ймовірно, у вас виникло питання - якщо PM розфарбувала піксел у гранично яскравий колір, звідки береться затухаючий \"хвіст\"?! Але це ви поторопилися з питанням, продовжуйте читання - все стане зрозуміло через буквально 4 залишилися рядки сценарію.
\nВ рядку №8 ви бачите чергову команду WT, або WAIT - затримка. Ета команда реалізує одразу 2 дії: виводить внутрішні піксели на справжні, зовнішні світлодіоди, і здійснює затримку виконання сценарію на вказані після знака рівності десяти мілісекундних інтервалів. У конкретно нашому випадку затримка робиться на 50 мс. А тепер - увага: яскравість піксела змінюється кожні 10 мс, значення FADE у піксела ми задали рівним п'яти; запитання - що буде до моменту завершення команди WT=05? Вірно, піксел спалахне на максимум і встигне зменшити свою яскравість на 25 умовних одиниць, тобто до моменту завершення цієї команди його яскравість буде вже не 255, а 230 (в десятковому представленні - так наочніше).
\nКоманда в дев'ятій стрічці LV0, як вже було анонсовано, позначає кінець циклічно повторюваної послідовності команд. Літера L в цій команді позначає LOOP, тобто цикл, а от решта два символи визначають умову повторення циклу. Їх може бути кілька (дивіться файл з детальним описом), але в конкретному випадку застосований варіант \"цикла за значенням змінної V0 з автоуменьшенням\". Це означає, що змінна V0 буде зменшена на 1, результат буде перевірений на рівність нулю, і якщо змінна ще не дорівнює нулю, буде повторено виконання команд тіла циклу, тобто від попередньої (найближчої) команди RPT. Завдяки покроковому виконанню циклу в симуляторі можна розібратися, як це працює.
\nЯкщо згадати, що до початку циклу (рядок 6) змінна V0 містила номер останнього піксела, і врахувати, що кожну ітерацію циклу вона буде зменшуватися на 1, то легко можна зрозуміти, що щоразу буде виводитись піксел, що наближається до першого. Причому, як нещодавно було сказано, в момент виводу чергового піксела раніше виведені втрачають у яскравості 25 умовних одиниць - тепер зрозуміло, як утворюється \"хвіст\" комети? Не потрібно виводити багато пікселів з різною яскравістю, достатньо тільки виводити новий, а решту візьме на себе DIGILIGHT. Тільки слід враховувати, що симулятор все ж не ідеально імітує DIGILIGHT, зокрема, яскравість пікселів у симуляторі спадає більш інтенсивно, ніж у реальності, так як залежність яскравості WS2812b від значення кольорової складової нелінійна. Це означає, що реальний хвіст комети буде більш довгим, ніж у симуляторі, але тепер адже всім зрозуміло, які рядки треба підкоригувати, щоб вкоротити його?
\nУ 10-й стрічці використовується цікава команда REV - REVERSE, тобто реверс. Цікавість її в тому, що щоразу при її виконанні змінюється порядок нумерації пікселів для команди PM: якщо спочатку порядок нумерації прямий, тобто 0, 1, 2 і т.д. до значення TP, то після виконання команди REV нулевим пікселом стане останній, першим - передостання і т.д. Якщо команду REV виконати двічі - знову відновиться попередній порядок нумерації, і так далі. Ця невелика хитрість призводить до того, що наша \"комета\", долетівши до краю смуги пікселів, відскакує від нього і рухається в зворотному напрямку, тягнучи за собою хвіст.
\nНу а заключна команда INF - INFINITY - це команда \"безкінечного\" циклу, тобто без яких-небудь умов вона викликає повтор \"своєї\" тіла циклу, тобто починаючи з рядка 5. Залишилося лише зберегти сценарій у файл на SD-карту і вставити її в адаптер DIGILIGHT - і можна насолоджуватися створеним.
\nОсь так, за допомогою 11 команд реалізовано сценарій алгоритму, що створює досить красивий ефект. Погодьтесь, що досить просто і дуже ефектно. В якості тренування спробуйте самостійно модифікувати тільки що розглянутий сценарій так, щоб при кожному \"відбитті\" комети від краю вона змінювала б колір на випадковий. До речі, повне опис усіх команд сценарію з деякими поясненнями ви можете скачати - див. прикладені до статті файли.
\nЯк бачите, алгоритмічний принцип створення ефектів дає користувачу потужний і гнучкий, незважаючи на примітивність двох-трьох-буквених команд, інструмент для створення світлових ефектів. Вряд чи ви знайдете ще більш простий інструмент з аналогічною результативністю. Однак, цей принцип вимагає яких-небудь, але навичок програмування, що не кожному гуманітарію може бути зрозуміло - що ж робити їм? Для них залишається спосіб прямого указання послідовності включення-виключення пікселів: очистили внутрішній стан командою CLR, задали параметри командами PC, PF і PB - перерахували всі піксели з цими параметрами в команді PM, повторили аналогічне для пікселів з іншими параметрами і виконали команду WT - отримали один \"кадр\" ефекту. Потім аналогічним чином намалювали і вивели другий кадр, третій і так далі... Ну і в кінці можна додати INF, щоб \"музика стала вічною\". Муторно, довго, обсяг сценарію помітно виросте - але що робити? Це плата за відсутність навичок алгоритмічного мислення...
\nТак, трохи не забув: сценарій, що містить команду INF, сам по собі не закінчиться ніколи, тобто якщо DIGILIGHT добереться до файлу з таким сценарієм, жоден наступний файл автоматично вже не буде зчитаний, вам доведеться вручну енкодером примусово зчитувати наступний. Тому команди INF слід уникати, якщо це, звичайно, не обумовлено якоюсь усвідомленою необхідністю.
\nСподіваюся, описана програма, як і сам принцип створення світлових ефектів разом з конструкцією світломузики DIGILIGHT, вам сподобалися. Пропоную ділитися (через форум) створеними сценаріями ефектів, щоб накопичити \"бібліотеку\". Архів з кількома \"навчальними\", але цілком робочими сценаріями, зробленими мною в процесі роботи над DIGILIGHT, я додаю до статті разом з джерелами програми DSM (Free Pascal, проект для середовища Typhon).
\nПрикреплені файли:
\n- \n
- DSM-win32.zip (1112 Кб) \n
- Мова опису автономних світлових ефектів.pdf (236 Кб) \n
- dsm-source.zip (107 Кб) \n
- script_examples.zip (2 Кб) \n