This commit is contained in:
Alex
2019-09-21 11:00:50 +03:00
parent 9e08c4e11e
commit 2d25ce5754
35 changed files with 455663 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 3.1 MiB

After

Width:  |  Height:  |  Size: 3.1 MiB

View File

Before

Width:  |  Height:  |  Size: 3.6 MiB

After

Width:  |  Height:  |  Size: 3.6 MiB

View File

Before

Width:  |  Height:  |  Size: 3.7 MiB

After

Width:  |  Height:  |  Size: 3.7 MiB

View File

Before

Width:  |  Height:  |  Size: 3.4 MiB

After

Width:  |  Height:  |  Size: 3.4 MiB

View File

Before

Width:  |  Height:  |  Size: 3.4 MiB

After

Width:  |  Height:  |  Size: 3.4 MiB

View File

@@ -0,0 +1,260 @@
/*
Скетч к проекту "Многофункциональный RGB светильник"
Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/
Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/
Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/
Автор: AlexGyver, AlexGyver Technologies, 2019
https://AlexGyver.ru/
*/
/*
Версия 1.5:
- Исправлено непереключение кнопкой с первого на последний режимы
- Добавлена настройка для отключения кнопки (для корректной работы схемы без кнопки)
- Убран статический IP для локального режима (вызывал проблемы)
- Добавлена возможность сброса настроек WiFi удержанием кнопки при включении лампы (~7 секунд)
- Добавлен вывод IP адреса на лампу по пятикратному нажатию на кнопку
*/
// Ссылка для менеджера плат:
// http://arduino.esp8266.com/stable/package_esp8266com_index.json
// ============= НАСТРОЙКИ =============
// -------- КНОПКА -------
#define USE_BUTTON 1 // 1 - использовать кнопку, 0 - нет
// -------- ВРЕМЯ -------
#define GMT 3 // смещение (москва 3)
#define NTP_ADDRESS "europe.pool.ntp.org" // сервер времени
// -------- РАССВЕТ -------
#define DAWN_BRIGHT 200 // макс. яркость рассвета
#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут
// ---------- МАТРИЦА ---------
#define BRIGHTNESS 40 // стандартная маскимальная яркость (0-255)
#define CURRENT_LIMIT 2000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит
#define WIDTH 16 // ширина матрицы
#define HEIGHT 16 // высота матрицы
#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB
#define MATRIX_TYPE 0 // тип матрицы: 0 - зигзаг, 1 - параллельная
#define CONNECTION_ANGLE 0 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз
// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default"
// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/
// --------- ESP --------
#define ESP_MODE 1
// 0 - точка доступа
// 1 - локальный
byte IP_AP[] = {192, 168, 4, 66}; // статический IP точки доступа (менять только последнюю цифру)
// ----- AP (точка доступа) -------
#define AP_SSID "GyverLamp"
#define AP_PASS "12345678"
#define AP_PORT 8888
// -------- Менеджер WiFi ---------
#define AC_SSID "AutoConnectAP"
#define AC_PASS "12345678"
// ============= ДЛЯ РАЗРАБОТЧИКОВ =============
#define LED_PIN 2 // пин ленты
#define BTN_PIN 4
#define MODE_AMOUNT 18
#define NUM_LEDS WIDTH * HEIGHT
#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты)
// ---------------- БИБЛИОТЕКИ -----------------
#define FASTLED_INTERRUPT_RETRY_COUNT 0
#define FASTLED_ALLOW_INTERRUPTS 0
#define FASTLED_ESP8266_RAW_PIN_ORDER
#define NTP_INTERVAL 60 * 1000 // обновление (1 минута)
#include "timerMinim.h"
#include <FastLED.h>
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <WiFiUdp.h>
#include <EEPROM.h>
#include <NTPClient.h>
#include <GyverButton.h>
#include "fonts.h"
// ------------------- ТИПЫ --------------------
CRGB leds[NUM_LEDS];
WiFiServer server(80);
WiFiUDP Udp;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_ADDRESS, GMT * 3600, NTP_INTERVAL);
timerMinim timeTimer(3000);
GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN);
// ----------------- ПЕРЕМЕННЫЕ ------------------
const char* autoConnectSSID = AC_SSID;
const char* autoConnectPass = AC_PASS;
const char AP_NameChar[] = AP_SSID;
const char WiFiPassword[] = AP_PASS;
unsigned int localPort = AP_PORT;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; //buffer to hold incoming packet
String inputBuffer;
static const byte maxDim = max(WIDTH, HEIGHT);
struct {
byte brightness = 50;
byte speed = 30;
byte scale = 40;
} modes[MODE_AMOUNT];
struct {
boolean state = false;
int time = 0;
} alarm[7];
byte dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60};
byte dawnMode;
boolean dawnFlag = false;
long thisTime;
boolean manualOff = false;
int8_t currentMode = 0;
boolean loadingFlag = true;
boolean ONflag = true;
uint32_t eepromTimer;
boolean settChanged = false;
// Конфетти, Огонь, Радуга верт., Радуга гориз., Смена цвета,
// Безумие 3D, Облака 3D, Лава 3D, Плазма 3D, Радуга 3D,
// Павлин 3D, Зебра 3D, Лес 3D, Океан 3D,
unsigned char matrixValue[8][16];
String lampIP = "";
void setup() {
ESP.wdtDisable();
//ESP.wdtEnable(WDTO_8S);
// ЛЕНТА
FastLED.addLeds<WS2812B, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS)/*.setCorrection( TypicalLEDStrip )*/;
FastLED.setBrightness(BRIGHTNESS);
if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT);
FastLED.show();
touch.setStepTimeout(100);
touch.setClickTimeout(500);
Serial.begin(115200);
Serial.println();
delay(1000);
// WI-FI
if (ESP_MODE == 0) { // режим точки доступа
WiFi.softAPConfig(IPAddress(IP_AP[0], IP_AP[1], IP_AP[2], IP_AP[3]),
IPAddress(192, 168, 4, 1),
IPAddress(255, 255, 255, 0));
WiFi.softAP(AP_NameChar, WiFiPassword);
IPAddress myIP = WiFi.softAPIP();
Serial.print("Access point Mode");
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin();
} else { // подключаемся к роутеру
Serial.print("WiFi manager");
WiFiManager wifiManager;
wifiManager.setDebugOutput(false);
#if (USE_BUTTON == 1)
if (digitalRead(BTN_PIN)) wifiManager.resetSettings();
#endif
wifiManager.autoConnect(autoConnectSSID, autoConnectPass);
/*WiFi.config(IPAddress(IP_STA[0], IP_STA[1], IP_STA[2], IP_STA[3]),
IPAddress(192, 168, 1, 1),
IPAddress(255, 255, 255, 0));*/
Serial.print("Connected! IP address: ");
Serial.println(WiFi.localIP());
lampIP = WiFi.localIP().toString();
}
Serial.printf("UDP server on port %d\n", localPort);
Udp.begin(localPort);
// EEPROM
EEPROM.begin(202);
delay(50);
if (EEPROM.read(198) != 20) { // первый запуск
EEPROM.write(198, 20);
EEPROM.commit();
for (byte i = 0; i < MODE_AMOUNT; i++) {
EEPROM.put(3 * i + 40, modes[i]);
EEPROM.commit();
}
for (byte i = 0; i < 7; i++) {
EEPROM.write(5 * i, alarm[i].state); // рассвет
eeWriteInt(5 * i + 1, alarm[i].time);
EEPROM.commit();
}
EEPROM.write(199, 0); // рассвет
EEPROM.write(200, 0); // режим
EEPROM.commit();
}
for (byte i = 0; i < MODE_AMOUNT; i++) {
EEPROM.get(3 * i + 40, modes[i]);
}
for (byte i = 0; i < 7; i++) {
alarm[i].state = EEPROM.read(5 * i);
alarm[i].time = eeGetInt(5 * i + 1);
}
dawnMode = EEPROM.read(199);
currentMode = (int8_t)EEPROM.read(200);
// отправляем настройки
sendCurrent();
char reply[inputBuffer.length() + 1];
inputBuffer.toCharArray(reply, inputBuffer.length() + 1);
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(reply);
Udp.endPacket();
timeClient.begin();
memset(matrixValue, 0, sizeof(matrixValue));
randomSeed(micros());
}
void loop() {
parseUDP();
effectsTick();
eepromTick();
timeTick();
#if (USE_BUTTON == 1)
buttonTick();
#endif
ESP.wdtFeed(); // пнуть собаку
yield(); // ещё раз пнуть собаку
}
void eeWriteInt(int pos, int val) {
byte* p = (byte*) &val;
EEPROM.write(pos, *p);
EEPROM.write(pos + 1, *(p + 1));
EEPROM.write(pos + 2, *(p + 2));
EEPROM.write(pos + 3, *(p + 3));
EEPROM.commit();
}
int eeGetInt(int pos) {
int val;
byte* p = (byte*) &val;
*p = EEPROM.read(pos);
*(p + 1) = EEPROM.read(pos + 1);
*(p + 2) = EEPROM.read(pos + 2);
*(p + 3) = EEPROM.read(pos + 3);
return val;
}

