ОБНОВЛЕНИЯ
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_MILLIS6-ым аргументом при инициализации: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доtofillGradient(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)- включит указанный пиксель указанным цветом в форматеmDataget(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);
// скорости достаточно! Эффект работает
}
ПОДДЕРЖАТЬ
Вы можете поддержать меня за создание доступных проектов с открытым исходным кодом, полный список реквизитов есть вот здесь.
![Связь нескольких Arduino по проводу [GyverBus]](https://alexgyver.ru/wp-content/uploads/2021/06/gyverBUS.jpg)


