mirror of
https://github.com/gunner47/GyverLamp.git
synced 2025-08-07 17:10:30 +03:00
add
This commit is contained in:
249
firmware/GyverLamp_v1.2/GyverLamp_v1.2.ino
Normal file
249
firmware/GyverLamp_v1.2/GyverLamp_v1.2.ino
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
Скетч к проекту "Многофункциональный RGB светильник"
|
||||
Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/
|
||||
Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/
|
||||
Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/
|
||||
Автор: AlexGyver, AlexGyver Technologies, 2019
|
||||
https://AlexGyver.ru/
|
||||
*/
|
||||
|
||||
/*
|
||||
Версия 1.2:
|
||||
- Добавлена настройка статического IP
|
||||
- Добавлен эффект "Цвет"
|
||||
- Добавлен эффект "Снег"
|
||||
- Добавлен эффект "Матрица"
|
||||
- Добавлен эффект "Светлячки"
|
||||
*/
|
||||
|
||||
// Ссылка для менеджера плат:
|
||||
// http://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
|
||||
// ============= НАСТРОЙКИ =============
|
||||
// -------- ВРЕМЯ -------
|
||||
#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 точки доступа (менять только последнюю цифру)
|
||||
byte IP_STA[] = {192, 168, 1, 66}; // статический IP локальный (менять только последнюю цифру)
|
||||
|
||||
// -------- Менеджер WiFi ---------
|
||||
#define AC_SSID "AutoConnectAP"
|
||||
#define AC_PASS "12345678"
|
||||
|
||||
// -------------- AP ---------------
|
||||
#define AP_SSID "GyverLamp"
|
||||
#define AP_PASS "12345678"
|
||||
#define AP_PORT 8888
|
||||
|
||||
// ============= ДЛЯ РАЗРАБОТЧИКОВ =============
|
||||
#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>
|
||||
|
||||
// ------------------- ТИПЫ --------------------
|
||||
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];
|
||||
|
||||
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.clear();
|
||||
FastLED.show();
|
||||
|
||||
touch.setStepTimeout(100);
|
||||
touch.setClickTimeout(500);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
// 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);
|
||||
//wifiManager.resetSettings();
|
||||
|
||||
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());
|
||||
}
|
||||
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();
|
||||
buttonTick();
|
||||
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;
|
||||
}
|
55
firmware/GyverLamp_v1.2/button.ino
Normal file
55
firmware/GyverLamp_v1.2/button.ino
Normal file
@@ -0,0 +1,55 @@
|
||||
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();
|
||||
}
|
||||
if (ONflag && touch.isTriple()) {
|
||||
if (--currentMode < 0) currentMode = 0;
|
||||
FastLED.setBrightness(modes[currentMode].brightness);
|
||||
loadingFlag = true;
|
||||
settChanged = true;
|
||||
eepromTimer = millis();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
25
firmware/GyverLamp_v1.2/eeprom.ino
Normal file
25
firmware/GyverLamp_v1.2/eeprom.ino
Normal 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();
|
||||
}
|
70
firmware/GyverLamp_v1.2/effectTicker.ino
Normal file
70
firmware/GyverLamp_v1.2/effectTicker.ino
Normal file
@@ -0,0 +1,70 @@
|
||||
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);
|
||||
FastLED.show();
|
||||
} else {
|
||||
effectsTick();
|
||||
for (int i = modes[currentMode].brightness; i > 8; i -= 8) {
|
||||
FastLED.setBrightness(i);
|
||||
delay(1);
|
||||
FastLED.show();
|
||||
}
|
||||
FastLED.clear();
|
||||
FastLED.show();
|
||||
}
|
||||
}
|
275
firmware/GyverLamp_v1.2/effects.ino
Normal file
275
firmware/GyverLamp_v1.2/effects.ino
Normal file
@@ -0,0 +1,275 @@
|
||||
// ================================= ЭФФЕКТЫ ====================================
|
||||
|
||||
// --------------------------------- конфетти ------------------------------------
|
||||
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;
|
||||
|
||||
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 > 70) 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]);
|
||||
}
|
||||
}
|
200
firmware/GyverLamp_v1.2/noiseEffects.ino
Normal file
200
firmware/GyverLamp_v1.2/noiseEffects.ino
Normal 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;
|
||||
}
|
101
firmware/GyverLamp_v1.2/parsing.ino
Normal file
101
firmware/GyverLamp_v1.2/parsing.ino
Normal file
@@ -0,0 +1,101 @@
|
||||
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();
|
||||
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);
|
||||
}
|
34
firmware/GyverLamp_v1.2/time.ino
Normal file
34
firmware/GyverLamp_v1.2/time.ino
Normal file
@@ -0,0 +1,34 @@
|
||||
void timeTick() {
|
||||
timeClient.update();
|
||||
if (timeTimer.isReady()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
36
firmware/GyverLamp_v1.2/timerMinim.h
Normal file
36
firmware/GyverLamp_v1.2/timerMinim.h
Normal 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();
|
||||
}
|
87
firmware/GyverLamp_v1.2/utility.ino
Normal file
87
firmware/GyverLamp_v1.2/utility.ino
Normal 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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user