WiFi подключение переработано, код переформатирован, добавлены комментарии

This commit is contained in:
gunner47
2019-07-16 22:50:56 +03:00
parent 90a13acc74
commit 0965f3d46a
10 changed files with 625 additions and 317 deletions

View File

@@ -16,58 +16,64 @@
// Ссылка для менеджера плат: // Ссылка для менеджера плат:
// http://arduino.esp8266.com/stable/package_esp8266com_index.json // http://arduino.esp8266.com/stable/package_esp8266com_index.json
// ============= НАСТРОЙКИ ============= // ============= НАСТРОЙКИ =============
// -------- ВРЕМЯ ------- // --- ВРЕМЯ ---------------------------
#define GMT 3 // смещение (москва 3) #define USE_NTP // закомментировать или удалить эту строку, если не нужно, чтобы устройство не лезло в интернет
#define NTP_ADDRESS "europe.pool.ntp.org" // сервер времени #define GMT (3) // часовой пояс (москва 3)
#define NTP_ADDRESS "europe.pool.ntp.org" // сервер времени
// -------- РАССВЕТ ------- // --- РАССВЕТ -------------------------
#define DAWN_BRIGHT 200 // макс. яркость рассвета #define DAWN_BRIGHT (200U) // максимальная яркость рассвета (0-255)
#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут #define DAWN_TIMEOUT (1U) // сколько рассвет светит после времени будильника, минут
// ---------- МАТРИЦА --------- // --- МАТРИЦА -------------------------
#define BRIGHTNESS 40 // стандартная маскимальная яркость (0-255) #define BRIGHTNESS (40U) // стандартная маскимальная яркость (0-255)
#define CURRENT_LIMIT 2000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит #define CURRENT_LIMIT (2000U) // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит
#define WIDTH 16 // ширина матрицы #define WIDTH (16U) // ширина матрицы
#define HEIGHT 16 // высота матрицы #define HEIGHT (16U) // высота матрицы
#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB #define COLOR_ORDER (GRB) // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB
#define MATRIX_TYPE 0 // тип матрицы: 0 - зигзаг, 1 - параллельная #define MATRIX_TYPE (0U) // тип матрицы: 0 - зигзаг, 1 - параллельная
#define CONNECTION_ANGLE 0 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний #define CONNECTION_ANGLE (0U) // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз #define STRIP_DIRECTION (0U) // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз
// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" // при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default"
// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ // шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/
// --------- ESP -------- // --- ESP -----------------------------
#define ESP_MODE 1 #define ESP_MODE (1U) // 0U - WiFi точка доступа, 1U - клиент WiFi (подключение к роутеру)
// 0 - точка доступа #define ESP_USE_BUTTON // если строка не закомментирована, должна быть подключена кнопка (иначе ESP может регистрировать "фантомные" нажатия и некорректно устанавливать яркость)
// 1 - локальный #define ESP_HTTP_PORT (80U) // номер порта, который будет использоваться во время первой утановки имени WiFi сети (и пароля), к которой потом будет подключаться лампа в режиме WiFi клиента (лучше не менять)
byte IP_AP[] = {192, 168, 4, 66}; // статический IP точки доступа (менять только последнюю цифру) #define ESP_UDP_PORT (8888U) // номер порта, который будет "слушать" UDP сервер во время работы лампы как в режиме WiFi точки доступа, так и в режиме WiFi клиента (лучше не менять)
byte IP_STA[] = {192, 168, 1, 66}; // статический IP локальный (менять только последнюю цифру) #define ESP_CONN_TIMEOUT (7U) // время в секундах (ДОЛЖНО БЫТЬ МЕНЬШЕ 8, иначе сработает WDT), которое ESP будет пытаться подключиться к WiFi сети, после его истечения автоматически развернёт WiFi точку доступа
#define ESP_CONF_TIMEOUT (300U) // время в секундах, которое ESP будет ждать ввода SSID и пароля WiFi сети роутера в конфигурационном режиме, после его истечения ESP перезагружается
#define GENERAL_DEBUG // если строка не закомментирована, будут выводиться отладочные сообщения
#define WIFIMAN_DEBUG (true) // вывод отладочных сообщений при подключении к WiFi сети: true - выводятся, false - не выводятся; настройка не зависит от GENERAL_DEBUG
// ----- AP (точка доступа) ------- // --- ESP (WiFi клиент) ---------------
#define AP_SSID "GyverLamp" uint8_t STA_STATIC_IP[] ={}; // статический IP адрес: {} - IP адрес определяется роутером; {192, 168, 1, 66} - IP адрес задан явно (если DHCP на роутере не решит иначе); должен быть из того же диапазона адресов, что разадёт роутер
#define AP_PASS "12345678" // SSID WiFi сети и пароль будут запрошены WiFi Manager'ом в режиме WiFi точки доступа, нет способа захардкодить их в прошивке
#define AP_PORT 8888
// -------- Менеджер WiFi --------- // --- AP (WiFi точка доступа) ---
#define AC_SSID "AutoConnectAP" #define AP_NAME ("GyverLamp") // имя WiFi точки доступа, используется как при запросе SSID и пароля WiFi сети роутера, так и при работе в режиме ESP_MODE = 0
#define AC_PASS "12345678" #define AP_PASS ("12345678") // пароль WiFi точки доступа
uint8_t AP_STATIC_IP[] = {192, 168, 4, 1}; // статический IP точки доступа (лучше не менять)
// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= // ============= ДЛЯ РАЗРАБОТЧИКОВ =====
#define LED_PIN 2 // пин ленты #define LED_PIN (2U) // пин ленты
#define BTN_PIN 4 #define BTN_PIN (4U) // пин кнопки
#define MODE_AMOUNT 18 #define MODE_AMOUNT (18U)
#define NUM_LEDS WIDTH * HEIGHT #define NUM_LEDS (WIDTH * HEIGHT)
#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) #define SEGMENTS (1U) // диодов в одном "пикселе" (для создания матрицы из кусков ленты)
// ---------------- БИБЛИОТЕКИ -----------------
#define FASTLED_INTERRUPT_RETRY_COUNT 0 // --- БИБЛИОТЕКИ ----------------------
#define FASTLED_ALLOW_INTERRUPTS 0 #define FASTLED_INTERRUPT_RETRY_COUNT (0U)
#define FASTLED_ALLOW_INTERRUPTS (0U)
#define FASTLED_ESP8266_RAW_PIN_ORDER #define FASTLED_ESP8266_RAW_PIN_ORDER
#define NTP_INTERVAL 60 * 1000 // обновление (1 минута) #define NTP_INTERVAL (30UL * 60UL * 1000UL)// интервал синхронизации времени (30 минут)
#include "timerMinim.h" #include "timerMinim.h"
#include <FastLED.h> #include <FastLED.h>
@@ -77,40 +83,48 @@ byte IP_STA[] = {192, 168, 1, 66}; // статический IP локальн
#include <WiFiManager.h> #include <WiFiManager.h>
#include <WiFiUdp.h> #include <WiFiUdp.h>
#include <EEPROM.h> #include <EEPROM.h>
#include <NTPClient.h> #ifdef ESP_USE_BUTTON
#include <GyverButton.h> #include <GyverButton.h>
#endif
#ifdef USE_NTP
#include <NTPClient.h>
#endif
// ------------------- ТИПЫ -------------------- // --- ИНИЦИАЛИЗАЦИЯ ОБЪЕКТОВ ----------
CRGB leds[NUM_LEDS]; CRGB leds[NUM_LEDS];
WiFiServer server(80); WiFiManager wifiManager;
WiFiServer wifiServer(ESP_HTTP_PORT);
WiFiUDP Udp; WiFiUDP Udp;
WiFiUDP ntpUDP; WiFiUDP ntpUDP;
#ifdef USE_NTP
NTPClient timeClient(ntpUDP, NTP_ADDRESS, GMT * 3600, NTP_INTERVAL); NTPClient timeClient(ntpUDP, NTP_ADDRESS, GMT * 3600, NTP_INTERVAL);
#endif
timerMinim timeTimer(3000); timerMinim timeTimer(3000);
#ifdef ESP_USE_BUTTON
GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN);
#endif
// ----------------- ПЕРЕМЕННЫЕ ------------------ // --- ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ -------
const char* autoConnectSSID = AC_SSID; uint16_t localPort = ESP_UDP_PORT;
const char* autoConnectPass = AC_PASS; char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; // buffer to hold incoming packet
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; String inputBuffer;
static const byte maxDim = max(WIDTH, HEIGHT); static const uint8_t maxDim = max(WIDTH, HEIGHT);
struct {
byte brightness = 50; struct
byte speed = 30; {
byte scale = 40; uint8_t brightness = 50;
uint8_t speed = 30;
uint8_t scale = 40;
} modes[MODE_AMOUNT]; } modes[MODE_AMOUNT];
struct { struct
{
boolean state = false; boolean state = false;
int time = 0; int16_t time = 0;
} alarm[7]; } alarm[7];
byte dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60}; uint8_t dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60};
byte dawnMode; uint8_t dawnMode;
boolean dawnFlag = false; boolean dawnFlag = false;
long thisTime; long thisTime;
boolean manualOff = false; boolean manualOff = false;
@@ -126,7 +140,9 @@ boolean settChanged = false;
unsigned char matrixValue[8][16]; unsigned char matrixValue[8][16];
void setup() {
void setup()
{
ESP.wdtDisable(); ESP.wdtDisable();
//ESP.wdtEnable(WDTO_8S); //ESP.wdtEnable(WDTO_8S);
@@ -137,97 +153,152 @@ void setup() {
FastLED.clear(); FastLED.clear();
FastLED.show(); FastLED.show();
#ifdef ESP_USE_BUTTON
touch.setStepTimeout(100); touch.setStepTimeout(100);
touch.setClickTimeout(500); touch.setClickTimeout(500);
#endif
Serial.begin(115200); Serial.begin(115200);
Serial.println(); Serial.println();
// WI-FI // WI-FI
if (ESP_MODE == 0) { // режим точки доступа wifiManager.setDebugOutput(WIFIMAN_DEBUG); // вывод отладочных сообщений
WiFi.softAPConfig(IPAddress(IP_AP[0], IP_AP[1], IP_AP[2], IP_AP[3]), if (ESP_MODE == 0) // режим WiFi точки доступа
IPAddress(192, 168, 4, 1), {
IPAddress(255, 255, 255, 0)); WiFi.softAPConfig( // wifiManager.startConfigPortal использовать нельзя, т.к. он блокирует вычислительный процесс внутри себя, а затем перезагружает ESP, т.е. предназначен только для ввода SSID и пароля
IPAddress(AP_STATIC_IP[0], AP_STATIC_IP[1], AP_STATIC_IP[2], AP_STATIC_IP[3]), // IP адрес WiFi точки доступа
IPAddress(AP_STATIC_IP[0], AP_STATIC_IP[1], AP_STATIC_IP[2], 1), // первый доступный IP адрес сети
IPAddress(255, 255, 255, 0)); // маска подсети
WiFi.softAP(AP_NameChar, WiFiPassword); WiFi.softAP(AP_NAME, AP_PASS);
IPAddress myIP = WiFi.softAPIP();
Serial.print("Access point Mode");
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin(); Serial.println("Режим WiFi точки доступа");
} else { // подключаемся к роутеру Serial.print("IP адрес: ");
Serial.print("WiFi manager"); Serial.println(WiFi.softAPIP());
WiFiManager wifiManager;
wifiManager.setDebugOutput(false); wifiServer.begin();
}
else
{ // режим WiFi клиента (подключаемся к роутеру, если есть сохранённые SSID и пароль, иначе создаём WiFi точку доступа и запрашиваем их)
Serial.println("Режим WiFi клиента");
if (WiFi.SSID())
{
Serial.print("Подключение WiFi сети: ");
Serial.println(WiFi.SSID());
}
else
{
Serial.println("WiFi сеть не определена, запуск WiFi точки доступа для настройки параметров подключения к WiFi сети...");
}
//wifiManager.resetSettings(); //wifiManager.resetSettings();
wifiManager.autoConnect(autoConnectSSID, autoConnectPass); if (STA_STATIC_IP)
WiFi.config(IPAddress(IP_STA[0], IP_STA[1], IP_STA[2], IP_STA[3]), {
IPAddress(192, 168, 1, 1), wifiManager.setSTAStaticIPConfig(
IPAddress(255, 255, 255, 0)); IPAddress(STA_STATIC_IP[0], STA_STATIC_IP[1], STA_STATIC_IP[2], STA_STATIC_IP[3]), // статический IP адрес ESP в режиме WiFi клиента
Serial.print("Connected! IP address: "); IPAddress(STA_STATIC_IP[0], STA_STATIC_IP[1], STA_STATIC_IP[2], 1), // первый доступный IP адрес сети (справедливо для 99,99% случаев; для сетей меньше чем на 255 адресов нужно вынести в константы)
IPAddress(255, 255, 255, 0)); // маска подсети (справедливо для 99,99% случаев; для сетей меньше чем на 255 адресов нужно вынести в константы)
}
wifiManager.setConnectTimeout(ESP_CONN_TIMEOUT); // установка времени ожидания подключения к WiFi сети, затем старт WiFi точки доступа
wifiManager.setConfigPortalTimeout(ESP_CONF_TIMEOUT); // установка времени работы WiFi точки доступа, затем перезагрузка; отключить watchdog?
wifiManager.autoConnect(AP_NAME, AP_PASS); // пытаемся подключиться к сохранённой ранее WiFi сети; в случае ошибки, будет развёрнута WiFi точка доступа с указанными AP_NAME и паролем на время ESP_CONN_TIMEOUT секунд; http://AP_STATIC_IP:ESP_HTTP_PORT (обычно http://192.168.0.1:80) - страница для ввода SSID и пароля от WiFi сети роутера
if (WiFi.status() != WL_CONNECTED)
{
Serial.printf("Время ожидания ввода SSID и пароля от WiFi сети или подключения к WiFi сети превышено\nПерезагрузка модуля");
#if defined(ESP8266)
ESP.reset();
#else
ESP.restart();
#endif
}
Serial.print("IP адрес: ");
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
} }
Serial.printf("UDP server on port %d\n", localPort);
Serial.printf("Порт UDP сервера: %u\n", localPort);
Udp.begin(localPort); Udp.begin(localPort);
// EEPROM // EEPROM
EEPROM.begin(202); EEPROM.begin(202);
delay(50); delay(50);
if (EEPROM.read(198) != 20) { // первый запуск if (EEPROM.read(198) != 20) // первый запуск
{
EEPROM.write(198, 20); EEPROM.write(198, 20);
EEPROM.commit(); EEPROM.commit();
for (byte i = 0; i < MODE_AMOUNT; i++) { for (uint8_t i = 0; i < MODE_AMOUNT; i++)
{
EEPROM.put(3 * i + 40, modes[i]); EEPROM.put(3 * i + 40, modes[i]);
EEPROM.commit(); EEPROM.commit();
} }
for (byte i = 0; i < 7; i++) {
EEPROM.write(5 * i, alarm[i].state); // рассвет for (uint8_t i = 0; i < 7; i++)
{
EEPROM.write(5 * i, alarm[i].state); // рассвет
eeWriteInt(5 * i + 1, alarm[i].time); eeWriteInt(5 * i + 1, alarm[i].time);
EEPROM.commit(); EEPROM.commit();
} }
EEPROM.write(199, 0); // рассвет
EEPROM.write(200, 0); // режим EEPROM.write(199, 0); // рассвет
EEPROM.write(200, 0); // режим
EEPROM.commit(); EEPROM.commit();
} }
for (byte i = 0; i < MODE_AMOUNT; i++) {
for (uint8_t i = 0; i < MODE_AMOUNT; i++)
{
EEPROM.get(3 * i + 40, modes[i]); EEPROM.get(3 * i + 40, modes[i]);
} }
for (byte i = 0; i < 7; i++) {
for (uint8_t i = 0; i < 7; i++)
{
alarm[i].state = EEPROM.read(5 * i); alarm[i].state = EEPROM.read(5 * i);
alarm[i].time = eeGetInt(5 * i + 1); alarm[i].time = eeGetInt(5 * i + 1);
} }
dawnMode = EEPROM.read(199); dawnMode = EEPROM.read(199);
currentMode = (int8_t)EEPROM.read(200); currentMode = (int8_t)EEPROM.read(200);
// отправляем настройки sendCurrent(); // отправляем настройки
sendCurrent();
char reply[inputBuffer.length() + 1]; char reply[inputBuffer.length() + 1];
inputBuffer.toCharArray(reply, inputBuffer.length() + 1); inputBuffer.toCharArray(reply, inputBuffer.length() + 1);
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(reply); Udp.write(reply);
Udp.endPacket(); Udp.endPacket();
#ifdef USE_NTP
timeClient.begin(); timeClient.begin();
#endif
memset(matrixValue, 0, sizeof(matrixValue)); memset(matrixValue, 0, sizeof(matrixValue));
randomSeed(micros()); randomSeed(micros());
} }
void loop() {
void loop()
{
parseUDP(); parseUDP();
effectsTick(); effectsTick();
eepromTick(); eepromTick();
#ifdef USE_NTP
timeTick(); timeTick();
#endif
#ifdef ESP_USE_BUTTON
buttonTick(); buttonTick();
ESP.wdtFeed(); // пнуть собаку #endif
yield(); ESP.wdtFeed(); // пнуть собаку
yield(); // обработать все "служебные" задачи: WiFi подключение и т.д.
} }
void eeWriteInt(int pos, int val) {
byte* p = (byte*) &val; void eeWriteInt(int16_t pos, int16_t val)
{
uint8_t* p = (uint8_t*) &val;
EEPROM.write(pos, *p); EEPROM.write(pos, *p);
EEPROM.write(pos + 1, *(p + 1)); EEPROM.write(pos + 1, *(p + 1));
EEPROM.write(pos + 2, *(p + 2)); EEPROM.write(pos + 2, *(p + 2));
@@ -235,9 +306,11 @@ void eeWriteInt(int pos, int val) {
EEPROM.commit(); EEPROM.commit();
} }
int eeGetInt(int pos) {
int val; int16_t eeGetInt(int16_t pos)
byte* p = (byte*) &val; {
int16_t val;
uint8_t* p = (uint8_t*) &val;
*p = EEPROM.read(pos); *p = EEPROM.read(pos);
*(p + 1) = EEPROM.read(pos + 1); *(p + 1) = EEPROM.read(pos + 1);
*(p + 2) = EEPROM.read(pos + 2); *(p + 2) = EEPROM.read(pos + 2);

View File

@@ -1,26 +1,36 @@
#ifdef ESP_USE_BUTTON
boolean brightDirection; boolean brightDirection;
void buttonTick() { void buttonTick()
{
touch.tick(); touch.tick();
if (touch.isSingle()) { if (touch.isSingle())
if (dawnFlag) { {
if (dawnFlag)
{
manualOff = true; manualOff = true;
dawnFlag = false; dawnFlag = false;
loadingFlag = true; loadingFlag = true;
FastLED.setBrightness(modes[currentMode].brightness); FastLED.setBrightness(modes[currentMode].brightness);
changePower(); changePower();
} else { }
if (ONflag) { else
{
if (ONflag)
{
ONflag = false; ONflag = false;
changePower(); changePower();
} else { }
else
{
ONflag = true; ONflag = true;
changePower(); changePower();
} }
} }
} }
if (ONflag && touch.isDouble()) { if (ONflag && touch.isDouble())
{
if (++currentMode >= MODE_AMOUNT) currentMode = 0; if (++currentMode >= MODE_AMOUNT) currentMode = 0;
FastLED.setBrightness(modes[currentMode].brightness); FastLED.setBrightness(modes[currentMode].brightness);
loadingFlag = true; loadingFlag = true;
@@ -29,7 +39,9 @@ void buttonTick() {
FastLED.clear(); FastLED.clear();
delay(1); delay(1);
} }
if (ONflag && touch.isTriple()) {
if (ONflag && touch.isTriple())
{
if (--currentMode < 0) currentMode = 0; if (--currentMode < 0) currentMode = 0;
FastLED.setBrightness(modes[currentMode].brightness); FastLED.setBrightness(modes[currentMode].brightness);
loadingFlag = true; loadingFlag = true;
@@ -39,21 +51,32 @@ void buttonTick() {
delay(1); delay(1);
} }
if (ONflag && touch.isHolded()) { if (ONflag && touch.isHolded())
{
brightDirection = !brightDirection; brightDirection = !brightDirection;
} }
if (ONflag && touch.isStep()) {
if (brightDirection) { if (ONflag && touch.isStep())
{
if (brightDirection)
{
if (modes[currentMode].brightness < 10) modes[currentMode].brightness += 1; if (modes[currentMode].brightness < 10) modes[currentMode].brightness += 1;
else if (modes[currentMode].brightness < 250) modes[currentMode].brightness += 5; else if (modes[currentMode].brightness < 250) modes[currentMode].brightness += 5;
else modes[currentMode].brightness = 255; else modes[currentMode].brightness = 255;
} else { }
else
{
if (modes[currentMode].brightness > 15) modes[currentMode].brightness -= 5; if (modes[currentMode].brightness > 15) modes[currentMode].brightness -= 5;
else if (modes[currentMode].brightness > 1) modes[currentMode].brightness -= 1; else if (modes[currentMode].brightness > 1) modes[currentMode].brightness -= 1;
else modes[currentMode].brightness = 1; else modes[currentMode].brightness = 0;
} }
FastLED.setBrightness(modes[currentMode].brightness); FastLED.setBrightness(modes[currentMode].brightness);
settChanged = true; settChanged = true;
eepromTimer = millis(); eepromTimer = millis();
#ifdef GENERAL_DEBUG
Serial.printf("New brightness value: %d\n", modes[currentMode].brightness);
#endif
} }
} }
#endif

View File

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

View File

@@ -1,10 +1,14 @@
uint32_t effTimer; uint32_t effTimer;
void effectsTick() { void effectsTick()
if (!dawnFlag) { {
if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { if (!dawnFlag)
{
if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) )
{
effTimer = millis(); effTimer = millis();
switch (currentMode) { switch (currentMode)
{
case 0: sparklesRoutine(); case 0: sparklesRoutine();
break; break;
case 1: fireRoutine(); case 1: fireRoutine();
@@ -47,10 +51,17 @@ void effectsTick() {
} }
} }
void changePower() { void changePower()
if (ONflag) { {
#ifdef GENERAL_DEBUG
Serial.printf("changePower(); brightness: %d\n", modes[currentMode].brightness);
#endif
if (ONflag)
{
effectsTick(); effectsTick();
for (int i = 0; i < modes[currentMode].brightness; i += 8) { for (uint8_t i = 0; i < modes[currentMode].brightness; i = constrain(i + 8, 0, modes[currentMode].brightness))
{
FastLED.setBrightness(i); FastLED.setBrightness(i);
delay(1); delay(1);
FastLED.show(); FastLED.show();
@@ -58,9 +69,12 @@ void changePower() {
FastLED.setBrightness(modes[currentMode].brightness); FastLED.setBrightness(modes[currentMode].brightness);
delay(2); delay(2);
FastLED.show(); FastLED.show();
} else { }
else
{
effectsTick(); effectsTick();
for (int i = modes[currentMode].brightness; i > 8; i -= 8) { for (uint8_t i = modes[currentMode].brightness; i > 0; i = constrain(i - 8, 0, modes[currentMode].brightness))
{
FastLED.setBrightness(i); FastLED.setBrightness(i);
delay(1); delay(1);
FastLED.show(); FastLED.show();

View File

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

View File

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

View File

@@ -1,15 +1,35 @@
void parseUDP() { void parseUDP()
int packetSize = Udp.parsePacket(); {
if (packetSize) { int32_t packetSize = Udp.parsePacket();
int n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
if (packetSize)
{
int32_t n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
packetBuffer[n] = 0; packetBuffer[n] = 0;
inputBuffer = packetBuffer; inputBuffer = packetBuffer;
if (inputBuffer.startsWith("DEB")) { #ifdef GENERAL_DEBUG
inputBuffer = "OK " + timeClient.getFormattedTime(); Serial.print("Inbound UDP packet: ");
} else if (inputBuffer.startsWith("GET")) { Serial.println(inputBuffer);
#endif
if (inputBuffer.startsWith("DEB"))
{
inputBuffer =
#ifdef USE_NTP
"OK " + timeClient.getFormattedTime();
#else
"OK --:--";
#endif
}
else if (inputBuffer.startsWith("GET"))
{
sendCurrent(); sendCurrent();
} else if (inputBuffer.startsWith("EFF")) { }
else if (inputBuffer.startsWith("EFF"))
{
saveEEPROM(); saveEEPROM();
currentMode = (byte)inputBuffer.substring(3).toInt(); currentMode = (byte)inputBuffer.substring(3).toInt();
loadingFlag = true; loadingFlag = true;
@@ -17,40 +37,71 @@ void parseUDP() {
delay(1); delay(1);
sendCurrent(); sendCurrent();
FastLED.setBrightness(modes[currentMode].brightness); FastLED.setBrightness(modes[currentMode].brightness);
} else if (inputBuffer.startsWith("BRI")) { }
modes[currentMode].brightness = inputBuffer.substring(3).toInt();
else if (inputBuffer.startsWith("BRI"))
{
#ifdef GENERAL_DEBUG
Serial.printf("New brightness value: %d\n", inputBuffer.substring(3).toInt());
#endif
modes[currentMode].brightness = constrain(inputBuffer.substring(3).toInt(), 0, 255);
FastLED.setBrightness(modes[currentMode].brightness); FastLED.setBrightness(modes[currentMode].brightness);
settChanged = true; settChanged = true;
eepromTimer = millis(); eepromTimer = millis();
} else if (inputBuffer.startsWith("SPD")) {
#ifdef GENERAL_DEBUG
Serial.printf("modes[currentMode].brightness: %d\n", modes[currentMode].brightness);
#endif
}
else if (inputBuffer.startsWith("SPD"))
{
modes[currentMode].speed = inputBuffer.substring(3).toInt(); modes[currentMode].speed = inputBuffer.substring(3).toInt();
loadingFlag = true; loadingFlag = true;
settChanged = true; settChanged = true;
eepromTimer = millis(); eepromTimer = millis();
} else if (inputBuffer.startsWith("SCA")) { }
else if (inputBuffer.startsWith("SCA"))
{
modes[currentMode].scale = inputBuffer.substring(3).toInt(); modes[currentMode].scale = inputBuffer.substring(3).toInt();
loadingFlag = true; loadingFlag = true;
settChanged = true; settChanged = true;
eepromTimer = millis(); eepromTimer = millis();
} else if (inputBuffer.startsWith("P_ON")) { }
else if (inputBuffer.startsWith("P_ON"))
{
ONflag = true; ONflag = true;
changePower(); changePower();
sendCurrent(); sendCurrent();
} else if (inputBuffer.startsWith("P_OFF")) { }
else if (inputBuffer.startsWith("P_OFF"))
{
ONflag = false; ONflag = false;
changePower(); changePower();
sendCurrent(); sendCurrent();
} else if (inputBuffer.startsWith("ALM_SET")) { }
else if (inputBuffer.startsWith("ALM_SET"))
{
byte alarmNum = (char)inputBuffer[7] - '0'; byte alarmNum = (char)inputBuffer[7] - '0';
alarmNum -= 1; alarmNum -= 1;
if (inputBuffer.indexOf("ON") != -1) { if (inputBuffer.indexOf("ON") != -1)
{
alarm[alarmNum].state = true; alarm[alarmNum].state = true;
inputBuffer = "alm #" + String(alarmNum + 1) + " ON"; inputBuffer = "alm #" + String(alarmNum + 1) + " ON";
} else if (inputBuffer.indexOf("OFF") != -1) { }
else if (inputBuffer.indexOf("OFF") != -1)
{
alarm[alarmNum].state = false; alarm[alarmNum].state = false;
inputBuffer = "alm #" + String(alarmNum + 1) + " OFF"; inputBuffer = "alm #" + String(alarmNum + 1) + " OFF";
} else { }
int almTime = inputBuffer.substring(8).toInt(); else
{
int32_t almTime = inputBuffer.substring(8).toInt();
alarm[alarmNum].time = almTime; alarm[alarmNum].time = almTime;
byte hour = floor(almTime / 60); byte hour = floor(almTime / 60);
byte minute = almTime - hour * 60; byte minute = almTime - hour * 60;
@@ -59,9 +110,15 @@ void parseUDP() {
":" + String(minute); ":" + String(minute);
} }
saveAlarm(alarmNum); saveAlarm(alarmNum);
} else if (inputBuffer.startsWith("ALM_GET")) { }
else if (inputBuffer.startsWith("ALM_GET"))
{
sendAlarms(); sendAlarms();
} else if (inputBuffer.startsWith("DAWN")) { }
else if (inputBuffer.startsWith("DAWN"))
{
dawnMode = inputBuffer.substring(4).toInt() - 1; dawnMode = inputBuffer.substring(4).toInt() - 1;
saveDawnMmode(); saveDawnMmode();
} }
@@ -71,10 +128,17 @@ void parseUDP() {
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(reply); Udp.write(reply);
Udp.endPacket(); Udp.endPacket();
#ifdef GENERAL_DEBUG
Serial.print("Outbound UDP packet: ");
Serial.println(reply);
Serial.println();
#endif
} }
} }
void sendCurrent() { void sendCurrent()
{
inputBuffer = "CURR"; inputBuffer = "CURR";
inputBuffer += " "; inputBuffer += " ";
inputBuffer += String(currentMode); inputBuffer += String(currentMode);
@@ -88,7 +152,8 @@ void sendCurrent() {
inputBuffer += String(ONflag); inputBuffer += String(ONflag);
} }
void sendAlarms() { void sendAlarms()
{
inputBuffer = "ALMS "; inputBuffer = "ALMS ";
for (byte i = 0; i < 7; i++) { for (byte i = 0; i < 7; i++) {
inputBuffer += String(alarm[i].state); inputBuffer += String(alarm[i].state);

View File

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

View File

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

View File

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