#include <LiquidCrystal.h>
#include <FastLED.h>
#define LDR_PIN A2
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
#define button1Pin 2 // Кнопка 1 подключена к пину 2 (btn1)
#define button2Pin 3 // Кнопка 2 подключена к пину 3 (btn2)
bool modeChanged = true;
#define NUM_ROWS 16
#define NUM_COLS 16
#define DATA_PIN 5 // NeoPixel подключены к пину 5
#define BRIGHTNESS 255
#define NUM_LEDS (NUM_ROWS * NUM_COLS)
CRGB leds[NUM_LEDS];
int mode = 0;
// Таймеры для анимаций
unsigned long previousMillis0 = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
// Интервалы обновления анимаций (мс)
const unsigned long interval0 = 100; // режим 0 - радужный круг
const unsigned long interval1 = 50; // режим 1 - бегущая точка
const unsigned long interval2 = 150; // режим 2 - плавная смена цветов
// Переменные для анимаций
uint8_t hue = 0; // Для цветовых эффектов
uint8_t pos = 0; // Позиция для бегущей точки
CRGBPalette16 currentPalette = RainbowColors_p; // Палитра для режима 2
bool tf;
const float GAMMA = 0.7;
const float RL10 = 50;
void setup() {
lcd.begin(16, 2);
pinMode(LDR_PIN, INPUT);
pinMode(button1Pin, INPUT_PULLUP);
pinMode(button2Pin, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
updateDisplay();
tf = digitalRead(6);
attachInterrupt(digitalPinToInterrupt(button1Pin), checkButtons, FALLING);
attachInterrupt(digitalPinToInterrupt(button2Pin), checkButtons, FALLING);
}
void loop() {
// Перевод аналоговых значений в люксы
int analogValue = analogRead(LDR_PIN);
float voltage = analogValue / 1024. * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
unsigned long now = millis();
tf = digitalRead(6);
if (digitalRead(button1Pin) == LOW) {
updateDisplay();
clearLEDs();
}
if (digitalRead(button2Pin) == LOW) {
updateDisplay();
clearLEDs();
}
// --- Анимации ---
switch (mode) {
case 0: { // Радужный круг
if (now - previousMillis0 >= interval0) {
previousMillis0 = now;
FastLED.clear();
// Рисуем концентрические круги с разными цветами
for (uint8_t r = 0; r < 8; r++) {
drawCircle(7, 7, r, CHSV(hue + r * 16, 255, 255));
}
FastLED.show();
hue++;
if(tf == false && lux > 100) mode = 3;
}
break;
}
case 1: { // Бегущая точка с хвостом
if (now - previousMillis1 >= interval1) {
previousMillis1 = now;
// Затемняем все светодиоды для эффекта хвоста
fadeToBlackBy(leds, NUM_LEDS, 20);
// Устанавливаем яркий светодиод в текущей позиции
leds[pos] = CHSV(hue, 255, 255);
FastLED.show();
// Перемещаем позицию
pos = (pos + 1) % NUM_LEDS;
hue += 5;
if(tf == false && lux > 100) mode = 4;
}
break;
}
case 2: { // Плавная смена цветов всей матрицы
if (now - previousMillis2 >= interval2) {
previousMillis2 = now;
// Заполняем всю матрицу цветом из палитры
uint8_t beat = beatsin8(10, 0, 255);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(currentPalette, beat + i, 255, LINEARBLEND);
}
FastLED.show();
hue++;
// Периодически меняем палитру
if (hue % 64 == 0) {
if (currentPalette == RainbowColors_p) {
currentPalette = OceanColors_p;
} else if (currentPalette == OceanColors_p) {
currentPalette = ForestColors_p;
} else {
currentPalette = RainbowColors_p;
}
}
if(tf == false && lux > 100) mode = 5;
}
break;
}
case 3: { // Выключение для режима 0
FastLED.clear();
FastLED.show();
if (lux <= 100) mode = 0;
if(tf == true) mode = 0;
break;
}
case 4: { // Выключение для режима 1
FastLED.clear();
FastLED.show();
if (lux <= 100) mode = 1;
if (tf == true) mode = 1;
break;
}
case 5: { // Выключение для режима 2
FastLED.clear();
FastLED.show();
if (lux <= 100) mode = 2;
if (tf == true) mode = 2;
break;
}
}
}
void drawCircle(uint8_t x0, uint8_t y0, uint8_t radius, CRGB color) {
int x = radius;
int y = 0;
int err = 0;
while (x >= y) {
leds[XY(x0 + x, y0 + y)] = color;
leds[XY(x0 + y, y0 + x)] = color;
leds[XY(x0 - y, y0 + x)] = color;
leds[XY(x0 - x, y0 + y)] = color;
leds[XY(x0 - x, y0 - y)] = color;
leds[XY(x0 - y, y0 - x)] = color;
leds[XY(x0 + y, y0 - x)] = color;
leds[XY(x0 + x, y0 - y)] = color;
y += 1;
err += 1 + 2*y;
if (2*(err - x) + 1 > 0) {
x -= 1;
err += 1 - 2*x;
}
}
}
void clearLEDs() {
FastLED.clear();
FastLED.show();
}
void updateDisplay() {
if(mode < 3){
lcd.clear();
switch (mode) {
case 0: {
lcd.setCursor(3, 0);
lcd.print("1 - CIRCLES");
lcd.setCursor(0, 1);
lcd.print("<3 2>");
break;
}
case 1: {
lcd.setCursor(3, 0);
lcd.print("2 - RUNNER");
lcd.setCursor(0, 1);
lcd.print("<1 3>");
break;
}
case 2: {
lcd.setCursor(3, 0);
lcd.print("3 - COLORS");
lcd.setCursor(0, 1);
lcd.print("<2 1>");
break;
}
}
}
}
uint16_t XY(uint8_t x, uint8_t y) {
return (y * NUM_COLS + x);
}
void checkButtons() {
if (mode < 3){
if (digitalRead(button1Pin) == LOW) {
mode--;
if (mode < 0) mode = 2;
modeChanged = true;
} else if (digitalRead(button2Pin) == LOW) {
mode++;
if (mode > 2) mode = 0;
modeChanged = true;
}
}
}