View File

@@ -0,0 +1,66 @@
boolean brightDirection;
void buttonTick() {
touch.tick();
if (touch.isSingle()) {
if (dawnFlag) {
manualOff = true;
dawnFlag = false;
loadingFlag = true;
FastLED.setBrightness(modes[currentMode].brightness);
changePower();
} else {
if (ONflag) {
ONflag = false;
changePower();
} else {
ONflag = true;
changePower();
}
}
}
if (ONflag && touch.isDouble()) {
if (++currentMode >= MODE_AMOUNT) currentMode = 0;
FastLED.setBrightness(modes[currentMode].brightness);
loadingFlag = true;
settChanged = true;
eepromTimer = millis();
FastLED.clear();
delay(1);
}
if (ONflag && touch.isTriple()) {
if (--currentMode < 0) currentMode = MODE_AMOUNT;
FastLED.setBrightness(modes[currentMode].brightness);
loadingFlag = true;
settChanged = true;
eepromTimer = millis();
FastLED.clear();
delay(1);
}
// вывод IP на лампу
if (ONflag && touch.hasClicks()) {
if (touch.getClicks() == 5) {
while(!fillString(lampIP)) delay(1);
}
}
if (ONflag && touch.isHolded()) {
brightDirection = !brightDirection;
}
if (ONflag && touch.isStep()) {
if (brightDirection) {
if (modes[currentMode].brightness < 10) modes[currentMode].brightness += 1;
else if (modes[currentMode].brightness < 250) modes[currentMode].brightness += 5;
else modes[currentMode].brightness = 255;
} else {
if (modes[currentMode].brightness > 15) modes[currentMode].brightness -= 5;
else if (modes[currentMode].brightness > 1) modes[currentMode].brightness -= 1;
else modes[currentMode].brightness = 1;
}
FastLED.setBrightness(modes[currentMode].brightness);
settChanged = true;
eepromTimer = millis();
}
}

View File

@@ -0,0 +1,25 @@
void saveEEPROM() {
EEPROM.put(3 * currentMode + 40, modes[currentMode]);
EEPROM.commit();
}
void eepromTick() {
if (settChanged && millis() - eepromTimer > 30000) {
settChanged = false;
eepromTimer = millis();
saveEEPROM();
if (EEPROM.read(200) != currentMode) EEPROM.write(200, currentMode);
EEPROM.commit();
}
}
void saveAlarm(byte almNumber) {
EEPROM.write(5 * almNumber, alarm[almNumber].state); // рассвет
eeWriteInt(5 * almNumber + 1, alarm[almNumber].time);
EEPROM.commit();
}
void saveDawnMmode() {
EEPROM.write(199, dawnMode); // рассвет
EEPROM.commit();
}

View File

@@ -0,0 +1,72 @@
uint32_t effTimer;
void effectsTick() {
if (!dawnFlag) {
if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) {
effTimer = millis();
switch (currentMode) {
case 0: sparklesRoutine();
break;
case 1: fireRoutine();
break;
case 2: rainbowVertical();
break;
case 3: rainbowHorizontal();
break;
case 4: colorsRoutine();
break;
case 5: madnessNoise();
break;
case 6: cloudNoise();
break;
case 7: lavaNoise();
break;
case 8: plasmaNoise();
break;
case 9: rainbowNoise();
break;
case 10: rainbowStripeNoise();
break;
case 11: zebraNoise();
break;
case 12: forestNoise();
break;
case 13: oceanNoise();
break;
case 14: colorRoutine();
break;
case 15: snowRoutine();
break;
case 16: matrixRoutine();
break;
case 17: lightersRoutine();
break;
}
FastLED.show();
}
}
}
void changePower() {
if (ONflag) {
effectsTick();
for (int i = 0; i < modes[currentMode].brightness; i += 8) {
FastLED.setBrightness(i);
delay(1);
FastLED.show();
}
FastLED.setBrightness(modes[currentMode].brightness);
delay(2);
FastLED.show();
} else {
effectsTick();
for (int i = modes[currentMode].brightness; i > 8; i -= 8) {
FastLED.setBrightness(i);
delay(1);
FastLED.show();
}
FastLED.clear();
delay(2);
FastLED.show();
}
}

View File

