Ця стаття про управління світлодіодами WS2812b, трохи про синтез логічних схем і реалізацію їх всередині мікроконтролера. Стаття з невеликими відступами і двома бонусами. Перший бонус ґрунтується на тому факті, що коли ми пишемо, то одночасно читаємо (хіба ні?). Другий бонус допоможе почати програмувати мікроконтролери і за 10 хвилин самим повторити реалізацію, описану в статті.
Триколірні «SPI світлодіоди» WS2812b (рис. 1) з драйвером і їх попередники WS2811/WS2812 включаються послідовно і керуються за однопровідною (послідовною) шиною (звідси іноді помилково називаються «SPI світлодіодами», хоча в описуваному випадку, особливо для «бонусу # 1», інтерфейс SPI відіграє ключову роль). Кожен біт кольору RGB (24біта, 8 біт на канал) кодується ШИМ сигналом (див. рис. 2), з періодом близько 1.25мкс. Світлодіоди WS2812 часто застосовуються в керованих світлодіодних стрічках і екранах, оскільки мають швидкий і простий інтерфейс, а кількість світлодіодів легко нарощується. Так, наприклад, при частоті 25 кадрів на секунду відео екран може містити одну лінійку з (40мс - 50мкс )/( 0.125мкс x 24) ауд = 1300 RGB світлодіоду. Це не так багато, але для рекламних вивісок, табло або біжучого рядка може бути цілком достатньо.
Ріс. 1. Світлодіодна стрічка з цифровим послідовним інтерфейсом
Ріс. 2. Параметри кодування бітової послідовності
Застосування дешевих мікроконтролерів для формування таких коротких сигналів (див. рис. 2) представляє певні труднощі. Так, наприклад, для контролера PIC16 з тактовою частотою 16МГц одна команда виконується за 250нс. Таким чином, для програмного управління драйвером WS2812 потрібно витратити практично 100% швидкодії ядра.
Синтез інтерфейсу
Для вирішення завдання можна було б використовувати апаратні можливості мікроконтролера, наприклад SPI інтерфейс. Часто використовують такий трюк, коли для передачі «нуля» передають послідовність «11100000», а для «одиниці» - «11111000», тобто один біт кодується байтом (або напівбайтом).
Інший шлях - використання SPI інтерфейсу і логічних елементів. У нотатках щодо застосування [1] та [2] опубліковані приклади, на яких в основному базується описана реалізація.
Отже, якщо взяти сигнали SPI інтерфейсу та інвертувати сигнал SCK (сигнал синхронізації) і об'єднати з SDO (вихідні дані) логічною функцією І, то отримаємо закодовані «Одиниці» (рис. 3).
Ріс. 3. Кодування одиниць
Для кодування «Нулів» потрібен інший сигнал з меншою тривалістю. Для цього можна використовувати ШИМ мікроконтролера. «Нулі» кодуються сигналом, описаним логічним виразом n (SDO) * n (SCK) * PWM (n це інверсія). Саме такий вираз наведено у [1] і [2], але, як можна помітити з підсумкової діаграми (рис 5), або вивести при синтезі логічної схеми за допомогою таблиці істинності і карт Карно, вираз можна записати як nSCK * PWM.
Ріс. 4. Кодування «нулів»
Залишається об'єднати потоки «Нулів» і «Одиниць» функцією АБО, і отримати потрібну ШИМ послідовність управління драйвером WS2811/WS2812.
Ріс. 5. Результат кодування потоку
У вигляді логічного виразу сигнал управління записується як:
(nSCK * SDO) + ( nSDO * nSCK * PWM) {1}
Застосовуючи теореми бульової алгебри (див., наприклад, чудовий підручник [3]) можна показати, що вираз {1} перетворюється до еквівалентних виразів:
n(SCK + nSDO) + n(SDO + SCK + nPWM) {2}
(nSCK * PWM) + (nSCK * SDO) {3}
n(SCK + nPWM) + n(SCK + nSDO) {4}
nSCK * (PWM + SDO) {5}
Багато молодших мікроконтролерів Microchip, наприклад PIC16F1508, PIC16F1509 мають вбудовані налаштовані Логічні комірки (Configurable Logic Cell, CLC).
Конфігуровані логічні осередки це незалежна від ядра периферія, яка може допомогти в реалізації логічно пов'язаної роботи периферії мікроконтролера і зовнішніх сигналів. Асинхронність від ядра і незалежність від програми дозволяє реалізовувати функції, які складно здійснити тільки програмними способами.
Вхідними сигналами для CLC можуть бути вхідні сигнали мікроконтролера, виходи CLC, інші вбудовані периферійні модулі і внутрішні генератори. Виходи CLC можуть виводитися на порти і використовуватися спільно з іншою периферією контролерів.
Враховуючи вищесказане, зв'язка SPI інтерфейсу і CLC виглядає як ідеальний варіант для вирішення завдання формування керуючого сигналу драйвера світлодіодів WS2812 (WS2811).
Для візуального конфігурування CLC і формування коду призначена утиліта "CLC Designer", так само конфігурування периферії мікроконтролерів можна здійснити через плагін "Mplab Code Configurator" "(MCC) до середовища розробки MPLAB X.
Не всі комбінації вхідних сигналів присутні на входах логічних комірках. Тому необхідно знайти таку комбінацію сигналів і комірок, які потрібні для виконання конкретного завдання. Для кодування даних на комірках CLC нам потрібні сигнали SCK, SDO і PWM. Логічний осередок CLC4 на своїх входах може мати сигнали від SCK, SDO, але не має сигналу від PWM, а CLC2 може на своїх входах мати PWM. Вихід CLC2 можна з'єднати з входом CLC4. Тому CLC2 буде виступати в ролі повторювача і транслювати ШІМ на вхід CLC4, а CLC4 буде виконувати логічну функцію виразів {1}, {2},... {5}.
Рис.6. CLC2 транслює PWM на вихід. Gate2 - 4 мають на виході лог.1 і не впливають на підсумковий результат
Насправді, функцію {1} у наведеному вигляді не реалізувати на одній комірці CLC, але її еквівалентні форми {2}... {5} - легко. (см.рис. 7).
Ріс. 7. CLC4 формує ШИМ кодування SPI сигналу через функцію n (SCK + SDA + nPWM) + n (SCK + SDA)
В даному випадку застосований додатково D-тригер, що дозволяє вхідним сигналам бути розсинхронізованими щодо тактової частоти контролера і уникнути помилкових перемикань виходу. Взагалі, для конкретного випадку D-тригер може бути не обов'язковим, але така конфігурація дає більш передбачувані таймінги на виході (синхронізація від тактової частоти FOSC).
Відступ # 1. П «ять способів розв» язання однієї задачі
Реалізацію логічних функцій {2}... {5} наведено на рис. 7a... 7г. Всі вирази еквівалентні і дають очікуваний результат (див. рис. 5).
Ріс. 7а. (nSCK * PWM) + (nSCK * SDO)
Ріс. 7б. n(SCK + nPWM) + n(SCK + nSDO)
Ріс. 7в. nSCK * (PWM + SDO)
Ріс. 7г. n(SCK + SDA + nPWM) + n(SCK + SDA)
Відступ # 2. Паразитні імпульси в комбінаційних логічних схемах
Можливі ситуації коли зміна вхідного сигналу призводить до кількох змін виходу, в результаті чого формується паразитний імпульс (glitch). Це може статися, якщо мінливий вхідний сигнал проходить до виходу кількома шляхами і кількість прохідних логічних вентилів в різних шляхах різна. Тоді, за рахунок затримки кожного з логічних елементів і різниці в часі проходження по «найкоротшому» і «критичному» шляху, можливе формування паразитного імпульсу. Цей процес добре описано у [3].
Для конкретного нашого прикладу, при реалізації функцій {1}... {5} таких ситуацій не виникає, але навіть якщо б і виникло, то проблему можна вирішити використовуючи конфігурацію OR-D конфігурованих комірок. Тоді схему з ризи.7г можна перерисувати як на рис. 7 (д), де додатковий D-тригер фіксує значення на виході по фронту сигналу тактової частоти контролера FOSC.
Ріс. 7д. Та ж функція що і на рис. 7г., але з анджелілкою по виходу
Отже, після того, як проведена конфігурація CLC, ШИМ і SPI, підготовча частина закінчена. Тепер якщо записати байт до регістру SSP1BUF, то на виході CLC4 отримаємо кодований ШІМ сигнал відповідно до формату WS2812. Поки SPI модуль передає дані, мікроконтролер може виконувати якісь інші завдання. Для кожного світлодіоду необхідно передати три байти. Схема підключення наведена на рис. 8.
Ріс. 8. Підключення стрічки WS2812b до мікроконтролера
Бонус # 1. Збільшення пам'яті
В описаному способі налаштована логіка і її спільна робота з периферією мікроконтролера забезпечує формування часових параметрів протоколу у форматі WS2812, від програми потрібно тільки записати байт в буфер SPI, подальшу «магію» беруть на себе налаштовані логічні комірки. Оскільки в описаному прикладі SPI використовується тільки для запису, а вхідна лінія SDI залишається вільною, то надається відмінна можливість використання SPI не тільки для управління світлодіодами, але і для одночасного отримання зовнішніх даних. Розгляньмо як одночасно з керуванням світлодіодами читати дані з мікросхеми пам'яті з інтерфейсом SPI.
SPI порт PIC мікроконтролера має два зрушення (один для передачі, один для прийому) з однією адресою. Запис в SSPBUF почне передачу байту і зрушує бітики в лінію SDO але одночасно в цей же регістр зрушуються дані з вхідної лінії SDI. Тобто передаючи байт в SPI (SDO) ми одночасно приймаємо дані з SPI (SDI).
Таким чином, якщо з'єднати до модуля SPI мікроконтролера світлодіоди WS2812 і, наприклад, SPI пам'ять (SRAM 23LC512 або EEPROM 25LCxxx), для пересилання даних із зовнішньої пам'яті у світлодіодну стрічку програмі необхідно лише переписувати дані з SSPBUF в SSPBUF, тобто читати байт із зовнішньої пам'яті і наступною командою відсилати дані назад в SPI (у світлодіоди) і одночасно читати наступний байт тощо.
Ріс. 9. З'єднання зовнішньої пам'яті
Під час запису масиву даних у зовнішню SPI пам'ять або читання першого байту з пам'яті, потрібно відключити вихід CLC4, щоб не видавати «сміття» на світлодіоди.
Залежно від того, як часто необхідно оновлювати масив світлодіодів, кількість світлодіодів може бути дуже великою - вона обмежена швидкістю оновлення і розміром зовнішньої пам'яті. З лінійок світлодіодів можна створювати LED екрани і табло. Дані в дисплейному буфері можна змінювати в той час, поки зображення не оновлюється, це також дає час на більш складні обчислення, пошук по таблицях та ін., що необхідно для побудови показуваної картинки.
Наявність буферизованого зображення у зовнішній пам'яті дозволяє показувати рухомі зображення шляхом зсуву початкової адреси читання пам'яті. Під час використання SPI EEPROM пам'яті можна відображати заздалегідь записані зображення. Інтерфейс SPI дозволяє підключати кілька мікросхем пам'яті, наприклад, одну EEPROM для зберігання знакогенератора, статичних зображень, а в другій SRAM створювати дисплейний буфер для подальшого виведення на LED-екран.
Бонус # 2. Робимо самі
Для вивчення вихідців можна зайти на сайт Microchip (вихідні коди прикладу AN1890 доступні на сайті
Але я пропоную подивитися коротке відео, де в п'яти хвилинах показано, як всю вищеописану магію створити своїми руками.
Джерела
1. AN1606. Using the Configurable Logic Cell (CLC) to Interface a PIC16F1509 and WS2811. LED Driver www.microchip.com
2. AN1890. Simple SRAM Buffering for Large LED Arrays. www.microchip.com
3. Д. Харріс, С. Харріс. «Цифрова схемотехніка та архітектура комп'ютера» (http://habrahabr.ru/post/259505/)
