|
|
(не показано 7 промежуточных версий 2 участников) |
Строка 1: |
Строка 1: |
| СТАТЬЯ НАХОДИТСЯ В СТАДИИ РАЗРАБОТКИ
| | {{DISPLAYTITLE:Подключение адресной ленты WS2812B к контроллеру Wiren Board}} |
| | ==Описание== |
| | {{Wbincludes:Community}} |
|
| |
|
| =Управление адресной лентой WS2812B из Wirenboard=
| | Автор статьи: [https://t.me/Paulstrong Paul Strong] |
| здесь будет рассмотрен один из способов управления адресной лентой WS2812B из Wirenboard с использованием ESP32.
| |
|
| |
|
| здесь не будут рассмотрены характеристики железной части, этому уделено очень много внимания на просторах Интернет, тут будет сугубо техническая информация по процессу достижения цели, с небольшими лирическими отступлениями.
| | В этой статье рассмотрим один из способов управления адресной лентой WS2812B из Wiren Board с использованием ESP32. |
|
| |
|
| ==Что нам понадобится==
| | Здесь не будут рассмотрены характеристики железной части, этому уделено очень много внимания на просторах Интернет, тут будет сугубо техническая информация по процессу достижения цели, с небольшими лирическими отступлениями. |
| * любая отладочная плата, основанная на esp32 | | |
| * две bread board платы | | Что нам понадобится: |
| * соединительные проводки | | * любая отладочная плата, основанная на esp32; |
| * лента ws2812b нужной длины (в моём случае бухта 5м с мощностью 14.4Вт/м) | | * две bread board платы; |
| * блок питания 5V соответствующей мощности (в моём случае 100W) | | * соединительные проводки; |
| * резистор 220 ом | | * лента ws2812b нужной длины (в моём случае бухта 5м с мощностью 14.4Вт/м); |
| * microUSB дата-кабель (обычный, от зарядки, может не подойти!) | | * блок питания 5V соответствующей мощности (в моём случае 100W); |
| * комп/ноут для сборки и заливки прошивки | | * резистор 220 ом; |
| * VSCode + PlatformIO | | * microUSB дата-кабель (обычный, от зарядки, может не подойти!); |
| * контроллер Wirenboard с wb-rules v2.x | | * комп/ноут для сборки и заливки прошивки; |
| * wi-fi сеть в диапазоне 2.4G | | * VSCode + PlatformIO; |
| | * контроллер Wirenboard с wb-rules v2.x; |
| | * wi-fi сеть в диапазоне 2.4G. |
|
| |
|
| ==Сборка физической схемы== | | ==Сборка физической схемы== |
| | [[Файл:Ws2812b_BB_Schema.png|thumb|right|600px| Схема сборки]] |
| Для сборки нам нужно две bread board платы, собираем по схеме: | | Для сборки нам нужно две bread board платы, собираем по схеме: |
|
| |
| [[Файл:Ws2812b_BB_Schema.png|600px]]
| |
| * пин 5V подключаем к +5V ленты | | * пин 5V подключаем к +5V ленты |
| * пин GND | | * пин GND |
| * пинг GPIO27 подключаем через резистор 220ом к DIN ленты | | * пинг GPIO27 подключаем через резистор 220ом к DIN ленты |
|
| |
|
| Обращаю внимание на то, что не рекомендуется тестировать конфигурацию более чем на 5 светодиодах, такого количества будет достаточно, чтобы понять как выглядит световая картинка в том или ином алгоритме. Подключение большего количества светодиодов может привести к выгоранию USB-порта на компе, т.к. там обычно предельно допустимый ток 350мА, а один светодиод на такой ленте потребляет около 50мА. | | Обращаю внимание на то, что не рекомендуется тестировать конфигурацию более чем на 5 светодиодах, такого количества будет достаточно, чтобы понять как выглядит световая картинка в том или ином алгоритме. |
| | |
| | Подключение большего количества светодиодов может привести к выгоранию USB-порта на компьютере, т.к. там обычно предельно допустимый ток 350мА, а один светодиод на такой ленте потребляет около 50мА. |
|
| |
|
| ==Первый скетч== | | ==Первый скетч== |
| Заливаем первую прошивку. | | Заливаем первую прошивку. |
|
| |
|
| Подразумевается что на PC уже установлена среда разработки VSCode и расширение PlatformIO. Создадим новый проект. | | Подразумевается что на компьютере уже установлена среда разработки VSCode и расширение PlatformIO. Создадим новый проект. |
|
| |
|
| [[Файл:Pio-create-prj.jpg]] | | [[Файл:Pio-create-prj.jpg]] |
|
| |
|
| закодим src/main.cpp, чтобы понимать, что esp32 работает, сделаем код, который постоянно зажигает и тушит встроенный светодиод синего цвета.
| | Чтобы понимать, что esp32 работает, сделаем код, который постоянно зажигает и тушит встроенный светодиод синего цвета. Запускаем это дело в виде асинхронной функции. |
| | |
| запускаем это дело в виде асинхронной функции.
| |
|
| |
|
| | Файл <code>src/main.cpp</code>: |
| <syntaxhighlight lang="c++"> | | <syntaxhighlight lang="c++"> |
| #include <Arduino.h> | | #include <Arduino.h> |
Строка 87: |
Строка 90: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| сейчас можно залить попробовать скомпилировать прошивку, для этого в нижней панели жмём кнопку [[Файл:Снимок экрана 2023-12-06 205145.jpg]]
| | Сейчас можно залить попробовать скомпилировать прошивку, для этого в нижней панели жмём кнопку [[Файл:Снимок экрана 2023-12-06 205145.jpg]] |
|
| |
|
| если всё собралось, только можно шить это дело в esp32:
| | Если всё собралось, только можно шить это дело в esp32: |
| * подключаем esp32 к компу при помощи microUSB data кабеля | | * подключаем esp32 к компу при помощи microUSB data кабеля; |
| * инициируем заливку прошивки при помощи кнопки [[Файл:Снимок экрана 2023-12-06 205336.jpg]], когда система напишет "Connecting..." - зажимаем кнопку Boot на dev-плате esp32 | | * инициируем заливку прошивки при помощи кнопки [[Файл:Снимок экрана 2023-12-06 205336.jpg]], когда система напишет «Connecting...» — зажимаем кнопку Boot на dev-плате esp32; |
| * если прошивка залилась успешно, перезагружаем esp32 соответствующей кнопкой, после этого у вас должен замигать синий светодиод на плате | | * если прошивка залилась успешно, перезагружаем esp32 соответствующей кнопкой, после этого у вас должен замигать синий светодиод на плате. |
|
| |
|
| ==Подключаемся к wifi== | | ==Подключаемся к Wi-Fi== |
| Приступаем к следующему этапу - нам нужно подключить нашу esp32 к wifi (чтобы далее подключиться к modbus tcp от wirenboard) | | Приступаем к следующему этапу — нам нужно подключить нашу esp32 к wifi (чтобы далее подключиться к modbus tcp от wirenboard) |
|
| |
|
| добавим к нашему файлу main.cpp следующий код:
| | Добавим к нашему файлу main.cpp следующий код: |
| <syntaxhighlight lang="c++"> | | <syntaxhighlight lang="c++"> |
| #include <Arduino.h> | | #include <Arduino.h> |
Строка 138: |
Строка 141: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| теперь после прошивки esp32 подключится к вашей wifi сети, IP-адрес можно будет посмотреть на роутере, либо в отладочных сообщения на Serial-порте, который связывает ваш комп с esp32, для этого нажмите кнопку [[Файл:Снимок экрана 2023-12-06 210510.jpg]] на нижней панели
| | Теперь после прошивки esp32 подключится к вашей wifi сети, IP-адрес можно будет посмотреть на роутере, либо в отладочных сообщения на Serial-порте, который связывает ваш комп с esp32, для этого нажмите кнопку [[Файл:Снимок экрана 2023-12-06 210510.jpg]] на нижней панели. |
|
| |
|
| ==Библиотека для работы с адресной лентой== | | ==Библиотека для работы с адресной лентой== |
|
| |
|
| Далее нам нужно подключить к проекту библиотеку для работы с лентой, они есть разные, я использовал FastLED | | Далее нам нужно подключить к проекту библиотеку для работы с лентой, они есть разные, я использовал FastLED. |
|
| |
|
| [[Файл:Снимок экрана 2023-12-06 201634.jpg]] | | [[Файл:Снимок экрана 2023-12-06 201634.jpg]] |
|
| |
|
| добавляем в проект
| | Добавляем в проект |
|
| |
|
| [[Файл:Снимок экрана 2023-12-06 203931.jpg]] | | [[Файл:Снимок экрана 2023-12-06 203931.jpg]] |
Строка 349: |
Строка 352: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| прошиваемся, в случае успеха у вас должна заработать лента, алгоритм будет менять каждые 5 секунд, всего 12 алгоритмов
| | Прошиваемся, в случае успеха у вас должна заработать лента, алгоритм будет менять каждые 5 секунд, всего 12 алгоритмов. |
|
| |
|
| Подробно останавливаться на коде прошивки мы не будем, в Интернете полно разных алгоритмов, их можно добавлять к нашей оснастке, переключать их реже или чаще, можно даже кнопку прикрутить под это дело на один из пинов, тут кому насколько фантазии хватит. | | Подробно останавливаться на коде прошивки мы не будем, в Интернете полно разных алгоритмов, их можно добавлять к нашей оснастке, переключать их реже или чаще, можно даже кнопку прикрутить под это дело на один из пинов, тут кому насколько фантазии хватит. |
|
| |
|
| ==Подключение к Modbus TCP== | | ==Подключение к Modbus TCP== |
| После настройки wifi мы можем подключаться к mqtt-брокеру wirenboard, для этого нужно установить библиотеку, как мы это делали ранее, называется она PubSubClient | | После настройки Wi-Fi мы можем подключаться к mqtt-брокеру контроллера Wiren Board, для этого нужно установить библиотеку, как мы это делали ранее, называется она PubSubClient. |
|
| |
|
| подключимся к брокеру, для этого добавим немного кода:
| | Подключимся к брокеру, для этого добавим немного кода: |
| <syntaxhighlight lang="c++"> | | <syntaxhighlight lang="c++"> |
| #include <Arduino.h> | | #include <Arduino.h> |
Строка 430: |
Строка 433: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| что мы здесь видим: мы можем создавать подписку на нужные топики либо сами публиковать какие то значения в нужные нам топики.
| | Что мы здесь видим: мы можем создавать подписку на нужные топики либо сами публиковать какие то значения в нужные нам топики. |
|
| |
|
| в нашем случае понадобится управлять настройками ленты, поэтому нам надо слушать некоторые топики, изменения которых будут влиять на поведение ленты, допустим, мы хотим управлять:
| | В нашем случае понадобится управлять настройками ленты, поэтому нам надо слушать некоторые топики, изменения которых будут влиять на поведение ленты, допустим, мы хотим управлять: |
| - яркостью
| | * яркостью |
| - выключать (яркость 0)
| | * выключать (яркость 0) |
| - включать (яркость 50%)
| | * включать (яркость 50%) |
| - останавливать и запускать автоматическую смену режима
| | * останавливать и запускать автоматическую смену режима |
|
| |
|
| ==Виртуальное устройство в Wirenboard== | | ==Виртуальное устройство в Wiren Board== |
| Создадим виртуальное устройство нашей ленты в wirenboard: | | Создадим на [[wb-rules]] виртуальное устройство нашей ленты в контроллере Wiren Board: |
| <syntaxhighlight lang="javascript"> | | <syntaxhighlight lang="javascript"> |
| defineVirtualDevice("ws2812b", { | | defineVirtualDevice("ws2812b", { |
Строка 477: |
Строка 480: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| теперь надо константу BRIGHTNESS переделать в переменную, ввести переменную hue_loop, а также подписаться на топики
| | Теперь надо константу BRIGHTNESS переделать в переменную, ввести переменную hue_loop, а также подписаться на топики |
| <syntaxhighlight lang="c++"> | | <syntaxhighlight lang="c++"> |
| #define BRIGHTNESS 50 | | #define BRIGHTNESS 50 |
Строка 541: |
Строка 544: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| Теперь можно управлять runtime-переменными esp32 через wirenboard | | Теперь можно управлять runtime-переменными esp32 через Wiren Board. |
|
| |
|
| [[Файл:Снимок экрана 2023-12-07 095833.jpg]] | | [[Файл:Снимок экрана 2023-12-07 095833.jpg]] |
Строка 591: |
Строка 594: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| теперь нам её придётся сделать обычной переменной:
| | Теперь нам её придётся сделать обычной переменной: |
| <syntaxhighlight lang="c++"> | | <syntaxhighlight lang="c++"> |
| int UPDATES_PER_SECOND = 500; | | int UPDATES_PER_SECOND = 500; |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| теперь нужно подписать на новый топик:
| | Теперь нужно подписать на новый топик: |
| <syntaxhighlight lang="c++"> | | <syntaxhighlight lang="c++"> |
| void modbusCallback(char* topic, byte* payload, unsigned int length) { | | void modbusCallback(char* topic, byte* payload, unsigned int length) { |
Строка 652: |
Строка 655: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| заливаем прошивку в esp32.
| | Заливаем прошивку в esp32. |
|
| |
|
| осталось обновить виртуальное устройство в wirenboard:
| | Осталось обновить виртуальное устройство в контроллере Wiren Board: |
| <syntaxhighlight lang="javascript"> | | <syntaxhighlight lang="javascript"> |
| defineVirtualDevice("ws2812b", { | | defineVirtualDevice("ws2812b", { |
Строка 687: |
Строка 690: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| после применения виртуального устройства можно управлять скорость обновления светодиодов из интерфейса wirenboard.
| | После применения виртуального устройства можно управлять скорость обновления светодиодов из веб-интерфейса контроллера Wiren Board. |
| | |
| ==Какие могут быть проблемы==
| |
| # изначально лента тестировалась на arduino nano, и на LED_TYPE==WS2812B оно работало странно, но с учетом того что какие-то отдельные светодиоды загорались, я пришёл к выводу что цифра работает, но есть какие-то проблемы с частотой, в итоге заработало на WS2811_400, то есть на частоте 400кгц, однако, в случае с esp32 всё заработало со штатным типом WS2812B
| |
| # важно учитывать тот факт, что нельзя допускать подключения ленты без стабильного плюса, то есть в случае подключения ленты к GND и DIN-пину, есть риск, что пин спалится, чтобы подстраховаться - ставится резистор на 220ом, но всё равно лучше избегать таких вот нештатных ситуаций
| |
| # на самом деле проблемы могут быть самые разнообразные, потому что это DIY, если что пишите в чатике - попробуем разобраться
| |
| | |
| | |
| | |
| ==Финальный код скетча==
| |
| <syntaxhighlight lang="c++">
| |
| #include <Arduino.h>
| |
| #include <FastLED.h>
| |
| #include <PubSubClient.h>
| |
| #include <WiFiClient.h>
| |
| #include <WiFi.h>
| |
| #include <ESPAsyncWebServer.h>
| |
| #include <AsyncTCP.h>
| |
| #include <ESPAsyncWebServer.h>
| |
| #include <AsyncElegantOTA.h>
| |
|
| |
|
| | ==Паяем на плату== |
|
| |
|
| | Понадобится: |
| | * макетная плата размером 40х60; |
| | * две винтовые клеммы на 2 и 3 контакта; |
| | * паяльник 40Вт с тонким жалом; |
| | * припой с флюсом. |
|
| |
|
| unsigned long ota_progress_millis = 0;
| | [[Image: Photo 2023-12-22 17-04-06.jpg |300px ]] |
| AsyncWebServer server(80);
| |
| void setupOTA(void) {
| |
| server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
| |
| request->send(200, "text/plain", "Hi! This is a sample response.");
| |
| });
| |
|
| |
|
| AsyncElegantOTA.begin(&server); // Start AsyncElegantOTA
| | Девборд в длину занимает почти всю плату - остаётся один ряд, поэтому решил клеммы разместить сбоку |
| server.begin();
| |
| Serial.println("HTTP server started");
| |
| }
| |
|
| |
|
| | [[Image: Photo 2023-12-22 17-04-07.jpg |300px ]] |
|
| |
|
| #define WIFI_SSID "ssid"
| | Клеммы соединяем через пазы |
| #define WIFI_PASSWORD "pass"
| |
| void setupWifi() {
| |
| WiFi.mode(WIFI_STA);
| |
| WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
| |
| char emptyMsg[1] = "";
| |
| char pointMsg[2] = ".";
| |
| Serial.println(emptyMsg);
| |
| // Wait for connection
| |
| while (WiFi.status() != WL_CONNECTED) {
| |
| delay(500);
| |
| Serial.println(pointMsg);
| |
| }
| |
| Serial.println(emptyMsg);
| |
| char connectedToMsg[14] = "Connected to ";
| |
| Serial.println(connectedToMsg);
| |
| Serial.println(WIFI_SSID);
| |
| char ipAddrMsg[30];
| |
| sprintf(ipAddrMsg, "IP address: %s", WiFi.localIP().toString().c_str());
| |
| Serial.println(ipAddrMsg);
| |
| }
| |
|
| |
|
| | [[Image: Photo 2023-12-22 17-04-06 2.jpg |300px ]] |
|
| |
|
| | Припаиваем к шахтам макетной платы все пять пинов от клемм, а также прихватываем крайние пины девборда. Есть важный нюанс - клеммы нужно расположить таким образом, чтобы было минимальное расстояние до нужных пинов девборда |
|
| |
|
| // This example shows several ways to set up and use 'palettes' of colors
| | [[Image: Photo 2023-12-22 17-04-07 (2).jpg |300px ]] |
| // with FastLED.
| |
| //
| |
| // These compact palettes provide an easy way to re-colorize your
| |
| // animation on the fly, quickly, easily, and with low overhead.
| |
| //
| |
| // USING palettes is MUCH simpler in practice than in theory, so first just
| |
| // run this sketch, and watch the pretty lights as you then read through
| |
| // the code. Although this sketch has eight (or more) different color schemes,
| |
| // the entire sketch compiles down to about 6.5K on AVR.
| |
| //
| |
| // FastLED provides a few pre-configured color palettes, and makes it
| |
| // extremely easy to make up your own color schemes with palettes.
| |
| //
| |
| // Some notes on the more abstract 'theory and practice' of
| |
| // FastLED compact palettes are at the bottom of this file.
| |
|
| |
|
| | Клеммы расположены прямо напротив нужных пинов, поэтому нет необходимости соединять проводами, напаял шлейфы из олова, от IO27 до клеммы идут два последовательных резистора по 100ом (какие были), скрутку резисторов приаял к шахте, чтобы не болталось ничего. |
|
| |
|
| #define DIN_PIN 27
| | [[Image: Photo 2023-12-22 17-04-08.jpg |300px ]] |
| #define NUM_LEDS 5
| |
| #define LED_TYPE WS2812B
| |
| #define COLOR_ORDER GRB
| |
| CRGB leds[NUM_LEDS];
| |
|
| |
| int UPDATES_PER_SECOND = 500;
| |
|
| |
|
| uint8_t BRIGHTNESS = 50;
| | Чтобы всё это упаковать, взял распаечную коробку небольшую, но в итоге совсем чуток не вместился туда, пришлось пока что на стяжках к корпусу блока питания закрепить, потом намучу какой-то подходящий корпус и переселю. |
| bool hueLoop = true;
| |
|
| |
|
| CRGBPalette16 currentPalette;
| | [[Image: Photo 2023-12-22 17-04-34.jpg |300px ]] |
| TBlendType currentBlending;
| |
|
| |
| extern CRGBPalette16 myRedWhiteBluePalette;
| |
| extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;
| |
|
| |
| void setupFastLED(){
| |
| delay( 3000 ); // power-up safety delay
| |
| FastLED.addLeds<LED_TYPE, DIN_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
| |
| FastLED.setBrightness( BRIGHTNESS );
| |
|
| |
| currentPalette = RainbowColors_p;
| |
| currentBlending = LINEARBLEND;
| |
| }
| |
|
| |
|
| | ==Какие могут быть проблемы== |
| | # изначально лента тестировалась на arduino nano, и на LED_TYPE==WS2812B оно работало странно, но с учетом того что какие-то отдельные светодиоды загорались, я пришёл к выводу что цифра работает, но есть какие-то проблемы с частотой, в итоге заработало на WS2811_400, то есть на частоте 400кгц, однако, в случае с esp32 всё заработало со штатным типом WS2812B; |
| | # важно учитывать тот факт, что нельзя допускать подключения ленты без стабильного плюса, то есть в случае подключения ленты к GND и DIN-пину, есть риск, что пин спалится, чтобы подстраховаться - ставится резистор на 220ом, но всё равно лучше избегать таких вот нештатных ситуаций; |
| | # на самом деле проблемы могут быть самые разнообразные, потому что это DIY, если что пишите в чатике - попробуем разобраться. |
|
| |
|
| #define MODBUS_SERVER "10.50.0.253"
| | ==Финальный код== |
| #define MODBUS_PORT 1883
| | Исходный код скетча и виртуального устройства на wb-rules смотрите в репозитори на ГитХабе [https://github.com/wirenboard/wb-community/tree/main/firmwares/ws2812b-to-wb ws2812b-to-wb] |
| WiFiClient wifiClient;
| |
| PubSubClient pubSubClient(wifiClient);
| |
| | |
| void modbusCallback(char* topic, byte* payload, unsigned int length) {
| |
| char payloadChar[sizeof(payload)];
| |
| Serial.print("Message arrived [");
| |
| Serial.print(topic);
| |
| Serial.print("] ");
| |
| for (int i = 0; i < length; i++) {
| |
| Serial.print((char)payload[i]);
| |
| payloadChar[i] = (char)payload[i];
| |
| }
| |
| Serial.println();
| |
| | |
| String payloadStr = String(payloadChar);
| |
| payloadStr.trim();
| |
|
| |
| if (strcmp(topic, "/devices/ws2812b/controls/brightness") == 0) {
| |
| BRIGHTNESS = payloadStr.toInt();
| |
| Serial.printf("brithness set to %d\n", BRIGHTNESS);
| |
| }
| |
| if (strcmp(topic, "/devices/ws2812b/controls/hueLoop") == 0) {
| |
| if(payloadStr.toInt() == 1) {
| |
| hueLoop = true;
| |
| } else {
| |
| hueLoop = false;
| |
| }
| |
| }
| |
| if (strcmp(topic, "/devices/ws2812b/controls/updatesPerSecond") == 0) {
| |
| UPDATES_PER_SECOND = payloadStr.toInt();
| |
| }
| |
| }
| |
| | |
| void setupModbus() {
| |
| pubSubClient.setServer(MODBUS_SERVER, MODBUS_PORT);
| |
| pubSubClient.setCallback(modbusCallback);
| |
| }
| |
| | |
| void modbusReconnect() {
| |
| // Loop until we're reconnected
| |
| while (!pubSubClient.connected()) {
| |
| Serial.print("Attempting MQTT connection...");
| |
| // Create a random client ID
| |
| String clientId = "ESP32Client-";
| |
| clientId += String(random(0xffff), HEX);
| |
| // Attempt to connect
| |
| if (pubSubClient.connect(clientId.c_str())) {
| |
| Serial.println("connected");
| |
| pubSubClient.subscribe("/devices/ws2812b/controls/brightness");
| |
| pubSubClient.subscribe("/devices/ws2812b/controls/hueLoop");
| |
| pubSubClient.subscribe("/devices/ws2812b/controls/updatesPerSecond");
| |
| } else {
| |
| Serial.print("failed, rc=");
| |
| Serial.print(pubSubClient.state());
| |
| Serial.println(" try again in 5 seconds");
| |
| // Wait 5 seconds before retrying
| |
| delay(5000);
| |
| }
| |
| }
| |
| }
| |
| | |
| void modbusLoop() {
| |
| if (!pubSubClient.connected()) {
| |
| modbusReconnect();
| |
| }
| |
| pubSubClient.loop();
| |
| }
| |
| | |
| void ChangePalettePeriodically();
| |
| void FillLEDsFromPaletteColors( uint8_t colorIndex);
| |
| | |
|
| |
| void FillLEDsFromPaletteColors( uint8_t colorIndex)
| |
| {
| |
| uint8_t brightness = 255;
| |
|
| |
| for( int i = 0; i < NUM_LEDS; ++i) {
| |
| leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
| |
| colorIndex += 3;
| |
| }
| |
| }
| |
|
| |
|
| |
| // There are several different palettes of colors demonstrated here.
| |
| //
| |
| // FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p,
| |
| // OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p.
| |
| //
| |
| // Additionally, you can manually define your own color palettes, or you can write
| |
| // code that creates color palettes on the fly. All are shown here.
| |
| void SetupTotallyRandomPalette();
| |
| void SetupPurpleAndGreenPalette();
| |
| void SetupPurpleAndGreenPalette();
| |
| void SetupBlackAndWhiteStripedPalette();
| |
| | |
| void ChangePalettePeriodically()
| |
| {
| |
| uint8_t secondHand = (millis() / 1000) % 60;
| |
| static uint8_t lastSecond = 99;
| |
|
| |
| FastLED.setBrightness(BRIGHTNESS);
| |
| if(!hueLoop) {
| |
| return;
| |
| }
| |
| | |
| if( lastSecond != secondHand) {
| |
| lastSecond = secondHand;
| |
| if( secondHand == 0) { currentPalette = RainbowColors_p; currentBlending = LINEARBLEND; }
| |
| if( secondHand == 10) { currentPalette = RainbowStripeColors_p; currentBlending = NOBLEND; }
| |
| if( secondHand == 15) { currentPalette = RainbowStripeColors_p; currentBlending = LINEARBLEND; }
| |
| if( secondHand == 20) { SetupPurpleAndGreenPalette(); currentBlending = LINEARBLEND; }
| |
| if( secondHand == 25) { SetupTotallyRandomPalette(); currentBlending = LINEARBLEND; }
| |
| if( secondHand == 30) { SetupBlackAndWhiteStripedPalette(); currentBlending = NOBLEND; }
| |
| if( secondHand == 35) { SetupBlackAndWhiteStripedPalette(); currentBlending = LINEARBLEND; }
| |
| if( secondHand == 40) { currentPalette = CloudColors_p; currentBlending = LINEARBLEND; }
| |
| if( secondHand == 45) { currentPalette = PartyColors_p; currentBlending = LINEARBLEND; }
| |
| if( secondHand == 50) { currentPalette = myRedWhiteBluePalette_p; currentBlending = NOBLEND; }
| |
| if( secondHand == 55) { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; }
| |
| }
| |
| }
| |
|
| |
| // This function fills the palette with totally random colors. | |
| void SetupTotallyRandomPalette()
| |
| {
| |
| for( int i = 0; i < 16; ++i) {
| |
| currentPalette[i] = CHSV( random8(), 255, random8());
| |
| }
| |
| }
| |
|
| |
| // This function sets up a palette of black and white stripes,
| |
| // using code. Since the palette is effectively an array of | |
| // sixteen CRGB colors, the various fill_* functions can be used
| |
| // to set them up.
| |
| void SetupBlackAndWhiteStripedPalette()
| |
| {
| |
| // 'black out' all 16 palette entries...
| |
| fill_solid( currentPalette, 16, CRGB::Black);
| |
| // and set every fourth one to white.
| |
| currentPalette[0] = CRGB::White;
| |
| currentPalette[4] = CRGB::White;
| |
| currentPalette[8] = CRGB::White;
| |
| currentPalette[12] = CRGB::White;
| |
|
| |
| }
| |
|
| |
| // This function sets up a palette of purple and green stripes.
| |
| void SetupPurpleAndGreenPalette()
| |
| {
| |
| CRGB purple = CHSV( HUE_PURPLE, 255, 255);
| |
| CRGB green = CHSV( HUE_GREEN, 255, 255);
| |
| CRGB black = CRGB::Black;
| |
|
| |
| currentPalette = CRGBPalette16(
| |
| green, green, black, black,
| |
| purple, purple, black, black,
| |
| green, green, black, black,
| |
| purple, purple, black, black );
| |
| }
| |
|
| |
|
| |
| // This example shows how to set up a static color palette
| |
| // which is stored in PROGMEM (flash), which is almost always more
| |
| // plentiful than RAM. A static PROGMEM palette like this
| |
| // takes up 64 bytes of flash.
| |
| const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM =
| |
| {
| |
| CRGB::Red,
| |
| CRGB::Gray, // 'white' is too bright compared to red and blue
| |
| CRGB::Blue,
| |
| CRGB::Black,
| |
|
| |
| CRGB::Red,
| |
| CRGB::Gray,
| |
| CRGB::Blue,
| |
| CRGB::Black,
| |
|
| |
| CRGB::Red,
| |
| CRGB::Red,
| |
| CRGB::Gray,
| |
| CRGB::Gray,
| |
| CRGB::Blue,
| |
| CRGB::Blue,
| |
| CRGB::Black,
| |
| CRGB::Black
| |
| };
| |
|
| |
|
| |
|
| |
| // Additional notes on FastLED compact palettes:
| |
| //
| |
| // Normally, in computer graphics, the palette (or "color lookup table")
| |
| // has 256 entries, each containing a specific 24-bit RGB color. You can then
| |
| // index into the color palette using a simple 8-bit (one byte) value.
| |
| // A 256-entry color palette takes up 768 bytes of RAM, which on Arduino
| |
| // is quite possibly "too many" bytes. | |
| // | |
| // FastLED does offer traditional 256-element palettes, for setups that
| |
| // can afford the 768-byte cost in RAM.
| |
| //
| |
| // However, FastLED also offers a compact alternative. FastLED offers
| |
| // palettes that store 16 distinct entries, but can be accessed AS IF
| |
| // they actually have 256 entries; this is accomplished by interpolating
| |
| // between the 16 explicit entries to create fifteen intermediate palette
| |
| // entries between each pair.
| |
| //
| |
| // So for example, if you set the first two explicit entries of a compact
| |
| // palette to Green (0,255,0) and Blue (0,0,255), and then retrieved
| |
| // the first sixteen entries from the virtual palette (of 256), you'd get
| |
| // Green, followed by a smooth gradient from green-to-blue, and then Blue.
| |
| | |
| | |
| #define LED_PIN 2
| |
| int led_status = HIGH;
| |
| | |
| void ledUpdate(int v) {
| |
| digitalWrite(LED_PIN, v);
| |
| }
| |
| | |
| void ledBlink( void * parameter ) {
| |
| const TickType_t xDelay = 1000 / portTICK_PERIOD_MS;
| |
| for(;;) {
| |
| switch (led_status)
| |
| {
| |
| case HIGH:
| |
| led_status = LOW;
| |
| break;
| |
| default:
| |
| led_status = HIGH;
| |
| break;
| |
| }
| |
| ledUpdate(led_status);
| |
| vTaskDelay(xDelay);
| |
| Serial.printf("blink %d\n", led_status);
| |
| }
| |
| }
| |
| | |
| void setupLedBlink() {
| |
| pinMode(LED_PIN, OUTPUT);
| |
| | |
| xTaskCreate(
| |
| ledBlink, /* Task function. */
| |
| "ledBlink", /* String with name of task. */
| |
| 10000, /* Stack size in bytes. */
| |
| NULL, /* Parameter passed as input of the task */
| |
| 1, /* Priority of the task. */
| |
| NULL); /* Task handle. */
| |
| }
| |
| | |
| | |
| void setup() {
| |
| Serial.begin(9600);
| |
| setupLedBlink();
| |
| setupWifi();
| |
| setupFastLED();
| |
| setupModbus();
| |
| setupOTA();
| |
| }
| |
| | |
| void loop()
| |
| {
| |
| modbusLoop();
| |
| ChangePalettePeriodically();
| |
|
| |
| static uint8_t startIndex = 0;
| |
| startIndex = startIndex + 1; /* motion speed */
| |
|
| |
| FillLEDsFromPaletteColors( startIndex);
| |
|
| |
| FastLED.show();
| |
| FastLED.delay(1000 / UPDATES_PER_SECOND);
| |
| }
| |
| </syntaxhighlight>
| |