@@ -0,0 +1,333 @@
// ================================= ЭФФЕКТЫ ====================================
// --------------------------------- конфетти ------------------------------------
void sparklesRoutine() {
for (byte i = 0; i < modes[0].scale; i++) {
byte x = random(0, WIDTH);
byte y = random(0, HEIGHT);
if (getPixColorXY(x, y) == 0)
leds[getPixelNumber(x, y)] = CHSV(random(0, 255), 255, 255);
}
fader(70);
}
// функция плавного угасания цвета для всех пикселей
void fader(byte step) {
for (byte i = 0; i < WIDTH; i++) {
for (byte j = 0; j < HEIGHT; j++) {
fadePixel(i, j, step);
}
}
}
void fadePixel(byte i, byte j, byte step) { // новый фейдер
int pixelNum = getPixelNumber(i, j);
if (getPixColor(pixelNum) == 0) return;
if (leds[pixelNum].r >= 30 ||
leds[pixelNum].g >= 30 ||
leds[pixelNum].b >= 30) {
leds[pixelNum].fadeToBlackBy(step);
} else {
leds[pixelNum] = 0;
}
}
// -------------------------------------- огонь ---------------------------------------------
// эффект "огонь"
#define SPARKLES 1 // вылетающие угольки вкл выкл
unsigned char line[WIDTH];
int pcnt = 0;
//these values are substracetd from the generated values to give a shape to the animation
const unsigned char valueMask[8][16] PROGMEM = {
{32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 },
{64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 },
{96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 },
{128, 64 , 32 , 0 , 0 , 32 , 64 , 128, 128, 64 , 32 , 0 , 0 , 32 , 64 , 128},
{160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160, 96 , 64 , 32 , 32 , 64 , 96 , 160},
{192, 128, 96 , 64 , 64 , 96 , 128, 192, 192, 128, 96 , 64 , 64 , 96 , 128, 192},
{255, 160, 128, 96 , 96 , 128, 160, 255, 255, 160, 128, 96 , 96 , 128, 160, 255},
{255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255}
};
//these are the hues for the fire,
//should be between 0 (red) to about 25 (yellow)
const unsigned char hueMask[8][16] PROGMEM = {
{1 , 11, 19, 25, 25, 22, 11, 1 , 1 , 11, 19, 25, 25, 22, 11, 1 },
{1 , 8 , 13, 19, 25, 19, 8 , 1 , 1 , 8 , 13, 19, 25, 19, 8 , 1 },
{1 , 8 , 13, 16, 19, 16, 8 , 1 , 1 , 8 , 13, 16, 19, 16, 8 , 1 },
{1 , 5 , 11, 13, 13, 13, 5 , 1 , 1 , 5 , 11, 13, 13, 13, 5 , 1 },
{1 , 5 , 11, 11, 11, 11, 5 , 1 , 1 , 5 , 11, 11, 11, 11, 5 , 1 },
{0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 },
{0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 },
{0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 }
};
void fireRoutine() {
if (loadingFlag) {
loadingFlag = false;
//FastLED.clear();
generateLine();
}
if (pcnt >= 100) {
shiftUp();
generateLine();
pcnt = 0;
}
drawFrame(pcnt);
pcnt += 30;
}
// Randomly generate the next line (matrix row)
void generateLine() {
for (uint8_t x = 0; x < WIDTH; x++) {
line[x] = random(64, 255);
}
}
void shiftUp() {
for (uint8_t y = HEIGHT - 1; y > 0; y--) {
for (uint8_t x = 0; x < WIDTH; x++) {
uint8_t newX = x;
if (x > 15) newX = x - 15;
if (y > 7) continue;
matrixValue[y][newX] = matrixValue[y - 1][newX];
}
}
for (uint8_t x = 0; x < WIDTH; x++) {
uint8_t newX = x;
if (x > 15) newX = x - 15;
matrixValue[0][newX] = line[newX];
}
}
// draw a frame, interpolating between 2 "key frames"
// @param pcnt percentage of interpolation
void drawFrame(int pcnt) {
int nextv;
//each row interpolates with the one before it
for (unsigned char y = HEIGHT - 1; y > 0; y--) {
for (unsigned char x = 0; x < WIDTH; x++) {
uint8_t newX = x;
if (x > 15) newX = x - 15;
if (y < 8) {
nextv =
(((100.0 - pcnt) * matrixValue[y][newX]
+ pcnt * matrixValue[y - 1][newX]) / 100.0)
- pgm_read_byte(&(valueMask[y][newX]));
CRGB color = CHSV(
modes[1].scale * 2.5 + pgm_read_byte(&(hueMask[y][newX])), // H
255, // S
(uint8_t)max(0, nextv) // V
);
leds[getPixelNumber(x, y)] = color;
} else if (y == 8 && SPARKLES) {
if (random(0, 20) == 0 && getPixColorXY(x, y - 1) != 0) drawPixelXY(x, y, getPixColorXY(x, y - 1));
else drawPixelXY(x, y, 0);
} else if (SPARKLES) {
// старая версия для яркости
if (getPixColorXY(x, y - 1) > 0)
drawPixelXY(x, y, getPixColorXY(x, y - 1));
else drawPixelXY(x, y, 0);
}
}
}
//first row interpolates with the "next" line
for (unsigned char x = 0; x < WIDTH; x++) {
uint8_t newX = x;
if (x > 15) newX = x - 15;
CRGB color = CHSV(
modes[1].scale * 2.5 + pgm_read_byte(&(hueMask[0][newX])), // H
255, // S
(uint8_t)(((100.0 - pcnt) * matrixValue[0][newX] + pcnt * line[newX]) / 100.0) // V
);
leds[getPixelNumber(newX, 0)] = color;
}
}
byte hue;
// ---------------------------------------- радуга ------------------------------------------
void rainbowVertical() {
hue += 2;
for (byte j = 0; j < HEIGHT; j++) {
CHSV thisColor = CHSV((byte)(hue + j * modes[2].scale), 255, 255);
for (byte i = 0; i < WIDTH; i++)
drawPixelXY(i, j, thisColor);
}
}
void rainbowHorizontal() {
hue += 2;
for (byte i = 0; i < WIDTH; i++) {
CHSV thisColor = CHSV((byte)(hue + i * modes[3].scale), 255, 255);
for (byte j = 0; j < HEIGHT; j++)
drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor;
}
}
// ---------------------------------------- ЦВЕТА ------------------------------------------
void colorsRoutine() {
hue += modes[4].scale;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CHSV(hue, 255, 255);
}
}
// --------------------------------- ЦВЕТ ------------------------------------
void colorRoutine() {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CHSV(modes[14].scale * 2.5, 255, 255);
}
}
// ------------------------------ снегопад 2.0 --------------------------------
void snowRoutine() {
// сдвигаем всё вниз
for (byte x = 0; x < WIDTH; x++) {
for (byte y = 0; y < HEIGHT - 1; y++) {
drawPixelXY(x, y, getPixColorXY(x, y + 1));
}
}
for (byte x = 0; x < WIDTH; x++) {
// заполняем случайно верхнюю строку
// а также не даём двум блокам по вертикали вместе быть
if (getPixColorXY(x, HEIGHT - 2) == 0 && (random(0, modes[15].scale) == 0))
drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4));
else
drawPixelXY(x, HEIGHT - 1, 0x000000);
}
}
// ------------------------------ МАТРИЦА ------------------------------
void matrixRoutine() {
for (byte x = 0; x < WIDTH; x++) {
// заполняем случайно верхнюю строку
uint32_t thisColor = getPixColorXY(x, HEIGHT - 1);
if (thisColor == 0)
drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, modes[16].scale) == 0));
else if (thisColor < 0x002000)
drawPixelXY(x, HEIGHT - 1, 0);
else
drawPixelXY(x, HEIGHT - 1, thisColor - 0x002000);
}
// сдвигаем всё вниз
for (byte x = 0; x < WIDTH; x++) {
for (byte y = 0; y < HEIGHT - 1; y++) {
drawPixelXY(x, y, getPixColorXY(x, y + 1));
}
}
}
// ----------------------------- СВЕТЛЯКИ ------------------------------
#define LIGHTERS_AM 100
int lightersPos[2][LIGHTERS_AM];
int8_t lightersSpeed[2][LIGHTERS_AM];
CHSV lightersColor[LIGHTERS_AM];
byte loopCounter;
int angle[LIGHTERS_AM];
int speedV[LIGHTERS_AM];
int8_t angleSpeed[LIGHTERS_AM];
void lightersRoutine() {
if (loadingFlag) {
loadingFlag = false;
randomSeed(millis());
for (byte i = 0; i < LIGHTERS_AM; i++) {
lightersPos[0][i] = random(0, WIDTH * 10);
lightersPos[1][i] = random(0, HEIGHT * 10);
lightersSpeed[0][i] = random(-10, 10);
lightersSpeed[1][i] = random(-10, 10);
lightersColor[i] = CHSV(random(0, 255), 255, 255);
}
}
FastLED.clear();
if (++loopCounter > 20) loopCounter = 0;
for (byte i = 0; i < modes[17].scale; i++) {
if (loopCounter == 0) { // меняем скорость каждые 255 отрисовок
lightersSpeed[0][i] += random(-3, 4);
lightersSpeed[1][i] += random(-3, 4);
lightersSpeed[0][i] = constrain(lightersSpeed[0][i], -20, 20);
lightersSpeed[1][i] = constrain(lightersSpeed[1][i], -20, 20);
}
lightersPos[0][i] += lightersSpeed[0][i];
lightersPos[1][i] += lightersSpeed[1][i];
if (lightersPos[0][i] < 0) lightersPos[0][i] = (WIDTH - 1) * 10;
if (lightersPos[0][i] >= WIDTH * 10) lightersPos[0][i] = 0;
if (lightersPos[1][i] < 0) {
lightersPos[1][i] = 0;
lightersSpeed[1][i] = -lightersSpeed[1][i];
}
if (lightersPos[1][i] >= (HEIGHT - 1) * 10) {
lightersPos[1][i] = (HEIGHT - 1) * 10;
lightersSpeed[1][i] = -lightersSpeed[1][i];
}
drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]);
}
}
/*
void lightersRoutine() {
if (loadingFlag) {
loadingFlag = false;
randomSeed(millis());
for (byte i = 0; i < LIGHTERS_AM; i++) {
lightersPos[0][i] = random(0, WIDTH * 10);
lightersPos[1][i] = random(0, HEIGHT * 10);
lightersColor[i] = CHSV(random(0, 255), 255, 255);
speedV[i] = random(5, 10);
angle[i] = random(0, 360);
angleSpeed[i] = random(-10, 10);
}
}
FastLED.clear();
if (++loopCounter > 20) loopCounter = 0;
for (byte i = 0; i < modes[17].scale; i++) {
if (loopCounter == 0) { // меняем скорость каждые 255 отрисовок
angleSpeed[i] += random(-3, 4);
angleSpeed[i] = constrain(angleSpeed[i], -15, 15);
}
lightersPos[0][i] += speedV[i] * cos(radians(angle[i]));
lightersPos[1][i] += speedV[i] * sin(radians(angle[i]));
if (lightersPos[0][i] < 0) lightersPos[0][i] = (WIDTH - 1) * 10;
if (lightersPos[0][i] >= WIDTH * 10) lightersPos[0][i] = 0;
if (lightersPos[1][i] < 0) {
lightersPos[1][i] = 0;
angle[i] = 360 - angle[i];
} else {
angle[i] += angleSpeed[i];
}
if (lightersPos[1][i] >= (HEIGHT - 1) * 10) {
lightersPos[1][i] = (HEIGHT - 1) * 10;
angle[i] = 360 - angle[i];
} else {
angle[i] += angleSpeed[i];
}
if (angle[i] > 360) angle[i] = 360 - angle[i];
if (angle[i] < 0) angle[i] = 360 + angle[i];
drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]);
}
}
*/

