#include <LiquidCrystal.h>
#include <Adafruit_NeoPixel.h>
LiquidCrystal lcd(13, 11, 7, 6, 5, 4);
#define LED_PIN 10
#define LED_COUNT 256
Adafruit_NeoPixel pixels(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
const int slide_switch = 9;
const int ldrPin = A0;
const int button1Pin = 3;
const int button2Pin = 2;
int currentMode = 0;
bool modeChanged = true;
bool matrixEnabled = true;
byte fireBuffer[16][16];
// Объявления всех функций
void updateModeDisplay();
void checkButtons();
void checkLightAndPower();
void modeRunningDot();
void modeGradient();
void modeFireEffect();
void setup() {
lcd.begin(16, 2);
pixels.begin();
pixels.show();
pinMode(button1Pin, INPUT_PULLUP);
pinMode(button2Pin, INPUT_PULLUP);
pinMode(slide_switch, INPUT_PULLUP);
pinMode(ldrPin, INPUT);
}
void loop() {
checkLightAndPower();
checkButtons();
if (!matrixEnabled) {
pixels.clear();
pixels.show();
lcd.setCursor(0, 1);
lcd.print("Matrix OFF ");
return;
}
if (modeChanged) {
pixels.clear();
if (currentMode == 2) {
memset(fireBuffer, 0, sizeof(fireBuffer));
}
updateModeDisplay();
modeChanged = false;
}
switch (currentMode) {
case 0: modeRunningDot(); break;
case 1: modeGradient(); break;
case 2: modeFireEffect(); break;
}
}
void checkButtons() {
static unsigned long lastPressTime = 0;
if (millis() - lastPressTime < 200) return;
if (digitalRead(button1Pin) == LOW) {
currentMode--;
if (currentMode < 0) currentMode = 2;
modeChanged = true;
lastPressTime = millis();
} else if (digitalRead(button2Pin) == LOW) {
currentMode++;
if (currentMode > 2) currentMode = 0;
modeChanged = true;
lastPressTime = millis();
}
}
void updateModeDisplay() {
lcd.setCursor(0, 0);
lcd.print("Mode ");
lcd.print(currentMode + 1);
lcd.print(": ");
}
void checkLightAndPower() {
int slideState = digitalRead(slide_switch);
if (slideState == LOW) { // Если энергосбережение включено
int analogValue = analogRead(A0);
float voltage = analogValue / 1024. * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float lux = pow(50 * 1e3 * pow(10, 0.7) / resistance, (1 / 0.7));
matrixEnabled = (lux < 500); // Включаем матрицу только если темно
} else { // Если энергосбережение выключено
matrixEnabled = true; // Всегда включаем матрицу
}
// Выводим состояние на LCD
}
void modeRunningDot() {
static int pos = 0;
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate > 30) {
pixels.clear();
pixels.setPixelColor(pos, pixels.Color(0, 150, 0));
pixels.show();
pos = (pos + 1) % LED_COUNT;
lastUpdate = millis();
}
lcd.setCursor(0, 1);
lcd.print("Running dot ");
}
void modeGradient() {
static int offset = 0;
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate > 100) {
for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) {
int index = y * 16 + x;
int r = (x + offset) % 16 * 16;
int g = (y + offset) % 16 * 16;
int b = 128;
pixels.setPixelColor(index, pixels.Color(r, g, b));
}
}
pixels.show();
offset = (offset + 1) % 16;
lastUpdate = millis();
}
lcd.setCursor(0, 1);
lcd.print("Gradient flow ");
}
void modeFireEffect() {
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate < 50) return;
for (int x = 0; x < 16; x++) {
fireBuffer[x][15] = random(100, 255);
}
for (int y = 0; y < 15; y++) {
for (int x = 0; x < 16; x++) {
int newVal = (
fireBuffer[(x - 1 + 16) % 16][y + 1] +
fireBuffer[x][y + 1] +
fireBuffer[(x + 1) % 16][y + 1] +
fireBuffer[x][(y + 2) % 16]
) / 4;
newVal -= random(0, 30);
if (newVal < 0) newVal = 0;
fireBuffer[x][y] = newVal;
}
}
for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) {
int heat = fireBuffer[x][y];
int r, g, b;
if (heat < 60) {
r = heat;
g = 0;
b = 0;
} else if (heat < 120) {
r = 255;
g = heat - 60;
b = 0;
} else if (heat < 180) {
r = 255;
g = 120 + (heat - 120) / 2;
b = 0;
} else {
r = 255;
g = 180 + (heat - 180) / 4;
b = (heat - 180) / 2;
}
pixels.setPixelColor(x + y * 16, pixels.Color(r, g, b));
}
}
pixels.show();
lastUpdate = millis();
lcd.setCursor(0, 1);
lcd.print("Fire effect ");
}