ОБНОВЛЕНИЯ
v3.3 Исправлен критический баг с влиянием на другие пины
v3.4
- Переработан ASM вывод, меньше весит, легче адаптируется под другие частоты / тайминги
- Добавлена поддержка LGT8F328P с частотой 32/16/8 MHz
- Переработан поллинг millis()/micros() — прямой вызов прерывания TIMER0_OVF, убран лишний код
v3.5 Исправлена ошибка компиляции в некоторых угодных компилятору случаях
ТЕОРИЯ
Мы с вами уже обсуждали адресные светодиодные ленты, есть гайд по особенностям подключения и сравнение библиотек. Что объединяет все библиотеки для управления адресной светодиодной лентой? Правильно, проблемы с нехваткой памяти, потому что один светодиод требует 3 байта оперативной памяти, по байту на каждый базовый цвет: красный, зелёный и синий. Протокол передачи данных на ленту состоит из последовательных передач байта каждого цвета, примерно так: R1, G1, B1, R2, G2, B2… Rn, Gn, Bn. Именно поэтому микроконтроллер хранит в памяти байт каждого цвета каждого светодиода в ленте. Для одного светодиода это выглядит так: RRRRRRRR GGGGGGGG BBBBBBBB – по 8 бит на каждый цвет. А что если попробовать “сжать” цвет? Мы попробовали!
БИБЛИОТЕКА
microLED – ультра-лёгкая библиотека для работы с адресной лентой/матрицей
- Основная фишка: сжатие цвета, код занимает в разы меньше места в SRAM по сравнению с аналогами (FastLED, NeoPixel и др.)
- Использование 8 битного цвета занимает в 3 раза меньше SRAM чем у других библиотек
- Использование 16 битного цвета занимает в 2/3 раза меньше SRAM чем у других библиотек
- Работа с цветом:
- RGB
- HSV
- HEX цвета
- “Цветовое колесо”
- Температура цвета
- 17 встроенных цветов
- Градиенты, фейды и другие инструменты
- Возможность чтения сжатого цвета
- Ограничение тока (автокоррекция макс. яркости)
- Быстрейшая реализация протокола общения с лентой
- Поддержка работы с адресными матрицами (см. пример)
- Поддержка чипов: WS2811, WS2812, WS2813, WS2815, WS2818, WS6812, APA102 (программно и SPI)
- Возможность работать без буфера (не занимая память в RAM)
- Поддержка всех AVR в том числе мелких аттини
- И многое другое!
Поддерживаемые платформы: ТОЛЬКО ДЛЯ АРХИТЕКТУРЫ AVR!!! тестировалось только на ATmega328 (Nano, UNO, Mini) и ATtiny85/ATtiny13. Должны поддерживаться и остальные МК этого поколения, тактовая частота только 8 и 16 МГц, а также 9.6 МГц для АТтини13.
УСТАНОВКА
- Библиотеку можно найти и установить через менеджер библиотек по названию microLED в:
- Arduino IDE (Инструменты/Управлять библиотеками)
- Arduino IDE v2 (вкладка «Library Manager»)
- PlatformIO (PIO Home, вкладка «Libraries»)
- Про ручную установку читай здесь
ДОКУМЕНТАЦИЯ
ОСОБЕННОСТИ
Данная библиотека нужна для проектов с лентой, в которых критичен объём занимаемой оперативной памяти: его можно уменьшить в 1.5 и 3 раза по сравнению с обычными библиотеками, а также вообще отказаться от динамического буфера и управлять лентой любой длины даже с ATtiny!! Библиотека написана очень просто, используемые в ней алгоритмы и решения очень прозрачны и могут кому-нибудь пригодиться. Единственный минус: инструменты для генерации и изменения цвета работают медленнее, чем в FastLED, поэтому для быстрых красивых эффектов на большой ленте/матрице придётся подключать фастлед для быстрой математики.
ПОДДЕРЖКА FASTLED (NEW!)
В версии 3.1 появилась полноценная поддержка совместной работы с FastLED для быстрого вычисления эффектов. Это позволяет выводить всякие шумы по палитрам даже на АТтини!! Для этого подключаем в скетч #include < FastLEDsupport.h>
(смотри примеры), саму FastLED подключать не нужно, она подключится автоматически. У нас появится функция CRGBtoData()
, которая переводит тип данных фастледа в микролед (конвертирует CRGB
в mData
при любой глубине цвета). В качестве примера работы с палитрой можно глянуть пример FIRE_with_FastLED.
ЦВЕТОВАЯ ГЛУБИНА
Цветовая глубина задаёт количество байт, которые занимает цвет одного светодиода и может быть от 1, 2 и 3 байта (8, 16 и 24 бита на один светодиод соответственно). Все остальные библиотеки используют 24-битную глубину цвета, в microLED её можно уменьшить для экономии памяти. При уменьшении цветовой глубины пропорционально уменьшается вес ленты в оперативной памяти, но в то же время ухудшается цвет: на эффектах с плавными переходами цвета будут заметны границы между оттенками. Настройка цветовой глубины задаёт работу всей библиотеки и делается при помощи дефайна COLOR_DEBTH
до подключения библиотеки:
#define COLOR_DEBTH 2 #include < microLED.h >
По умолчанию (если не указывать дефайн) глубина настроена на 24 бита (COLOR DEBTH 3). Понижать глубину рекомендуется только в целях экономии памяти.
ГАММА КОРРЕКЦИЯ
Ещё одна настройка, которая делается дефайном и влияет на всю библиотеку сразу. Гамма коррекция позволяет получать более естественные цвета и их смеси, а также более приятные глазу переходы яркости и реализована 4мя способами:
#define CRT_OFF
- коррекция отключена для экономии памяти и ускорения вычислений.#define CRT_PGM
- коррекция по таблице. Добавляет 256 байт во Flash память, но работает быстрее и красивее всех остальных.#define CRT_SQUARE
- квадратная коррекция. Занимает мало памяти, выполняется гораздо дольше таблицы (около 7 мкс).#define CRT_CUBIC
- кубическая коррекция. Выглядит приятнее квадратной, но выполняется ещё дольше.
По умолчанию включена коррекция по таблице. Остальные режимы - для продвинутого пользователя и экспериментов.
КАК РАБОТАЕТ БИБЛИОТЕКА?
Режим буфера
При инициализации указываем длину ленты, внутри библиотеки будет создан буфер типа mData
, который занимает 1, 2 или 3 байта в зависимости от выбранной цветовой глубины и олицетворяет цвет в формате RGB. С данным массивом можно работать как с обычным массивом и присваивать его элементам цвет в формате mData
(например, strip.leds[5] = mRed
). Само собой, массив занимает место в оперативной памяти микроконтроллера пропорционально длине ленты. Забив буфер цветами, можно вызвать strip.show()
и лента обновится с максимально возможной скоростью.
strip.leds[0] = mRGB(0, 230, 60); strip.leds[5] = mRed; strip.show();
Режим потока
В этом режиме буфер не создаётся (количество светодиодов указываем 0), оперативная память не занимается, а мы генерируем цвет пикселей "на лету". Для начала передачи нужно вызвать .begin()
, для передачи цвета - .send(mData цвет)
нужное количество раз и завершить вывод вызовом .end()
.
Тут есть некоторые ограничения: между вызовами send()
должно пройти не более 50-300 мкс (в зависимости от модели ленты), иначе вывод сбросится. Для экономии времени можно заранее посчитать цвет перед выводом, например зальём всю ленту:
mData data = mHSV(0, 255, 120); strip.begin(); for (int i = 0; i < num; i++) { strip.send(data); } strip.end();
ИНИЦИАЛИЗАЦИЯ ЛЕНТЫ
В библиотеке версии 3 и выше лента объявляется через шаблон: microLED< amount, pin, clock, chip, order, cli, millis>
объект:
amount
- количество светодиодов в ленте. Для работы в режиме потока можно указать0
, так как длина ленты фактически ничем не ограничена.pin
- пин, к которому подключен дата-вход ленты (D, Din, DI).clock
- пин, к которому подключен тактовый-вход ленты (C, CLK). Этот пин подключается только для SPI лент, например APA102.- Для работы с лентами серии WSxxxx нужно указать вместо этого пина параметр
MLED_NO_CLOCK
или минус 1 , т.е.-1
- Для работы с лентами серии WSxxxx нужно указать вместо этого пина параметр
chip
- модель ленты (светодиодов), в библиотеке поддерживаютсяLED_WS2811
,LED_WS2812
,LED_WS2813
,LED_WS2815
,LED_WS2818
,LED_WS6812
,APA102
,APA102_SPI
. Выбор модели ленты задаёт скорость протокола (она у них разная) и настройки тока потребления для режимов ограничения (о них читай дальше).order
- порядок цветов в ленте. В идеальном мире порядок цветов должен зависеть от модели чипа и эта настройка должна быть встроена в выбор чипа, но китайцы торгуют лентами, которые по протоколу совпадают с одним чипом, но имеют другой порядок цветов. Таким образом библиотека поддерживает больше типов лент, чем написано выше, но нужно угадать с выбором "клона" и порядок цветов. Порядок:ORDER_RGB
,ORDER_RBG
,ORDER_BRG
,ORDER_BGR
,ORDER_GRB
,ORDER_GBR
.
Оригинальные ленты на поддерживаемых библиотекой чипах имеют такой порядок цветов, также это готовая строка инициализации:
// microLED< NUMLEDS, STRIP_PIN, -1, LED_WS2811, ORDER_GBR> strip; // microLED< NUMLEDS, STRIP_PIN, -1, LED_WS2812, ORDER_GRB> strip; // microLED< NUMLEDS, STRIP_PIN, -1, LED_WS2813, ORDER_GRB> strip; // microLED< NUMLEDS, STRIP_PIN, -1, LED_WS2815, ORDER_GRB> strip; // microLED< NUMLEDS, STRIP_PIN, -1, LED_WS2818, ORDER_RGB> strip; // microLED< NUMLEDS, STRIP_PIN, -1, LED_WS6812, ORDER_RGB> strip; // microLED< NUMLEDS, STRIP_PIN, CLOCK_PIN, LED_APA102, ORDER_BGR> strip; // microLED< NUMLEDS, MLED_NO_CLOCK, MLED_NO_CLOCK, LED_APA102_SPI, ORDER_BGR> strip;
Можно вставить прямо в свой код =) Оставшиеся две настройки не являются обязательными (можно не указывать):
cli
- выбор настроек запрета прерываний для повышения надёжности вывода данных на ленту:CLI_OFF
- прерывания не отключаются (возможны сбои в работе ленты даже от прерываний системного таймера)CLI_LOW
- прерывания отключаются на время передачи одного цветаCLI_AVER
- прерывания отключаются на время передачи светодиода (3 цвета)CLI_HIGH
- прерывания отключаются на время передачи данных на всю ленту
millis
- при отключении прерываний в режиме среднего и высокого приоритета (CLI_AVER
иCLI_HIGH
) неизбежно будут чуть отставать функции времени millis() и micros(). В библиотеке встроено обслуживание функций времени, для активации передаёмSAVE_MILLIS
6-ым аргументом при инициализации:microLED< NUMLEDS, STRIP_PIN, LED_WS2818, ORDER_GRB, CLI_AVER, SAVE_MILLIS> strip
;
ОСОБЕННОСТИ 2Х ПИНОВЫХ ЛЕНТ (NEW!)
Существует два вида лент, имеющих 2 пина для управления (помимо питания):
- Ленты моделей WS2813, WS2815, WS2818 и их копии с буквами SK и такими же цифрами. У этих лент подключается только один пин из двух, тот который DI. Пин BI (B) не подключается. При инициализации указывается только DI пин, второй пишем -1 или "заглушку"
MLED_NO_CLOCK
. - Ленты моделей APA102 (она же SK9822) требуют подключения именно двух своих пинов, один из которых Data (D, DI, DAT), а второй - Clock (C, CLK, SCK). При инициализации указываем оба.
SPI ЛЕНТЫ (NEW!)
В библиотеке версии 3.1 добавлена поддержка SPI лент, в том числе аппаратная (на базе стандартной библиотеки SPI.h). Рассмотрим куски примеров.
При выборе LED_APA102
ленту можно подключить на любые два пина и указать их при инициализации. Всё
// пример работы с LED_APA102 программно #define DATA_PIN 3 // пин дата #define CLOCK_PIN 4 // пин клок #define NUMLEDS 50 // кол-во светодиодов #include // подключаем библу microLED< NUMLEDS, DATA_PIN, CLOCK_PIN, LED_APA102, ORDER_BGR, CLI_AVER> strip;
При выборе LED_APA102_SPI
лента подключается к выводам аппаратной шины SPI микроконтроллера:
- Data пин на MOSI (D11 на Arduino Nano)
- Clock пин на SCK (D13 на Arduino Nano)
Что это даёт? Аппаратный SPI позволяет выводить данные на ленту чуть ли не в 10 раз быстрее, чем программный способ! В коде должно быть:
#define MLED_USE_SPI // обязательный деф до библиотеки для поддержки SPI.h //#define MLED_SPI_CLOCK 8000000 // частоту SPI можно менять из скетча #include // подключаем библу microLED<NUMLEDS, -1, -1, LED_APA102_SPI, ORDER_BGR, CLI_AVER> strip;
Пины в этом случае не указываются! Ставим заглушку или -1. Это всё.
ГЕНЕРАЦИЯ ЦВЕТА
Для работы с цветом в библиотеке есть несколько инструментов, возвращающих тип данных mData
для отправки на ленту или в буфер. mData
- тип данных, который олицетворяет цвет светодиода в формате RGB. В зависимости от выбранной цветовой глубины является:
- 8 бит -
uint8_t
- 16 бит -
uint16_t
- 24 бита -
struct {byte r, g, b}
Собственно инструменты и функции:
mRGB(r, g, b)
- итоговый цвет будет замешан из красного, зелёного и синего, все параметры задаются в диапазоне 0-255mHSV(h, s, v)
- цвет из пространства hsv: цвет, насыщенность, яркость. Все параметры задаются в диапазоне 0-255. Цвет в диапазоне 0-255 совершает круг от красного к зелёному, от зелёного к синему и от синего снова к красному. Функция "тяжёлая", поэтому для генерирования "радуги" рекомендуется использоватьmWheel()
иmWheel8()
mHSVfast(h, s, v)
- то же самое, но выполняется быстрее и даёт менее приятные глазу цветовые переходыmWheel(val)
- принимает значение от0
до1530
и возвращает цвет из цветового круга, как и hsv. Выполняется очень быстроmWheel(val, bright)
- то же самое, но с яркостью (0-255)mWheel8(val)
- то же самое что предыдущий, но принимает0-255
и делает цвет постоянной яркости.mWheel8(val, bright)
- то же самое, но с яркостью (0-255)mHEX(val)
- принимает цвет в формате RGB888 (обычный web-формат). Например0xFF0000
это красныйmKelvin(temp)
- выдает цвет, соответствующий цветовой температуре temp в кельвинах- 16 предустановленных цветов:
mWhite, mSilver, mGray, mBlack, mRed, mMaroon, mOrange, mYellow, mOlive, mLime, mGreen, mAqua, mTeal, mBlue, mNavy, mMagenta, mPurple
getBlend(val, max, color1, color2)
- выдает цвет в указанном месте градиента двух цветов:val
- искомая точка (от 0 до max),max
- размер градиента,color1
иcolor2
- цвета, соответствующие 0 и max позиции градиента. НапримерgetBlend(30, 100, mRed, mBlack)
вернёт красный, смешанный с черным на 30/100, то есть чуть темнее красного.getFade(mData data, uint8_t val)
- вернёт цветdata
, яркость которого понижена наval
(0-255).uint32_t getHEX(mData data)
- вернёт HEX RGB888 вне зависимости от выбранной цветовой глубины (функция распакует и вернёт в привычном представлении)RGB888to565(x)
,RGB888to323(x)
,RGB565to888(x)
,RGB323to888(x)
- макросы конвертации цвета из одной кодировки в другую (принимает численное значение).getR(mData x)
- извлечь красный канал из цветаgetG(mData x)
- извлечь зелёный канал из цветаgetB(mData x)
- извлечь синий канал из цветаmergeRGB(r,g,b)
- объединить три цвета (0-255 каждый) в mData с учётом выбранной модели CRT гамма-коррекцииmergeRGBraw(r,g,b)
- объединить три цвета (0-255 каждый) в mDatafade8(byte x, byte b)
- уменьшить яркость x (0-255) на b (0-255)fade8R(mData x, byte b)
- уменьшить яркость красного канала цвета x на b (0-255)fade8G(mData x, byte b)
- уменьшить яркость зелёного канала цвета x на b (0-255)fade8B(mData x, byte b)
- уменьшить яркость синего канала цвета x на b (0-255)getCRT(byte x)
- получить скорректированное значение яркости x с учётом выбранной модели CRT гамма-коррекцииgetCRT_PGM(byte x)
- получить CRT из прогмем (работает только если выбрана PGM модель)getCRT_SQUARE(byte x)
- получить CRT по квадратной моделиgetCRT_QUBIC(byte x)
- получить CRT по кубической моделиRGB24to16(x)
- конвертация 24-бит цвета в 16-битRGB24to8(x)
- конвертация 24-бит цвета в 8-битRGB16to24(x)
- конвертация 16-бит цвета в 24-битRGB8to24(x)
- конвертация 8-бит цвета в 24-битRGB24toR(x)
- вытащить байт R из 24-бит цветаRGB24toG(x)
- вытащить байт G из 24-бит цветаRGB24toB(x)
- вытащить байт B из 24-бит цветаRGBto24(r,g,b)
- склеить 24-бит цветRGBto16(r,g,b)
- склеить 16-бит цветRGBto8(r,g,b)
- склеить 8-бит цвет
ГРАДИЕНТЫ
В библиотеке реализован инструмент для создания градиентов любого размера (количество цветных сегментов) и длины:
mGradient< 4 > myGrad; // создать градиент с именем myGrad на 4 точки // указываем цвет каждой точки myGrad.colors[0] = mBlack; myGrad.colors[1] = mRed; myGrad.colors[2] = mYellow; myGrad.colors[3] = mWhite; // создали градиент чёрный-красный-жёлтый-белый с одинаковым расстоянием между точками // при помощи .get(позиция, размер) можно получить цвет в заданном месте градиента при указанной длине // заливаем всю ленту for (int i = 0; i < NUMLEDS; i++) { strip.set(i, myGrad.get(i, NUMLEDS)); // получаем последовательно все цвета } strip.show();
РАБОТА С ЛЕНТОЙ ПОПИКСЕЛЬНО
Можно присвоить цвет в формате mData
напрямую в буфер: strip.leds[0] = mRed
. Есть функция set, которая делает то же самое:
set(num, color)
- установить светодиоду под номером num
цвет color
. Например strip.set(0, mWheel(120));
fade(int num, byte val)
- уменьшить яркость светодиода num
на величину val
get(num)
- вернёт цвет в формате mData
. Равносильно чтению элемента массива буфера strip.leds[num]
. Полученный цвет можно фейдить и применять к нему другие описанные выше модификаторы.
ЗАЛИВКА УЧАСТКОВ
clear()
- очистить все цвета в буфере (погасить светодиоды)fill(color)
- залить всю ленту цветомcolor
. Напримерfill(mRGB(120, 50 96))
fill(from, to, color)
залить цветомcolor
, со светодиодаfrom
доto
fillGradient(from, to, color1, color2)
- залить градиентом отcolor1
доcolor2
между светодиодамиfrom
иto
Примечание: это функции для работы с буфером. Для применения нужно вызвать show()
. Для потокового вывода эти функции не работают!
ЯРКОСТЬ
Яркость задаётся в setBrightness(val)
в диапазоне 0-255. Установка яркости занимается дополнительным уменьшением яркости, то есть если поставить цвет mRed
и максимальную яркость - это будет 255 по красному каналу цвета (максимум). Если поставить яркость 128, красный канал пропорционально уменьшится, остальные каналы останутся нулями.
РАБОТА С МАТРИЦЕЙ
Для работы с матрицей при инициализации, помимо настроек шаблона ленты, нужно указать параметры матрицы: (width, height, type, conn, dir)
. Где width
и height
- ширина и высота матрицы, type
, conn
и dir
- тип соединения матрицы, угол и направление подключения (см. картинки к документации).
Так как матрица - это все ещё лента, у каждого пикселя помимо двух координат есть номер в ленте. Получить его можно при помощи getPixNumber(x, y)
. Система координат - первая четверть декартовой СК: начало (0, 0) - левый нижний угол. Вверх растёт y, вправо - x.
set(x, y, color)
- включит указанный пиксель указанным цветом в форматеmData
get(x, y)
- прочитает цвет пикселяdrawBitmap8(int X, int Y, const uint8_t *frame, int width, int height)
- вывод битмапа (битмап 1мерный PROGMEM)drawBitmap16(int X, int Y, const uint16_t *frame, int width, int height)
- вывод битмапа (битмап 1мерный PROGMEM)drawBitmap32(int X, int Y, const uint32_t *frame, int width, int height)
- вывод битмапа (битмап 1мерный PROGMEM)
ОГРАНИЧЕНИЕ ТОКА (ЯРКОСТИ)
В библиотеке есть возможность автоматически ограничить яркость ленты по установленному току потребления при помощи setMaxCurrent(cur)
, где cur
- ток в миллиамперах. В самой библиотеке ток каждого типа ленты уже задан, но я измерял его для своих лент, и он может отличаться от лент, купленных в другом магазине. Для наиболее точной работы ограничения нужно настроить ток ленты для своей ленты, задав в oneLedMax
максимальный (белый, 255) ток одного светодиода в миллиамперах и oneLedIdle
- холостой ток (светодиод выключен) в мкА.
oneLedMax = (ток ленты с одним горящим) - (ток выключенной ленты) oneLedIdle = (ток выключенной ленты) / длина ленты * 1000
Берём кусок ленты, например WS2818, 180 диодов (3 в каждом секторе, 60 секторов):
- 160 мА когда горит один сектор из 60
- 114 мА когда лента не горит
Так как активный ток равен холостому + активному, 160-114 = 46 чистых мА на сектор имеем 114 / 60 = 1.9 мА холостых на сектор
strip.oneLedIdle = 1900; // задаём в мка strip.oneLedMax = 46; // задаём в ма
Берём бухту ленты, например WS2812, 60*5м = 300 диодов
- 102 мА когда горит один диод
- 74 мА когда лента не горит
Так как активный ток равен холостому + активному, 102-74 = 28 чистых мА на диод имеем 74 / 300 = 0.24 мА холостых на диод
strip.oneLedIdle = 240; // задаём в мка strip.oneLedMax = 28; // задаём в ма
ТИНИЛЕД!
В версии 3.1 появилась новая мощная штука: tinyLED.h - библиотека для вывода данных на ленту, написанная на ассемблере и использующая минимально возможный объём памяти! Библиотека задумана для генерации и вывода эффектов "на лету", когда программный буфер не используется. Это позволяет выводить ту же плывущую радугу на ленту неограниченной длины, занимая всего 300 байт Flash памяти и ноль оперативной!!! Тини 13 рада такому обновлению. Для обеспечения максимальной вариативности библиотека настраивается дефайнами перед подключением, их много, поэтому рассмотрим все.
НАСТРОЙКИ
Чип ленты выбирается дефайном
TLED_CHIP
. Доступны:
#define TLED_CHIP LED_WS2811 #define TLED_CHIP LED_WS2812 #define TLED_CHIP LED_WS2813 #define TLED_CHIP LED_WS2815 #define TLED_CHIP LED_WS2818 #define TLED_CHIP LED_WS6812 #define TLED_CHIP LED_APA102 #define TLED_CHIP LED_APA102_SPIПорядок цветов выбирается дефайном
TLED_ORDER
:
#define TLED_ORDER ORDER_RGB #define TLED_ORDER ORDER_RBG #define TLED_ORDER ORDER_BRG #define TLED_ORDER ORDER_BGR #define TLED_ORDER ORDER_GRB #define TLED_ORDER ORDER_GBRВ большинстве случаев порядок цветов совпадает с указанным в документации, но можно нарваться на подделку (если покупать не по моим ссылкам, а искать самую дешёвую ленту). Вот стандартная "расцветовка":
- LED_WS2811 - ORDER_GBR
- LED_WS2812 - ORDER_GRB
- LED_WS2813 - ORDER_GRB
- LED_WS2815 - ORDER_GRB
- LED_WS2818 - ORDER_RGB
- LED_WS6812 - ORDER_RGB
- LED_APA102 - ORDER_BGR
- LED_APA102_SPI - ORDER_BGR
TLED_CLI
, по умолчанию стоит LOW:
// #define TLED_CLI CLI_OFF // прерывания не запрещаются // #define TLED_CLI CLI_LOW // запрещаются на время передачи байта (стоит по умолчанию) // #define TLED_CLI CLI_AVER // запрещаются на время передачи светодиода (3 байта) // #define TLED_CLI CLI_HIGH // запрещаются на время передачи всей лентыУправление яркостью можно отключить целях уменьшения веса кода (экономия около 60 байт). Делаем одинокий дефайн
TLED_STATIC_BRIGHT
и setBrightness()
перестаёт работать. В то же время яркость светодиодов спокойно регулируется при генерации эффектов, общая яркость она и не нужна особо.
// #define TLED_STATIC_BRIGHTС пинами и подключением тут всё немного труднее: мы работаем напрямую с портом, поэтому должны его указать. 1 пин ленты
// по умолчанию задефайнен PORTB (для ATtiny) // можно указать свой порт, если у тиньки больше 8 ног или это вообще атмега // #define TLED_PORT PORTB // #define TLED_DDR DDRBСам пин указывается при инициализации объекта:
#include "tinyLED.h" tinyLED< 3> strip; // например пин 32 пин ленты, софт SPI
// программный SPI, например LED_APA102 // по умолчанию PORTB // можно указать свой порт, если у тиньки больше 8 ног или это вообще атмега // #define TLED_CLK_PORT PORTB // #define TLED_CLK_DDR DDRB // #define TLED_DAT_PORT PORTB // #define TLED_DAT_DDR DDRBСами пины указываются при инициализации объекта:
#include "tinyLED.h" tinyLED< 3, 4> strip; // < DATA, CLOCK > для 2-пин лент2 пин ленты, аппаратный SPI При выборе в качестве модели ленты
LED_APA102_SPI
в код автоматически подключается библиотека SPI.h. Она есть не для всех МК, так что не везде будет работать! Лента подключается к аппаратным выводам SPI микроконтроллера, например на Nano это D13 (CLK) и D11 (DATA). Дефайны пинов указывать не нужно, как и номера пинов при инициализации:
tinyLED strip;Но добавляется настройка скорости SPI:
TLED_SPI_CLOCK
// #define TLED_SPI_CLOCK 8000000По умолчанию стоит 8000000, можно менять как надо. Это всё.
ПРОГРАММИРОВАНИЕ
Тинилед автоматически подцепляет файл с моей реализацией цветовых инструментов и может их использовать. Данные выводятся "потоком", перед началом и после отправки нужно вызвать begin() и end(), если это SPI лента или используется высокий приоритет прерываний. Сам вывод делается при помощи
sendRGB(r,g,b)
или просто send(data)
, где data
- тип данных моей библиотеки. Например можно покрасить ленту в один из стандартных цветов:
// залить 50 ледов жёлтым цветом strip.begin(); for (byte i = 0; i < 50; i++) strip.send(mYellow); strip.end();Или вывести радугу:
const int numleds = 100; strip.begin(); for (int i = 0; i < numleds; i++) strip.send(mWheel8(i * 255 / numleds)); // выводим радугу strip.end();Из дополнительных инструментов есть:
setBrightness(0-255)
- установка яркости всего вывода (отключается дефайном)sendRGBW(r,g,b,w)
- для RGBW ленты (например WS6812)sendBuffer(buf, size)
- выводит буфер типа mData длиной size. Смотри пример tinyled_bufferclear(size)
- гасит указанное количество ледов (там внутри бегин-цикл-енд и всё, просто для удобства сделал)
#include < FastLEDsupport.h> // вкл поддержку FL DEFINE_GRADIENT_PALETTE( heatmap_gp ) { // делаем палитру огня 0, 0, 0, 0, // black 128, 255, 0, 0, // red 224, 255, 255, 0, // bright yellow 255, 255, 255, 255 // full white }; CRGBPalette16 fire_p = heatmap_gp; #define TLED_CHIP LED_WS2812 #define TLED_ORDER ORDER_GRB #define numleds 100 #include < tinyLED.h> tinyLED< 3> strip; void setup() { strip.setBrightness(100); } void loop() { static int count = 0; count += 10; for (int i = 0; i < numleds; i++) strip.send(CRGBtoData(ColorFromPalette(fire_p, inoise8(i * 25, count), 255, LINEARBLEND))); delay(30); }Скетч компилил для тини85, занимает 2 кб Flash (25%) и 73 б (14%) оперативной памяти. Аналогичный скетч с выводом FastLED занимает 4.2 кб Flash (51%) и 450 б (51%) оперативки. Более того, с микроледом длина ленты не влияет на размер кода, вот такие пироги!
((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | ((b & 0b11111000) >> 3)Распаковка для отправки данных на ленту делается так:
loopData[0] = (data & 0b1111100000000000) >> 8; loopData[1] = (data & 0b0000011111100000) >> 3; loopData[2] = (data & 0b0000000000011111) << 3;Далее сжали цвет до одного байта, хранится как RRGGGBBB. "Запаковка" трёх байт r, g и b в один выглядит вот так:
( (r & 0b11000000) | ((g & 0b11100000) >> 2) | (b & 0b11100000) >> 5)Распаковка для отправки данных на ленту делается так:
loopData[0] = data & 0b11000000; loopData[1] = (data & 0b00111000) << 2; loopData[2] = (data & 0b00000111) << 5;Вот и всё! Получилась очень сильная экономия памяти, которая позволяет, например, впихнуть в Arduino Nano почти 2 тысячи светодиодов при разрешении 8 бит, или 1 тысячу при разрешении 16 бит. Круто! =) Алгоритм вывода данных на ленту разработан Egor ‘Nich1con’ Zaharov и обгоняет все существующие библиотеки для работы с лентами, а я в свою очередь дописал лёгкую оболочку по работе с цветовыми пространствами и светодиодными матрицами. Сравнения по весу и скорости с другими библиотеками: Частота обновления (Гц) от количества светодиодов (сравнение с другими библиотеками), включая минимальное время между отправками (40 мкс). microLED работает в режиме MAX_DATA_SPEED - разогнанном протоколе связи (не работает на WS2811!)
Кол-во диодов | FastLED 24-bit | NeoPixel 24-bit | WS2812 24-bit | microLED 24-bit | microLED 16-bit | microLED 8-bit |
---|---|---|---|---|---|---|
8 | 400 | 1818 | 3260 | 4782 | 4420 | 4460 |
16 | 400 | 1264 | 1751 | 2663 | 2437 | 2462 |
50 | 333 | 554 | 589 | 923 | 840 | 848 |
100 | 220 | 301 | 298 | 472 | 428 | 432 |
500 | 60 | 65 | 61 | 96 | 87 | 88 |
Память | FastLED 24-bit | NeoPixel 24-bit | WS2812 24-bit | microLED 24-bit | microLED 16-bit | microLED 8-bit |
---|---|---|---|---|---|---|
Flash | 2786 | 1984 | 946 | 306 | 346 | 324 |
SRAM | 90+3*LED | 40+3*LED | 31+3*LED | 20+3*LED | 20+2*LED | 20+1*LED |
// шаблон: < количество, пин, чип, порядок, прерывания, миллис> // инициализация ЛЕНТА: нет аргументов microLED; // инициализация МАТРИЦА: ширина матрицы, высота матрицы, тип матрицы, угол подключения, направление (см. ПОДКЛЮЧЕНИЕ МАТРИЦЫ) microLED(uint8_t width, uint8_t height, M_type type, M_connection conn, M_dir dir); // лента и матрица void set(int n, mData color); // ставим цвет светодиода mData (равносильно leds[n] = color) mData get(int num);// получить цвет диода в mData (равносильно leds[n]) void fill(mData color); // заливка цветом mData void fill(int from, int to, mData color);// заливка цветом mData void fillGradient(int from, int to, mData color1, mData color2); // залить градиентом двух цветов void fade(int num, byte val); // уменьшить яркость // матрица uint16_t getPixNumber(int x, int y); // получить номер пикселя в ленте по координатам void set(int x, int y, mData color); // ставим цвет пикселя x y в mData mData get(int x, int y);// получить цвет пикселя в mData void fade(int x, int y, byte val);// уменьшить яркость void drawBitmap8(int X, int Y, const uint8_t *frame, int width, int height); // вывод битмапа (битмап 1мерный PROGMEM) void drawBitmap16(int X, int Y, const uint16_t *frame, int width, int height); // вывод битмапа (битмап 1мерный PROGMEM) void drawBitmap32(int X, int Y, const uint32_t *frame, int width, int height); // вывод битмапа (битмап 1мерный PROGMEM) // общее void setMaxCurrent(int ma);// установить максимальный ток (автокоррекция яркости). 0 - выключено void setBrightness(uint8_t newBright); // яркость 0-255 void clear(); // очистка // вывод буфера void show(); // вывести весь буфер // вывод потока void begin(); // начать вывод потоком void send(mData data); // отправить один светодиод void end();// закончить вывод потоком // цвет uint32_t getHEX(mData data); // перепаковать в 24 бит HEX mData getFade(mData data, uint8_t val); // уменьшить яркость на val mData getBlend(int x, int amount, mData c0, mData c1); // получить промежуточный цвет mData mRGB(uint8_t r, uint8_t g, uint8_t b); // RGB 255, 255, 255 mData mWheel(int color, uint8_t bright=255); // цвета 0-1530 + яркость mData mWheel8(uint8_t color, uint8_t bright=255); // цвета 0-255 + яркость mData mHEX(uint32_t color); // mHEX цвет mData mHSV(uint8_t h, uint8_t s, uint8_t v); // HSV 255, 255, 255 mData mHSVfast(uint8_t h, uint8_t s, uint8_t v); // HSV 255, 255, 255 mData mKelvin(int kelvin); // температура // макросы уменьшения яркости fade8(x, b) fade8R(x, b) fade8G(x, b) fade8B(x, b) // упаковка-распаковка getR(x) getG(x) getB(x) mergeRGB(r,g,b) mergeRGBraw(r,g,b) getCRT(byte x) - получить скорректированное значение яркости x с учётом выбранной модели CRT гамма-коррекции getCRT_PGM(byte x) - получить CRT из прогмем (работает только если выбрана PGM модель) getCRT_SQUARE(byte x) - получить CRT по квадратной модели getCRT_QUBIC(byte x) - получить CRT по кубической модели RGB24to16(x) - конвертация 24-бит цвета в 16-бит RGB24to8(x) - конвертация 24-бит цвета в 8-бит RGB16to24(x) - конвертация 16-бит цвета в 24-бит RGB8to24(x) - конвертация 8-бит цвета в 24-бит RGB24toR(x) - вытащить байт R из 24-бит цвета RGB24toG(x) - вытащить байт G из 24-бит цвета RGB24toB(x) - вытащить байт B из 24-бит цвета RGBto24(r,g,b) - склеить 24-бит цвет RGBto16(r,g,b) - склеить 16-бит цвет RGBto8(r,g,b) - склеить 8-бит цвет
ПРИМЕРЫ
Остальные примеры смотри в папке examples библиотеки, также примеры можно открыть из Arduino IDE/Файл/Примеры
// базовый пример работы с лентой, основные возможности // библиотека microLED версии 3.0+ // для более подробной информации читай документацию // константы для удобства #define STRIP_PIN 2 // пин ленты #define NUMLEDS 20 // кол-во светодиодов // ===== ЦВЕТОВАЯ ГЛУБИНА ===== // 1, 2, 3 (байт на цвет) // на меньшем цветовом разрешении скетч будет занимать в разы меньше места, // но уменьшится и количество оттенков и уровней яркости! // дефайн делается ДО ПОДКЛЮЧЕНИЯ БИБЛИОТЕКИ // без него будет 3 байта по умолчанию #define COLOR_DEBTH 3 #include <microLED.h> // подключаем библу // ======= ИНИЦИАЛИЗАЦИЯ ======= // <колво-ледов, пин, клок пин, чип, порядок> // microLED<NUMLEDS, DATA_PIN, CLOCK_PIN, LED_WS2818, ORDER_GRB> strip; // CLOCK пин нужен только для SPI лент (например APA102) // для обычных WS лент указываем MLED_NO_CLOCK // по APA102 смотри отдельный гайд в примерах // различные китайские подделки могут иметь совместимость // с одним чипом, но другой порядок цветов! // поддерживаемые чипы лент и их официальный порядок цветов: // microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2811, ORDER_GBR> strip; // microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2812, ORDER_GRB> strip; // microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2813, ORDER_GRB> strip; // microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2815, ORDER_GRB> strip; // microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2818, ORDER_RGB> strip; // microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS6812, ORDER_RGB> strip; // microLED<NUMLEDS, STRIP_PIN, CLOCK_PIN, LED_APA102, ORDER_BGR> strip; // microLED<NUMLEDS, MLED_NO_CLOCK, MLED_NO_CLOCK, LED_APA102_SPI, ORDER_BGR> strip; // для аппаратного SPI // ======= ПРЕРЫВАНИЯ ======= // для повышения надёжности передачи данных на ленту можно отключать прерывания. // В библиотеке есть 4 режима: // CLI_OFF - прерывания не отключаются (возможны сбои в работе ленты) // CLI_LOW - прерывания отключаются на время передачи одного цвета // CLI_AVER - прерывания отключаются на время передачи одного светодиода (3 цвета) // CLI_HIGH - прерывания отключаются на время передачи даных на всю ленту // По умолчанию отключение прерываний стоит на CLI_OFF (не отключаются) // Параметр передаётся 5ым при инициализации: // microLED<NUMLEDS, STRIP_PIN, LED_WS2818, ORDER_GRB, CLI_AVER> strip; // ======= СПАСИТЕ МИЛЛИС ======= // При отключении прерываний в режиме среднего и высокого проритета (CLI_AVER и CLI_HIGH) // неизбежно будут чуть отставать функции времени millis() и micros() // В библиотеке встроено обслуживание функций времени, для активации передаём SAVE_MILLIS // 6-ым аргументом при инициализации: // microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2818, ORDER_GRB, CLI_AVER, SAVE_MILLIS> strip; // это НЕЗНАЧИТЕЛЬНО замедлит вывод на ленту, но позволит миллису считать без отставания! // инициализирую ленту (выше был гайд!) microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2818, ORDER_GRB, CLI_AVER> strip; void setup() { // ===================== БАЗОВЫЕ ШТУКИ ===================== // яркость (0-255) strip.setBrightness(60); // яркость применяется по CRT гамме // применяется при выводе .show() ! // очистка буфера (выключить диоды, чёрный цвет) strip.clear(); // применяется при выводе .show() ! strip.show(); // вывод изменений на ленту delay(1); // между вызовами show должна быть пауза минимум 40 мкс !!!! // ===================== УСТАНОВКА ЦВЕТА ===================== // Библиотека поддерживает два варианта работы с лентой: // изменение цвета конкретного диода при помощи функции set(диод, цвет) // или работа с массивом .leds[] "вручную" // запись strip.set(диод, цвет); равносильна strip.leds[диод] = цвет; // ------------- ОСНОВНЫЕ ФУНКЦИИ РАБОТЫ С ЦВЕТОМ ------------ // указанные ниже функции врзвращают тип данных mData - сжатое представление цвета // mRGB(uint8_t r, uint8_t g, uint8_t b); // цвет RGB, 0-255 каждый канал strip.set(0, mRGB(255, 0, 0)); // диод 0, цвет RGB (255 0 0) (красный) // mHSV(uint8_t h, uint8_t s, uint8_t v); // цвет HSV, 0-255 каждый канал strip.leds[1] = mHSV(30, 255, 255); // диод 1, (цвет 30, яркость и насыщенность максимум) // mHSVfast(uint8_t h, uint8_t s, uint8_t v); // цвет HSV, 0-255 каждый канал // расчёт выполняется чуть быстрее, но цвета не такие плавные strip.set(2, mHSVfast(90, 255, 255)); // диод 2, цвет 90, яркость и насыщенность максимум // mHEX(uint32_t color); // WEB цвета (0xRRGGBB) strip.set(3, mHEX(0x30B210)); // диод 3, цвет HEX 0x30B210 // в библиотеке есть 17 предустановленных цветов (макс. яркость) strip.leds[4] = mAqua; // диод 4, цвет aqua // mWheel(int color); // цвета радуги 0-1530 // mWheel(int color, uint8_t bright); // цвета радуги 0-1530 + яркость 0-255 strip.set(5, mWheel(1200)); // диод 5, цвет 1200 // mWheel8(int color); // цвета радуги 0-255 // mWheel8(int color, uint8_t bright); // цвета радуги 0-255 + яркость 0-255 //strip.set(6, mWheel8(100)); // диод 6, цвет 100 (диапазон 0-255 вдоль радуги) strip.set(6, mWheel8(100, 50)); // вторым параметром можно передать яркость // mKelvin(int kelvin); // цветовая температура 1'000-40'000 Кельвин strip.set(7, mKelvin(3500)); // диод 7, цветовая температура 3500К strip.show(); // выводим все изменения на ленту delay(2000); // задержка показа // ===================== ЗАЛИВКА ===================== // Есть готовая функция для заливки всей ленты цветом - .fill() // принимает конвертированный цвет, например от функций цвета или констант выше strip.fill(mYellow); // заливаем жёлтым strip.show(); // выводим изменения delay(2000); // также можно указать начало и конец заливки strip.fill(3, 7, mWheel8(100)); // заливаем ~зелёным с 3 по 6: счёт идёт с 0, заливается до указанного -1 strip.show(); // выводим изменения delay(2000); // ------------- РУЧНАЯ ЗАЛИВКА В ЦИКЛЕ ------------ // Например покрасим половину ленты в один, половину в другой for (int i = 0; i < NUMLEDS / 2; i++) strip.leds[i] = mHSV(0, 255, 255); // красный for (int i = NUMLEDS / 2; i < NUMLEDS; i++) strip.leds[i] = mHSV(80, 255, 255); // примерно зелёный strip.show(); // выводим изменения delay(2000); // ------------------------------------------ // Для ускорения ручных заливок (ускорения расчёта цвета) можно создать переменную типа mData mData value1, value2; value1 = mHSV(60, 100, 255); value2 = mHSV(190, 255, 190); for (int i = 0; i < NUMLEDS; i++) { if (i < NUMLEDS / 2) strip.leds[i] = value1; // первая половина ленты else strip.leds[i] = value2; // вторая половина ленты } strip.show(); // выводим изменения delay(2000); // ------------------------------------------ // в цикле можно менять параметры генерации цвета. Например, сделаем радугу for (int i = 0; i < NUMLEDS; i++) strip.set(i, mWheel8(i * 255 / NUMLEDS)); // полный круг от 0 до 255 strip.show(); // выводим изменения delay(2000); // или градиент от красного к чёрному (последовательно меняя яркость) for (int i = 0; i < NUMLEDS; i++) strip.set(i, mWheel8(0, i * 255 / NUMLEDS)); // полный круг от 0 до 255 strip.show(); // выводим изменения } void loop() { }
// пример работы с матрицей 32x8 #define M_PIN 8 // пин матрицы #define M_WIDTH 32 // ширина матрицы #define M_HEIGHT 8 // высота матрицы #define NUM_LEDS (M_WIDTH * M_HEIGHT) // для удобства запомним и количство ледов #include <microLED.h> #include <FastLEDsupport.h> // нужна для шума // инициализация у матрицы такая же, как у ленты, но добавляются параметры в (скобках) microLED<NUM_LEDS, M_PIN, MLED_NO_CLOCK, LED_WS2812, ORDER_GRB, CLI_AVER> matrix(M_WIDTH, M_HEIGHT, ZIGZAG, LEFT_TOP, DIR_DOWN); // тип матрицы: ZIGZAG - зигзаг, PARALLEL - параллельная // угол подключения: LEFT_BOTTOM - левый нижний, LEFT_TOP - левый верхний, RIGHT_TOP - правый верхний, RIGHT_BOTTOM - правый нижний // направление ленты из угла подключения: DIR_RIGHT - вправо, DIR_UP - вверх, DIR_LEFT - влево, DIR_DOWN - вниз // шпаргалка по настройке матрицы в папке docs в библиотеке void setup() { matrix.setBrightness(100); // яркость (0-255) // Проверка ориентации матрицы // Система координат - декартовая первая четверть (левый нижний угол - 0) // Левый нижний угол - жёлтый // Левый верхний - пурпурный // Правый нижний - голубой // для установки пикселя используем set(x, y, цвет) // всё остальное - так же как у ленты!!! matrix.set(0, 0, mYellow); matrix.set(0, 7, mPurple); matrix.set(7, 0, mTeal); matrix.show(); delay(3000); matrix.clear(); } void loop() { // примеры эффектов rainbow2D(); //fire2D(); //fire2D(); //rainbow(); // горизонтальная радуга //balls(); // шарики //confetti(); matrix.show(); delay(30); } // =========== РАДУГА =========== void rainbow() { static byte hue = 0; hue += 5; for (int i = 0; i < M_WIDTH; i++) { for (int j = 0; j < M_HEIGHT; j++) matrix.set(i, j, mWheel8(hue + i * 255 / M_WIDTH)); } } // =========== ШАРИКИ =========== #define BALLS_AMOUNT 5 boolean loadingFlag = true; int coord[BALLS_AMOUNT][2]; int8_t vector[BALLS_AMOUNT][2]; mData ballColors[BALLS_AMOUNT]; void balls() { if (loadingFlag) { loadingFlag = false; for (byte j = 0; j < BALLS_AMOUNT; j++) { int sign; // забиваем случайными данными coord[j][0] = M_WIDTH / 2 * 10; random8(0, 2) ? sign = 1 : sign = -1; vector[j][0] = random8(4, 15) * sign; coord[j][1] = M_HEIGHT / 2 * 10; random8(0, 2) ? sign = 1 : sign = -1; vector[j][1] = random8(4, 15) * sign; ballColors[j] = mWheel8(random8(0, 9) * 28); } } matrix.clear(); // очистить // движение шариков for (byte j = 0; j < BALLS_AMOUNT; j++) { for (byte i = 0; i < 2; i++) { coord[j][i] += vector[j][i]; if (coord[j][i] < 0) { coord[j][i] = 0; vector[j][i] = -vector[j][i]; } } if (coord[j][0] > (M_WIDTH - 1) * 10) { coord[j][0] = (M_WIDTH - 1) * 10; vector[j][0] = -vector[j][0]; } if (coord[j][1] > (M_HEIGHT - 1) * 10) { coord[j][1] = (M_HEIGHT - 1) * 10; vector[j][1] = -vector[j][1]; } matrix.set(coord[j][0] / 10, coord[j][1] / 10, ballColors[j]); } } // =========== КОНФЕТТИ =========== void confetti() { for (int i = 0; i < NUM_LEDS; i++) { if (matrix.get(i) == 0) if (random8(0, 100) == 0) matrix.set(i, mWheel8(random8())); matrix.fade(i, 30); } } // =========== ОГОНЬ =========== mGradient<4> myGrad; boolean loadingFlag2 = true; void fire2D() { static int count = 0; if (loadingFlag2) { loadingFlag2 = false; // заполняем палитру myGrad.colors[0] = mBlack; myGrad.colors[1] = mRed; myGrad.colors[2] = mYellow; myGrad.colors[3] = mWhite; } for (int i = 0; i < M_WIDTH; i++) for (int j = 0; j < M_HEIGHT; j++) matrix.set(i, j, myGrad.get(inoise8(i * 50, j * 50, count), 255)); count += 20; } // =========== РАДУЖНЫЕ ШТУКИ =========== void rainbow2D() { static int count = 0; static byte count2 = 0; for (int i = 0; i < M_WIDTH; i++) for (int j = 0; j < M_HEIGHT; j++) matrix.set(i, j, mWheel8(count2 + inoise8(i * 50, j * 50, count), 255)); count += 20; count2++; }
// При помощи CRGBtoData() можно конвертировать CRGB в mDATA! // Используем быструю математику FastLED и компактный вывод microLED // для достижения максимума каефа при минимуме занятой памяти #define LEDPIN 2 #include <microLED.h> #include <FastLEDsupport.h> // вкл поддержку microLED<0, LEDPIN, MLED_NO_CLOCK, LED_WS2818, ORDER_GRB, CLI_AVER> strip; void setup() { strip.setBrightness(150); } void loop() { static byte count = 0; static int count2 = 0; count++; count2 += 10; strip.begin(); for (int i = 0; i < 50; i++) { // движется палитра полосатая //strip.send(CRGBtoData(ColorFromPalette(RainbowStripeColors_p, count + i * 3, 255, LINEARBLEND))); // рандомный шум радугой strip.send(CRGBtoData(ColorFromPalette(RainbowColors_p, inoise8(i * 20, count2), 255, LINEARBLEND))); } strip.end(); delay(40); } /* // =========== ТО ЖЕ САМОЕ ДЛЯ ТИНИЛЕД ========== #define TLED_PORT PORTD // выводил на Нанку, портД (пин D3) #define TLED_DDR DDRD #include <tinyLED.h> #include <FastLEDsupport.h> tinyLED<3> strip; void setup() { strip.setBrightness(100); } void loop() { static byte count = 0; static int count2 = 0; count++; count2 += 10; for (int i = 0; i < 50; i++) { // движется палитра полосатая //strip.send(CRGBtoData(ColorFromPalette(RainbowStripeColors_p, count + i * 3, 255, LINEARBLEND))); // рандомный шум радугой strip.send(CRGBtoData(ColorFromPalette(RainbowColors_p, inoise8(i * 20, count2), 255, LINEARBLEND))); } delay(40); } */
// пример с tinyLED, должно работать на всех тиньках и мегах // дефайны настроек, прописываются перед подключением либы #define TLED_ORDER ORDER_GRB // порядок цветов #define TLED_CHIP LED_WS2812 // чип светодиода ленты /* Доступные модели лент и их порядок цветов Китайцы могут продавать копию с другим порядком =) LED_WS2811 // ORDER_GBR LED_WS2812 // ORDER_GRB LED_WS2813 // ORDER_GRB LED_WS2815 // ORDER_GRB LED_WS2818 // ORDER_RGB LED_WS6812 // ORDER_RGB + W LED_APA102 // ORDER_BGR LED_APA102_SPI // ORDER_BGR */ // ===== 1 пин ленты ===== // по умолч. PORTB // можно указать свой порт, если у тиньки больше 8 ног или это вообще атмега // пин указывается при создании // #define TLED_PORT PORTB // #define TLED_DDR DDRB // ===== 2 пин SPI ленты ===== // программный SPI, например LED_APA102 // по умолч. PORTB // можно указать свой порт, если у тиньки больше 8 ног или это вообще атмега // пин указывается при создании // #define TLED_CLK_PORT PORTB // #define TLED_CLK_DDR DDRB // #define TLED_DAT_PORT PORTB // #define TLED_DAT_DDR DDRB // ===== Запрет прерываний ===== // можно указать приоритет прерываний (умолч CLI_LOW): // #define TLED_CLI CLI_OFF // прерывания не запрещаются // #define TLED_CLI CLI_LOW // запрещаются на время передачи байта // #define TLED_CLI CLI_AVER // запрещаются на время передачи светодиода (3 байта) // #define TLED_CLI CLI_HIGH // запрещаются на время передачи всей ленты // ===== Яркость ===== // #define TLED_STATIC_BRIGHT // отключает изменение общей яркости вывода и экономит 60 байт флэш // ===== SPI лента ===== // только при выборе LED_APA102_SPI // пины не указываются в скетче // #define TLED_SPI_CLOCK 8000000 // скорость аппаратного SPI для ленты LED_APA102_SPI // либа #include "tinyLED.h" tinyLED<3> strip; // указываем пин (в порядке порта) // tinyLED<3, 4> strip; // <DATA, CLOCK> для 2-пин лент (APA102) // tinyLED strip; // для LED_APA102_SPI не указываем пины ВООБЩЕ! #define NUMLEDS 50 // количество светодиодов (для циклов) void setup() { // begin() - начать отправку (НУЖНО ТОЛЬКО ДЛЯ SPI ЛЕНТ ИЛИ CLI_HIGH) // end() - закончить отправку (НУЖНО ТОЛЬКО ДЛЯ SPI ЛЕНТ ИЛИ CLI_HIGH) // write() - отправить один байт // sendRGB(r,g,b) - отправить цвет на 1 диод // sendRGBW(r,g,b,w) - отправить на rgbw ленту (например WS6812) // send(mData) - отправить цвет в формате mData // sendBuffer(mData буфер, размер) - отправить внешний буфер на ленту // clear(размер) - очистить на длину // setBrightness(0-255) - яркость для всего вывода // каждый вывод "задвигает" указанный цвет // чтобы остановить вывод - перестаём вызывать функцию на 50-300 мкс (зависит от чипа) // ================================================= //strip.begin(); strip.sendRGB(255, 255, 255); // отправить r,g,b на первый лед strip.send(mOrange); // отправить оранжевый strip.send(mAqua); // голубой strip.send(mPurple); // и розовый //strip.end(); // леды загорятся вот так: // начало--розовый--аква--оранж--белый delay(5000); // пауза // ================================================= // зальём 50 ледов белым. Вывод начнётся с начала!! //strip.begin(); for (byte i = 0; i < 10; i++) strip.send(mYellow); //strip.end(); delay(5000); // пауза // ================================================= // зальём 50 ледов с чередованием жёлтый-чёрный //strip.begin(); for (byte i = 0; i < 50; i++) { strip.send(i % 2 == 0 ? mYellow : mBlack); } //strip.end(); delay(5000); // пауза } void loop() { // ================================================= // иииии бегущая радуга! static byte count; count++; //strip.begin(); for (int i = 0; i < NUMLEDS; i++) { strip.send(mWheel8(count + i * 255 / NUMLEDS)); // выводим радугу } //strip.end(); delay(30); }
// пример работы с лентой без буфера #define STRIP_PIN 2 // пин ленты #define NUMLEDS 20 // кол-во светодиодов #include <microLED.h> // количество светодиодов указываем 0 microLED<0, STRIP_PIN, MLED_NO_CLOCK, LED_WS2818, ORDER_GRB, CLI_AVER> strip; #include <FastLEDsupport.h> // нужна для шума void setup() { strip.setBrightness(150); // алгоритм вывода такой: // strip.begin(); // strip.send(цвет); // strip.send(цвет); // .......... // strip.end(); // функция send(цвет) загружает следующий цвет в ленту // при каждом новом вызове цвет передаётся "паравозиком" по ленте, // таким образом можно выводить на ленту любой длины. // Между вызовами send() должно пройти МЕНЬШЕ 50 мкс (для 2812), иначе вывод будет прерван // Это усложняет генерацию эффектов "на лету", потому что для некоторых банально не хватит скорости вычисления strip.begin(); for (int i = 0; i < NUMLEDS; i++) { strip.send(mWheel8(i * 255 / NUMLEDS)); // выводим радугу } strip.end(); delay(2000); } void loop() { // а тут давайте запустим генерацию гармонического шума по палитре радуги с дополнительным смещением спектра static int counter = 0; static byte counter2 = 0; counter += 10; counter2++; strip.begin(); for (int i = 0; i < NUMLEDS; i++) strip.send(mWheel8(counter2 + inoise8(i * 50, counter))); strip.end(); delay(30); // скорости достаточно! Эффект работает }
ПОДДЕРЖАТЬ
Вы можете поддержать меня за создание доступных проектов с открытым исходным кодом, полный список реквизитов есть вот здесь.