View File

@@ -0,0 +1,231 @@
// шрифты для вывода текста
const uint8_t fontHEX[][5] PROGMEM = {
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 32
{0x00, 0x00, 0x6f, 0x00, 0x00}, // ! 0x21 33
{0x00, 0x07, 0x00, 0x07, 0x00}, // " 0x22 34
{0x14, 0x7f, 0x14, 0x7f, 0x14}, // # 0x23 35
{0x00, 0x07, 0x04, 0x1e, 0x00}, // $ 0x24 36
{0x23, 0x13, 0x08, 0x64, 0x62}, // % 0x25 37
{0x36, 0x49, 0x56, 0x20, 0x50}, // & 0x26 38
{0x00, 0x00, 0x07, 0x00, 0x00}, // ' 0x27 39
{0x00, 0x1c, 0x22, 0x41, 0x00}, // ( 0x28 40
{0x00, 0x41, 0x22, 0x1c, 0x00}, // ) 0x29 41
{0x14, 0x08, 0x3e, 0x08, 0x14}, // * 0x2a 42
{0x08, 0x08, 0x3e, 0x08, 0x08}, // + 0x2b 43
{0x00, 0x50, 0x30, 0x00, 0x00}, // , 0x2c 44
{0x08, 0x08, 0x08, 0x08, 0x08}, // - 0x2d 45
{0x00, 0x60, 0x60, 0x00, 0x00}, // . 0x2e 46
{0x20, 0x10, 0x08, 0x04, 0x02}, // / 0x2f 47
{0x3e, 0x51, 0x49, 0x45, 0x3e}, // 0 0x30 48
{0x00, 0x42, 0x7f, 0x40, 0x00}, // 1 0x31 49
{0x42, 0x61, 0x51, 0x49, 0x46}, // 2 0x32 50
{0x21, 0x41, 0x45, 0x4b, 0x31}, // 3 0x33 51
{0x18, 0x14, 0x12, 0x7f, 0x10}, // 4 0x34 52
{0x27, 0x45, 0x45, 0x45, 0x39}, // 5 0x35 53
{0x3c, 0x4a, 0x49, 0x49, 0x30}, // 6 0x36 54
{0x01, 0x71, 0x09, 0x05, 0x03}, // 7 0x37 55
{0x36, 0x49, 0x49, 0x49, 0x36}, // 8 0x38 56
{0x06, 0x49, 0x49, 0x29, 0x1e}, // 9 0x39 57
{0x00, 0x36, 0x36, 0x00, 0x00}, // : 0x3a 58
{0x00, 0x56, 0x36, 0x00, 0x00}, // ; 0x3b 59
{0x08, 0x14, 0x22, 0x41, 0x00}, // < 0x3c 60
{0x14, 0x14, 0x14, 0x14, 0x14}, // = 0x3d 61
{0x00, 0x41, 0x22, 0x14, 0x08}, // > 0x3e 62
{0x02, 0x01, 0x51, 0x09, 0x06}, // ? 0x3f 63
{0x3e, 0x41, 0x5d, 0x49, 0x4e}, // @ 0x40 64
{0x7e, 0x09, 0x09, 0x09, 0x7e}, // A 0x41 65
{0x7f, 0x49, 0x49, 0x49, 0x36}, // B 0x42 66
{0x3e, 0x41, 0x41, 0x41, 0x22}, // C 0x43 67
{0x7f, 0x41, 0x41, 0x41, 0x3e}, // D 0x44 68
{0x7f, 0x49, 0x49, 0x49, 0x41}, // E 0x45 69
{0x7f, 0x09, 0x09, 0x09, 0x01}, // F 0x46 70
{0x3e, 0x41, 0x49, 0x49, 0x7a}, // G 0x47 71
{0x7f, 0x08, 0x08, 0x08, 0x7f}, // H 0x48 72
{0x00, 0x41, 0x7f, 0x41, 0x00}, // I 0x49 73
{0x20, 0x40, 0x41, 0x3f, 0x01}, // J 0x4a 74
{0x7f, 0x08, 0x14, 0x22, 0x41}, // K 0x4b 75
{0x7f, 0x40, 0x40, 0x40, 0x40}, // L 0x4c 76
{0x7f, 0x02, 0x0c, 0x02, 0x7f}, // M 0x4d 77
{0x7f, 0x04, 0x08, 0x10, 0x7f}, // N 0x4e 78
{0x3e, 0x41, 0x41, 0x41, 0x3e}, // O 0x4f 79
{0x7f, 0x09, 0x09, 0x09, 0x06}, // P 0x50 80
{0x3e, 0x41, 0x51, 0x21, 0x5e}, // Q 0x51 81
{0x7f, 0x09, 0x19, 0x29, 0x46}, // R 0x52 82
{0x46, 0x49, 0x49, 0x49, 0x31}, // S 0x53 83
{0x01, 0x01, 0x7f, 0x01, 0x01}, // T 0x54 84
{0x3f, 0x40, 0x40, 0x40, 0x3f}, // U 0x55 85
{0x0f, 0x30, 0x40, 0x30, 0x0f}, // V 0x56 86
{0x3f, 0x40, 0x30, 0x40, 0x3f}, // W 0x57 87
{0x63, 0x14, 0x08, 0x14, 0x63}, // X 0x58 88
{0x07, 0x08, 0x70, 0x08, 0x07}, // Y 0x59 89
{0x61, 0x51, 0x49, 0x45, 0x43}, // Z 0x5a 90
{0x3c, 0x4a, 0x49, 0x29, 0x1e}, // [ 0x5b 91
{0x02, 0x04, 0x08, 0x10, 0x20}, // \ 0x5c 92
{0x00, 0x41, 0x7f, 0x00, 0x00}, // ] 0x5d 93
{0x04, 0x02, 0x01, 0x02, 0x04}, // ^ 0x5e 94
{0x40, 0x40, 0x40, 0x40, 0x40}, // _ 0x5f 95
{0x00, 0x00, 0x03, 0x04, 0x00}, // ` 0x60 96
{0x20, 0x54, 0x54, 0x54, 0x78}, // a 0x61 97
{0x7f, 0x48, 0x44, 0x44, 0x38}, // b 0x62 98
{0x38, 0x44, 0x44, 0x44, 0x20}, // c 0x63 99
{0x38, 0x44, 0x44, 0x48, 0x7f}, // d 0x64 100
{0x38, 0x54, 0x54, 0x54, 0x18}, // e 0x65 101
{0x08, 0x7e, 0x09, 0x01, 0x02}, // f 0x66 102
{0x0c, 0x52, 0x52, 0x52, 0x3e}, // g 0x67 103
{0x7f, 0x08, 0x04, 0x04, 0x78}, // h 0x68 104
{0x00, 0x44, 0x7d, 0x40, 0x00}, // i 0x69 105
{0x20, 0x40, 0x44, 0x3d, 0x00}, // j 0x6a 106
{0x00, 0x7f, 0x10, 0x28, 0x44}, // k 0x6b 107
{0x00, 0x41, 0x7f, 0x40, 0x00}, // l 0x6c 108
{0x7c, 0x04, 0x18, 0x04, 0x78}, // m 0x6d 109
{0x7c, 0x08, 0x04, 0x04, 0x78}, // n 0x6e 110
{0x38, 0x44, 0x44, 0x44, 0x38}, // o 0x6f 111
{0x7c, 0x14, 0x14, 0x14, 0x08}, // p 0x70 112
{0x08, 0x14, 0x14, 0x18, 0x7c}, // q 0x71 113
{0x7c, 0x08, 0x04, 0x04, 0x08}, // r 0x72 114
{0x48, 0x54, 0x54, 0x54, 0x20}, // s 0x73 115
{0x04, 0x3f, 0x44, 0x40, 0x20}, // t 0x74 116
{0x3c, 0x40, 0x40, 0x20, 0x7c}, // u 0x75 117
{0x1c, 0x20, 0x40, 0x20, 0x1c}, // v 0x76 118
{0x3c, 0x40, 0x30, 0x40, 0x3c}, // w 0x77 119
{0x44, 0x28, 0x10, 0x28, 0x44}, // x 0x78 120
{0x0c, 0x50, 0x50, 0x50, 0x3c}, // y 0x79 121
{0x44, 0x64, 0x54, 0x4c, 0x44}, // z 0x7a 122
{0x00, 0x08, 0x36, 0x41, 0x41}, // { 0x7b 123
{0x00, 0x00, 0x7f, 0x00, 0x00}, // | 0x7c 124
{0x41, 0x41, 0x36, 0x08, 0x00}, // } 0x7d 125
{0x04, 0x02, 0x04, 0x08, 0x04}, // ~ 0x7e 126
{0x7E, 0x11, 0x11, 0x11, 0x7E}, //__А (0xC0).
{0x7F, 0x49, 0x49, 0x49, 0x33}, //__Б (0xC1).
{0x7F, 0x49, 0x49, 0x49, 0x36}, //__В (0xC2).
{0x7F, 0x01, 0x01, 0x01, 0x03}, //__Г (0xC3).
{0xE0, 0x51, 0x4F, 0x41, 0xFF}, //__Д (0xC4).
{0x7F, 0x49, 0x49, 0x49, 0x41}, //__Е (0xC5).
{0x77, 0x08, 0x7F, 0x08, 0x77}, //__Ж (0xC6).
{0x41, 0x49, 0x49, 0x49, 0x36}, //__З (0xC7).
{0x7F, 0x10, 0x08, 0x04, 0x7F}, //__И (0xC8).
{0x7C, 0x21, 0x12, 0x09, 0x7C}, //__Й (0xC9).
{0x7F, 0x08, 0x14, 0x22, 0x41}, //__К (0xCA).
{0x20, 0x41, 0x3F, 0x01, 0x7F}, //__Л (0xCB).
{0x7F, 0x02, 0x0C, 0x02, 0x7F}, //__М (0xCC).
{0x7F, 0x08, 0x08, 0x08, 0x7F}, //__Н (0xCD).
{0x3E, 0x41, 0x41, 0x41, 0x3E}, //__О (0xCE).
{0x7F, 0x01, 0x01, 0x01, 0x7F}, //__П (0xCF).
{0x7F, 0x09, 0x09, 0x09, 0x06}, //__Р (0xD0).
{0x3E, 0x41, 0x41, 0x41, 0x22}, //__С (0xD1).
{0x01, 0x01, 0x7F, 0x01, 0x01}, //__Т (0xD2).
{0x47, 0x28, 0x10, 0x08, 0x07}, //__У (0xD3).
{0x1C, 0x22, 0x7F, 0x22, 0x1C}, //__Ф (0xD4).
{0x63, 0x14, 0x08, 0x14, 0x63}, //__Х (0xD5).
{0x7F, 0x40, 0x40, 0x40, 0xFF}, //__Ц (0xD6).
{0x07, 0x08, 0x08, 0x08, 0x7F}, //__Ч (0xD7).
{0x7F, 0x40, 0x7F, 0x40, 0x7F}, //__Ш (0xD8).
{0x7F, 0x40, 0x7F, 0x40, 0xFF}, //__Щ (0xD9).
{0x01, 0x7F, 0x48, 0x48, 0x30}, //__Ъ (0xDA).
{0x7F, 0x48, 0x30, 0x00, 0x7F}, //__Ы (0xDB).
{0x00, 0x7F, 0x48, 0x48, 0x30}, //__Ь (0xDC).
{0x22, 0x41, 0x49, 0x49, 0x3E}, //__Э (0xDD).
{0x7F, 0x08, 0x3E, 0x41, 0x3E}, //__Ю (0xDE).
{0x46, 0x29, 0x19, 0x09, 0x7F}, //__Я (0xDF).
{0x20, 0x54, 0x54, 0x54, 0x78}, //__а (0xE0).
{0x3C, 0x4A, 0x4A, 0x49, 0x31}, //__б (0xE1).
{0x7C, 0x54, 0x54, 0x28, 0x00}, //__в (0xE2).
{0x7C, 0x04, 0x04, 0x0C, 0x00}, //__г (0xE3).
{0xE0, 0x54, 0x4C, 0x44, 0xFC}, //__д (0xE4).
{0x38, 0x54, 0x54, 0x54, 0x18}, //__е (0xE5).
{0x6C, 0x10, 0x7C, 0x10, 0x6C}, //__ж (0xE6).
{0x44, 0x54, 0x54, 0x28, 0x00}, //__з (0xE7).
{0x7C, 0x20, 0x10, 0x08, 0x7C}, //__и (0xE8).
{0x78, 0x42, 0x24, 0x12, 0x78}, //__й (0xE9).
{0x7C, 0x10, 0x28, 0x44, 0x00}, //__к (0xEA).
{0x20, 0x44, 0x3C, 0x04, 0x7C}, //__л (0xEB).
{0x7C, 0x08, 0x10, 0x08, 0x7C}, //__м (0xEC).
{0x7C, 0x10, 0x10, 0x10, 0x7C}, //__н (0xED).
{0x38, 0x44, 0x44, 0x44, 0x38}, //__о (0xEE).
{0x7C, 0x04, 0x04, 0x04, 0x7C}, //__п (0xEF).
{0x7C, 0x14, 0x14, 0x14, 0x08}, //__р (0xF0).
{0x38, 0x44, 0x44, 0x44, 0x00}, //__с (0xF1).
{0x04, 0x04, 0x7C, 0x04, 0x04}, //__т (0xF2).
{0x0C, 0x50, 0x50, 0x50, 0x3C}, //__у (0xF3).
{0x30, 0x48, 0xFE, 0x48, 0x30}, //__ф (0xF4).
{0x44, 0x28, 0x10, 0x28, 0x44}, //__х (0xF5).
{0x7C, 0x40, 0x40, 0x7C, 0xC0}, //__ц (0xF6).
{0x0C, 0x10, 0x10, 0x10, 0x7C}, //__ч (0xF7).
{0x7C, 0x40, 0x7C, 0x40, 0x7C}, //__ш (0xF8).
{0x7C, 0x40, 0x7C, 0x40, 0xFC}, //__щ (0xF9).
{0x04, 0x7C, 0x50, 0x50, 0x20}, //__ъ (0xFA).
{0x7C, 0x50, 0x50, 0x20, 0x7C}, //__ы (0xFB).
{0x7C, 0x50, 0x50, 0x20, 0x00}, //__ь (0xFC).
{0x28, 0x44, 0x54, 0x54, 0x38}, //__э (0xFD).
{0x7C, 0x10, 0x38, 0x44, 0x38}, //__ю (0xFE).
{0x08, 0x54, 0x34, 0x14, 0x7C}, //__я (0xFF).
/*
{0x7e, 0x09, 0x09, 0x09, 0x7e}, // А 192
{0x7F, 0x49, 0x49, 0x49, 0x71}, // Б
{0x7f, 0x49, 0x49, 0x49, 0x36}, // В
{0x7F, 0x01, 0x01, 0x01, 0x01}, // Г
{0x60, 0x3E, 0x21, 0x3F, 0x60}, // Д
{0x7f, 0x49, 0x49, 0x49, 0x41}, // Е
{0x76, 0x08, 0x7F, 0x08, 0x76}, // Ж
{0x21, 0x41, 0x45, 0x4b, 0x31}, // З
{0x7F, 0x20, 0x10, 0x08, 0x7F}, // И
{0x7E, 0x20, 0x11, 0x08, 0x7E}, // Й
{0x7f, 0x08, 0x14, 0x22, 0x41}, // К
{0x70, 0x0E, 0x01, 0x01, 0x7F}, // Л
{0x7f, 0x02, 0x0c, 0x02, 0x7f}, // М
{0x7f, 0x08, 0x08, 0x08, 0x7f}, // Н
{0x3e, 0x41, 0x41, 0x41, 0x3e}, // О
{0x7F, 0x01, 0x01, 0x01, 0x7F}, // П
{0x7f, 0x09, 0x09, 0x09, 0x06}, // Р
{0x3e, 0x41, 0x41, 0x41, 0x22}, // С
{0x01, 0x01, 0x7f, 0x01, 0x01}, // Т
{0x07, 0x48, 0x48, 0x48, 0x7F}, // У
{0x1C, 0x22, 0x7F, 0x22, 0x1C}, // Ф
{0x63, 0x14, 0x08, 0x14, 0x63}, // Х
{0x7F, 0x40, 0x40, 0x7F, 0xC0}, // Ц
{0x07, 0x08, 0x08, 0x08, 0x7F}, // Ч
{0x7F, 0x40, 0x7F, 0x40, 0x7F}, // Ш
{0x7F, 0x40, 0x7F, 0x40, 0xFF}, // Щ
{0x01, 0x7F, 0x48, 0x48, 0x70}, // Ъ
{0x7F, 0x48, 0x70, 0x00, 0x7F}, // Ы
{0x00, 0x7F, 0x48, 0x48, 0x70}, // Ь
{0x22, 0x41, 0x49, 0x49, 0x3E}, // Э
{0x7F, 0x08, 0x3E, 0x41, 0x3E}, // Ю
{0x46, 0x29, 0x19, 0x09, 0x7F}, // Я 223
{0x20, 0x54, 0x54, 0x54, 0x78}, //a 224
{0x3c, 0x4a, 0x4a, 0x49, 0x31}, //б
{0x7c, 0x54, 0x54, 0x28, 0x00}, //в
{0x7c, 0x04, 0x04, 0x04, 0x0c}, //г
{0xe0, 0x54, 0x4c, 0x44, 0xfc}, //д
{0x38, 0x54, 0x54, 0x54, 0x18}, //e
{0x6c, 0x10, 0x7c, 0x10, 0x6c}, //ж
{0x44, 0x44, 0x54, 0x54, 0x28}, //з
{0x7c, 0x20, 0x10, 0x08, 0x7c}, //и
{0x7c, 0x41, 0x22, 0x11, 0x7c}, //й
{0x7c, 0x10, 0x28, 0x44, 0x00}, //к
{0x20, 0x44, 0x3c, 0x04, 0x7c}, //л
{0x7c, 0x08, 0x10, 0x08, 0x7c}, //м
{0x7c, 0x10, 0x10, 0x10, 0x7c}, //н
{0x38, 0x44, 0x44, 0x44, 0x38}, //o
{0x7c, 0x04, 0x04, 0x04, 0x7c}, //п
{0x7C, 0x14, 0x14, 0x14, 0x08}, //p
{0x38, 0x44, 0x44, 0x44, 0x20}, //c
{0x04, 0x04, 0x7c, 0x04, 0x04}, //т
{0x0C, 0x50, 0x50, 0x50, 0x3C}, //у
{0x30, 0x48, 0xfc, 0x48, 0x30}, //ф
{0x44, 0x28, 0x10, 0x28, 0x44}, //x
{0x7c, 0x40, 0x40, 0x40, 0xfc}, //ц
{0x0c, 0x10, 0x10, 0x10, 0x7c}, //ч
{0x7c, 0x40, 0x7c, 0x40, 0x7c}, //ш
{0x7c, 0x40, 0x7c, 0x40, 0xfc}, //щ
{0x04, 0x7c, 0x50, 0x50, 0x20}, //ъ
{0x7c, 0x50, 0x50, 0x20, 0x7c}, //ы
{0x7c, 0x50, 0x50, 0x20, 0x00}, //ь
{0x28, 0x44, 0x54, 0x54, 0x38}, //э
{0x7c, 0x10, 0x38, 0x44, 0x38}, //ю
{0x08, 0x54, 0x34, 0x14, 0x7c}, //я 255
*/
};

View File

@@ -0,0 +1,200 @@
// ******************* НАСТРОЙКИ *****************
// "масштаб" эффектов. Чем меньше, тем крупнее!
#define MADNESS_SCALE 100
#define CLOUD_SCALE 30
#define LAVA_SCALE 50
#define PLASMA_SCALE 30
#define RAINBOW_SCALE 30
#define RAINBOW_S_SCALE 20
#define ZEBRA_SCALE 30
#define FOREST_SCALE 120
#define OCEAN_SCALE 90
// ***************** ДЛЯ РАЗРАБОТЧИКОВ ******************
// The 16 bit version of our coordinates
static uint16_t x;
static uint16_t y;
static uint16_t z;
uint16_t speed = 20; // speed is set dynamically once we've started up
uint16_t scale = 30; // scale is set dynamically once we've started up
// This is the array that we keep our computed noise values in
#define MAX_DIMENSION (max(WIDTH, HEIGHT))
#if (WIDTH > HEIGHT)
uint8_t noise[WIDTH][WIDTH];
#else
uint8_t noise[HEIGHT][HEIGHT];
#endif
CRGBPalette16 currentPalette( PartyColors_p );
uint8_t colorLoop = 1;
uint8_t ihue = 0;
void madnessNoise() {
if (loadingFlag) {
loadingFlag = false;
scale = modes[5].scale;
speed = modes[5].speed;
}
fillnoise8();
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]);
drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = CHSV(noise[j][i], 255, noise[i][j]);
}
}
ihue += 1;
}
void rainbowNoise() {
if (loadingFlag) {
loadingFlag = false;
currentPalette = RainbowColors_p;
scale = modes[9].scale;
speed = modes[9].speed;
colorLoop = 1;
}
fillNoiseLED();
}
void rainbowStripeNoise() {
if (loadingFlag) {
loadingFlag = false;
currentPalette = RainbowStripeColors_p;
scale = modes[10].scale;
speed = modes[10].speed;
colorLoop = 1;
}
fillNoiseLED();
}
void zebraNoise() {
if (loadingFlag) {
loadingFlag = false;
// '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;
scale = modes[11].scale;
speed = modes[11].speed;
colorLoop = 1;
}
fillNoiseLED();
}
void forestNoise() {
if (loadingFlag) {
loadingFlag = false;
currentPalette = ForestColors_p;
scale = modes[12].scale;
speed = modes[12].speed;
colorLoop = 0;
}
fillNoiseLED();
}
void oceanNoise() {
if (loadingFlag) {
loadingFlag = false;
currentPalette = OceanColors_p;
scale = modes[13].scale;
speed = modes[13].speed;
colorLoop = 0;
}
fillNoiseLED();
}
void plasmaNoise() {
if (loadingFlag) {
loadingFlag = false;
currentPalette = PartyColors_p;
scale = modes[8].scale;
speed = modes[8].speed;
colorLoop = 1;
}
fillNoiseLED();
}
void cloudNoise() {
if (loadingFlag) {
loadingFlag = false;
currentPalette = CloudColors_p;
scale = modes[6].scale;
speed = modes[6].speed;
colorLoop = 0;
}
fillNoiseLED();
}
void lavaNoise() {
if (loadingFlag) {
loadingFlag = false;
currentPalette = LavaColors_p;
scale = modes[7].scale;
speed = modes[7].speed;
colorLoop = 0;
}
fillNoiseLED();
}
// ******************* СЛУЖЕБНЫЕ *******************
void fillNoiseLED() {
uint8_t dataSmoothing = 0;
if ( speed < 50) {
dataSmoothing = 200 - (speed * 4);
}
for (int i = 0; i < MAX_DIMENSION; i++) {
int ioffset = scale * i;
for (int j = 0; j < MAX_DIMENSION; j++) {
int joffset = scale * j;
uint8_t data = inoise8(x + ioffset, y + joffset, z);
data = qsub8(data, 16);
data = qadd8(data, scale8(data, 39));
if ( dataSmoothing ) {
uint8_t olddata = noise[i][j];
uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing);
data = newdata;
}
noise[i][j] = data;
}
}
z += speed;
// apply slow drift to X and Y, just for visual variation.
x += speed / 8;
y -= speed / 16;
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
uint8_t index = noise[j][i];
uint8_t bri = noise[i][j];
// if this palette is a 'loop', add a slowly-changing base value
if ( colorLoop) {
index += ihue;
}
// brighten up, as the color palette itself often contains the
// light/dark dynamic range desired
if ( bri > 127 ) {
bri = 255;
} else {
bri = dim8_raw( bri * 2);
}
CRGB color = ColorFromPalette( currentPalette, index, bri);
drawPixelXY(i, j, color); //leds[getPixelNumber(i, j)] = color;
}
}
ihue += 1;
}
void fillnoise8() {
for (int i = 0; i < MAX_DIMENSION; i++) {
int ioffset = scale * i;
for (int j = 0; j < MAX_DIMENSION; j++) {
int joffset = scale * j;
noise[i][j] = inoise8(x + ioffset, y + joffset, z);
}
}
z += speed;
}

View File

@@ -0,0 +1,102 @@
void parseUDP() {
int packetSize = Udp.parsePacket();
if (packetSize) {
int n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
packetBuffer[n] = 0;
inputBuffer = packetBuffer;
if (inputBuffer.startsWith("DEB")) {
inputBuffer = "OK " + timeClient.getFormattedTime();
} else if (inputBuffer.startsWith("GET")) {
sendCurrent();
} else if (inputBuffer.startsWith("EFF")) {
saveEEPROM();
currentMode = (byte)inputBuffer.substring(3).toInt();
loadingFlag = true;
FastLED.clear();
delay(1);
sendCurrent();
FastLED.setBrightness(modes[currentMode].brightness);
} else if (inputBuffer.startsWith("BRI")) {
modes[currentMode].brightness = inputBuffer.substring(3).toInt();
FastLED.setBrightness(modes[currentMode].brightness);
settChanged = true;
eepromTimer = millis();
} else if (inputBuffer.startsWith("SPD")) {
modes[currentMode].speed = inputBuffer.substring(3).toInt();
loadingFlag = true;
settChanged = true;
eepromTimer = millis();
} else if (inputBuffer.startsWith("SCA")) {
modes[currentMode].scale = inputBuffer.substring(3).toInt();
loadingFlag = true;
settChanged = true;
eepromTimer = millis();
} else if (inputBuffer.startsWith("P_ON")) {
ONflag = true;
changePower();
sendCurrent();
} else if (inputBuffer.startsWith("P_OFF")) {
ONflag = false;
changePower();
sendCurrent();
} else if (inputBuffer.startsWith("ALM_SET")) {
byte alarmNum = (char)inputBuffer[7] - '0';
alarmNum -= 1;
if (inputBuffer.indexOf("ON") != -1) {
alarm[alarmNum].state = true;
inputBuffer = "alm #" + String(alarmNum + 1) + " ON";
} else if (inputBuffer.indexOf("OFF") != -1) {
alarm[alarmNum].state = false;
inputBuffer = "alm #" + String(alarmNum + 1) + " OFF";
} else {
int almTime = inputBuffer.substring(8).toInt();
alarm[alarmNum].time = almTime;
byte hour = floor(almTime / 60);
byte minute = almTime - hour * 60;
inputBuffer = "alm #" + String(alarmNum + 1) +
" " + String(hour) +
":" + String(minute);
}
saveAlarm(alarmNum);
} else if (inputBuffer.startsWith("ALM_GET")) {
sendAlarms();
} else if (inputBuffer.startsWith("DAWN")) {
dawnMode = inputBuffer.substring(4).toInt() - 1;
saveDawnMmode();
}
char reply[inputBuffer.length() + 1];
inputBuffer.toCharArray(reply, inputBuffer.length() + 1);
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(reply);
Udp.endPacket();
}
}
void sendCurrent() {
inputBuffer = "CURR";
inputBuffer += " ";
inputBuffer += String(currentMode);
inputBuffer += " ";
inputBuffer += String(modes[currentMode].brightness);
inputBuffer += " ";
inputBuffer += String(modes[currentMode].speed);
inputBuffer += " ";
inputBuffer += String(modes[currentMode].scale);
inputBuffer += " ";
inputBuffer += String(ONflag);
}
void sendAlarms() {
inputBuffer = "ALMS ";
for (byte i = 0; i < 7; i++) {
inputBuffer += String(alarm[i].state);
inputBuffer += " ";
}
for (byte i = 0; i < 7; i++) {
inputBuffer += String(alarm[i].time);
inputBuffer += " ";
}
inputBuffer += (dawnMode + 1);
}

View File

@@ -0,0 +1,90 @@
// работа с бегущим текстом
// **************** НАСТРОЙКИ ****************
#define TEXT_DIRECTION 1 // 1 - по горизонтали, 0 - по вертикали
#define MIRR_V 0 // отразить текст по вертикали (0 / 1)
#define MIRR_H 0 // отразить текст по горизонтали (0 / 1)
#define TEXT_HEIGHT 0 // высота, на которой бежит текст (от низа матрицы)
#define LET_WIDTH 5 // ширина буквы шрифта
#define LET_HEIGHT 8 // высота буквы шрифта
#define SPACE 1 // пробел
// --------------------- ДЛЯ РАЗРАБОТЧИКОВ ----------------------
int offset = WIDTH;
uint32_t scrollTimer;
boolean fillString(String text) {
if (loadingFlag) {
offset = WIDTH; // перемотка в правый край
loadingFlag = false;
}
if (millis() - scrollTimer >= 100) {
scrollTimer = millis();
FastLED.clear();
byte i = 0, j = 0;
while (text[i] != '\0') {
if ((byte)text[i] > 191) { // работаем с русскими буквами!
i++;
} else {
drawLetter(j, text[i], offset + j * (LET_WIDTH + SPACE));
i++;
j++;
}
}
offset--;
if (offset < -j * (LET_WIDTH + SPACE)) { // строка убежала
offset = WIDTH + 3;
return true;
}
FastLED.show();
}
return false;
}
void drawLetter(uint8_t index, uint8_t letter, int16_t offset) {
int8_t start_pos = 0, finish_pos = LET_WIDTH;
CRGB letterColor = CRGB::White;
if (offset < -LET_WIDTH || offset > WIDTH) return;
if (offset < 0) start_pos = -offset;
if (offset > (WIDTH - LET_WIDTH)) finish_pos = WIDTH - offset;
for (byte i = start_pos; i < finish_pos; i++) {
int thisByte;
if (MIRR_V) thisByte = getFont((byte)letter, LET_WIDTH - 1 - i);
else thisByte = getFont((byte)letter, i);
for (byte j = 0; j < LET_HEIGHT; j++) {
boolean thisBit;
if (MIRR_H) thisBit = thisByte & (1 << j);
else thisBit = thisByte & (1 << (LET_HEIGHT - 1 - j));
// рисуем столбец (i - горизонтальная позиция, j - вертикальная)
if (TEXT_DIRECTION) {
if (thisBit) leds[getPixelNumber(offset + i, TEXT_HEIGHT + j)] = letterColor;
else drawPixelXY(offset + i, TEXT_HEIGHT + j, 0x000000);
} else {
if (thisBit) leds[getPixelNumber(i, offset + TEXT_HEIGHT + j)] = letterColor;
else drawPixelXY(i, offset + TEXT_HEIGHT + j, 0x000000);
}
}
}
}
// ------------- СЛУЖЕБНЫЕ ФУНКЦИИ --------------
// интерпретатор кода символа в массиве fontHEX (для Arduino IDE 1.8.* и выше)
uint8_t getFont(uint8_t font, uint8_t row) {
font = font - '0' + 16; // перевод код символа из таблицы ASCII в номер согласно нумерации массива
if (font <= 90) return pgm_read_byte(&(fontHEX[font][row])); // для английских букв и символов
else if (font >= 112 && font <= 159) { // и пизд*ц ждя русских
return pgm_read_byte(&(fontHEX[font - 17][row]));
} else if (font >= 96 && font <= 111) {
return pgm_read_byte(&(fontHEX[font + 47][row]));
}
}

View File

@@ -0,0 +1,36 @@
void timeTick() {
if (ESP_MODE == 1) {
if (timeTimer.isReady()) {
timeClient.update();
byte thisDay = timeClient.getDay();
if (thisDay == 0) thisDay = 7; // воскресенье это 0
thisDay--;
thisTime = timeClient.getHours() * 60 + timeClient.getMinutes();
// проверка рассвета
if (alarm[thisDay].state && // день будильника
thisTime >= (alarm[thisDay].time - dawnOffsets[dawnMode]) && // позже начала
thisTime < (alarm[thisDay].time + DAWN_TIMEOUT) ) { // раньше конца + минута
if (!manualOff) {
// величина рассвета 0-255
int dawnPosition = 255 * ((float)(thisTime - (alarm[thisDay].time - dawnOffsets[dawnMode])) / dawnOffsets[dawnMode]);
dawnPosition = constrain(dawnPosition, 0, 255);
CHSV dawnColor = CHSV(map(dawnPosition, 0, 255, 10, 35),
map(dawnPosition, 0, 255, 255, 170),
map(dawnPosition, 0, 255, 10, DAWN_BRIGHT));
fill_solid(leds, NUM_LEDS, dawnColor);
FastLED.setBrightness(255);
FastLED.show();
dawnFlag = true;
}
} else {
if (dawnFlag) {
dawnFlag = false;
manualOff = false;
FastLED.setBrightness(modes[currentMode].brightness);
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
// мини-класс таймера, версия 1.0
class timerMinim
{
public:
timerMinim(uint32_t interval); // объявление таймера с указанием интервала
void setInterval(uint32_t interval); // установка интервала работы таймера
boolean isReady(); // возвращает true, когда пришло время. Сбрасывается в false сам (AUTO) или вручную (MANUAL)
void reset(); // ручной сброс таймера на установленный интервал
private:
uint32_t _timer = 0;
uint32_t _interval = 0;
};
timerMinim::timerMinim(uint32_t interval) {
_interval = interval;
_timer = millis();
}
void timerMinim::setInterval(uint32_t interval) {
_interval = interval;
}
boolean timerMinim::isReady() {
if ((long)millis() - _timer >= _interval) {
_timer = millis();
return true;
} else {
return false;
}
}
void timerMinim::reset() {
_timer = millis();
}

View File

@@ -0,0 +1,87 @@
// служебные функции
// залить все
void fillAll(CRGB color) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = color;
}
}
// функция отрисовки точки по координатам X Y
void drawPixelXY(int8_t x, int8_t y, CRGB color) {
if (x < 0 || x > WIDTH - 1 || y < 0 || y > HEIGHT - 1) return;
int thisPixel = getPixelNumber(x, y) * SEGMENTS;
for (byte i = 0; i < SEGMENTS; i++) {
leds[thisPixel + i] = color;
}
}
// функция получения цвета пикселя по его номеру
uint32_t getPixColor(int thisSegm) {
int thisPixel = thisSegm * SEGMENTS;
if (thisPixel < 0 || thisPixel > NUM_LEDS - 1) return 0;
return (((uint32_t)leds[thisPixel].r << 16) | ((long)leds[thisPixel].g << 8 ) | (long)leds[thisPixel].b);
}
// функция получения цвета пикселя в матрице по его координатам
uint32_t getPixColorXY(int8_t x, int8_t y) {
return getPixColor(getPixelNumber(x, y));
}
// **************** НАСТРОЙКА МАТРИЦЫ ****************
#if (CONNECTION_ANGLE == 0 && STRIP_DIRECTION == 0)
#define _WIDTH WIDTH
#define THIS_X x
#define THIS_Y y
#elif (CONNECTION_ANGLE == 0 && STRIP_DIRECTION == 1)
#define _WIDTH HEIGHT
#define THIS_X y
#define THIS_Y x
#elif (CONNECTION_ANGLE == 1 && STRIP_DIRECTION == 0)
#define _WIDTH WIDTH
#define THIS_X x
#define THIS_Y (HEIGHT - y - 1)
#elif (CONNECTION_ANGLE == 1 && STRIP_DIRECTION == 3)
#define _WIDTH HEIGHT
#define THIS_X (HEIGHT - y - 1)
#define THIS_Y x
#elif (CONNECTION_ANGLE == 2 && STRIP_DIRECTION == 2)
#define _WIDTH WIDTH
#define THIS_X (WIDTH - x - 1)
#define THIS_Y (HEIGHT - y - 1)
#elif (CONNECTION_ANGLE == 2 && STRIP_DIRECTION == 3)
#define _WIDTH HEIGHT
#define THIS_X (HEIGHT - y - 1)
#define THIS_Y (WIDTH - x - 1)
#elif (CONNECTION_ANGLE == 3 && STRIP_DIRECTION == 2)
#define _WIDTH WIDTH
#define THIS_X (WIDTH - x - 1)
#define THIS_Y y
#elif (CONNECTION_ANGLE == 3 && STRIP_DIRECTION == 1)
#define _WIDTH HEIGHT
#define THIS_X y
#define THIS_Y (WIDTH - x - 1)
#else
#define _WIDTH WIDTH
#define THIS_X x
#define THIS_Y y
#pragma message "Wrong matrix parameters! Set to default"
#endif
// получить номер пикселя в ленте по координатам
uint16_t getPixelNumber(int8_t x, int8_t y) {
if ((THIS_Y % 2 == 0) || MATRIX_TYPE) { // если чётная строка
return (THIS_Y * _WIDTH + THIS_X);
} else { // если нечётная строка
return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1);
}
}