#include <LiquidCrystal.h>
#define BTN_UP 2
#define BTN_LEFT 3
#define BTN_OK 4
#define BTN_RIGHT 5
#define BTN_DOWN 6
#define PHOTOR A0
#define LED 13
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
enum StateMachine {Menu, Led, Photo, Brightness, ProgressBar};
enum StateMachine state = Menu;
boolean UpWasUp, LeftWasUp, OkWasUp, RightWasUp, DownWasUp = true;
String names[4] = {"Led", "Photo", "Brightness", "Progress Bar"};
int index = 0;
boolean goMenu = false;
// LED режим переменные
int ledMode = 0; // 0-включено, 1-мигание, 2-SOS, 3-выключено
String ledModes[4] = {"ON", "Blink", "SOS", "OFF"};
unsigned long previousMillis = 0;
const long interval = 500; // интервал для мигания
int blinkState = LOW;
int sosStep = 0;
unsigned long sosPreviousMillis = 0;
const long sosIntervals[18] = {200, 200, 200, 200, 200, 200, // S: ... (3 точки)
600, 200, 600, 200, 600, 200, // O: --- (3 тире)
600, 200, 200, 200, 200, 200}; // S: ... (3 точки)
// Brightness режим переменные
int brightness = 0;
int currentBrightness = 0;
boolean brightnessChanged = false;
unsigned long brightnessLastChange = 0;
const long brightnessFadeTime = 50; // время между шагами плавного изменения
// Progress Bar режим переменные
int progress = 0;
void setup() {
lcd.begin(16, 2);
lcd.print("start menu");
delay(2000);
lcd.clear();
for (int i = 2; i < 7; i++) {
pinMode(i, INPUT_PULLUP);
}
pinMode(13, OUTPUT);
pinMode(PHOTOR, INPUT);
// Инициализация ШИМ - полное выключение
analogWrite(LED, 0);
digitalWrite(LED, LOW);
}
void loop() {
switch (state) {
case Menu:
setMenu();
break;
case Led:
setLed();
break;
case Photo:
setPhoto();
break;
case Brightness:
setBrightness();
break;
case ProgressBar:
setProgressBar();
break;
}
boolean OkIsUp = digitalRead(BTN_OK);
if (OkWasUp != OkIsUp) {
delay(20);
OkIsUp = digitalRead(BTN_OK);
if (!OkIsUp) {
lcd.clear();
if (goMenu) {
index = 0;
state = Menu;
// При выходе из LED режима выключаем светодиод
digitalWrite(LED, LOW);
analogWrite(LED, 0);
currentBrightness = 0;
brightness = 0;
} else {
switch (index) {
case 0:
state = Led;
break;
case 1:
state = Photo;
break;
case 2:
state = Brightness;
// Сбрасываем яркость при входе в режим
currentBrightness = brightness;
analogWrite(LED, currentBrightness);
break;
case 3:
state = ProgressBar;
break;
}
}
goMenu = !goMenu;
}
}
OkWasUp = OkIsUp;
}
void setMenu() {
lcd.setCursor(0, 0);
lcd.print("Menu ");
lcd.setCursor(0, 1);
String name = names[index];
for (int i = 0; i < 16; i++) {
if (i >= name.length()) {
lcd.print(" ");
} else {
lcd.print(name[i]);
}
}
boolean UpIsUp = digitalRead(BTN_UP);
if (UpWasUp != UpIsUp) {
delay(10);
UpIsUp = digitalRead(BTN_UP);
if (!UpIsUp) {
if (index >= 3) {
index = 0;
} else {
index++;
}
lcd.clear();
}
}
UpWasUp = UpIsUp;
boolean DownIsUp = digitalRead(BTN_DOWN);
if (DownWasUp != DownIsUp) {
delay(10);
DownIsUp = digitalRead(BTN_DOWN);
if (!DownIsUp) {
if (index <= 0) {
index = 3;
} else {
index--;
}
lcd.clear();
}
}
DownWasUp = DownIsUp;
}
void setLed() {
lcd.setCursor(0, 0);
lcd.print("LED Mode: ");
lcd.setCursor(0, 1);
lcd.print(ledModes[ledMode]);
lcd.print(" ");
// Управление режимами LED
boolean LeftIsUp = digitalRead(BTN_LEFT);
if (LeftWasUp != LeftIsUp) {
delay(10);
LeftIsUp = digitalRead(BTN_LEFT);
if (!LeftIsUp) {
if (ledMode <= 0) {
ledMode = 3;
} else {
ledMode--;
}
lcd.clear();
// Сбрасываем состояния при смене режима
blinkState = LOW;
sosStep = 0;
digitalWrite(LED, LOW);
analogWrite(LED, 0);
}
}
LeftWasUp = LeftIsUp;
boolean RightIsUp = digitalRead(BTN_RIGHT);
if (RightWasUp != RightIsUp) {
delay(10);
RightIsUp = digitalRead(BTN_RIGHT);
if (!RightIsUp) {
if (ledMode >= 3) {
ledMode = 0;
} else {
ledMode++;
}
lcd.clear();
// Сбрасываем состояния при смене режима
blinkState = LOW;
sosStep = 0;
digitalWrite(LED, LOW);
analogWrite(LED, 0);
}
}
RightWasUp = RightIsUp;
// Реализация режимов LED
unsigned long currentMillis = millis();
switch (ledMode) {
case 0: // Включено
digitalWrite(LED, HIGH);
break;
case 1: // Мигание
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
blinkState = !blinkState;
digitalWrite(LED, blinkState);
}
break;
case 2: // SOS
if (currentMillis - sosPreviousMillis >= sosIntervals[sosStep]) {
sosPreviousMillis = currentMillis;
// Определяем, должен ли светодиод быть включен или выключен
if (sosStep % 2 == 0) {
// Четные шаги - включение светодиода
digitalWrite(LED, HIGH);
} else {
// Нечетные шаги - выключение светодиода
digitalWrite(LED, LOW);
}
sosStep++;
if (sosStep >= 18) { // Полный цикл SOS
sosStep = 0;
}
}
break;
case 3: // Выключено
digitalWrite(LED, LOW);
analogWrite(LED, 0);
break;
}
}
void setPhoto() {
int photoValue = analogRead(PHOTOR);
// Инвертируем значение: чем больше света, тем меньше значение
int invertedValue = 1023 - photoValue;
lcd.setCursor(0, 0);
lcd.print("Photoresistor: ");
lcd.setCursor(0, 1);
lcd.print("Value: ");
lcd.print(invertedValue);
lcd.print(" ");
delay(100); // Небольшая задержка для стабильности чтения
}
void setBrightness() {
lcd.setCursor(0, 0);
lcd.print("Brightness: ");
lcd.setCursor(0, 1);
lcd.print("Value: ");
lcd.print(brightness);
lcd.print(" ");
// Плавное изменение яркости
unsigned long currentMillis = millis();
if (brightnessChanged && (currentMillis - brightnessLastChange >= brightnessFadeTime)) {
// Плавно изменяем яркость к целевому значению
if (currentBrightness < brightness) {
currentBrightness++;
analogWrite(LED, currentBrightness);
} else if (currentBrightness > brightness) {
currentBrightness--;
analogWrite(LED, currentBrightness);
} else {
brightnessChanged = false;
}
brightnessLastChange = currentMillis;
}
// Управление яркостью кнопками с увеличенным шагом для заметности
boolean UpIsUp = digitalRead(BTN_UP);
if (UpWasUp != UpIsUp) {
delay(10);
UpIsUp = digitalRead(BTN_UP);
if (!UpIsUp) {
if (brightness < 250) {
brightness += 5; // Увеличенный шаг для заметности
if (brightness > 255) brightness = 255;
brightnessChanged = true;
brightnessLastChange = currentMillis;
lcd.clear();
}
}
}
UpWasUp = UpIsUp;
boolean DownIsUp = digitalRead(BTN_DOWN);
if (DownWasUp != DownIsUp) {
delay(10);
DownIsUp = digitalRead(BTN_DOWN);
if (!DownIsUp) {
if (brightness > 5) {
brightness -= 5; // Увеличенный шаг для заметности
if (brightness < 0) brightness = 0;
brightnessChanged = true;
brightnessLastChange = currentMillis;
lcd.clear();
} else if (brightness > 0) {
brightness = 0; // Гарантированное выключение
currentBrightness = 0;
analogWrite(LED, 0);
digitalWrite(LED, LOW);
brightnessChanged = false;
lcd.clear();
}
}
}
DownWasUp = DownIsUp;
// Гарантируем выключение при brightness = 0
if (brightness == 0 && currentBrightness == 0) {
analogWrite(LED, 0);
digitalWrite(LED, LOW);
}
}
void setProgressBar() {
lcd.setCursor(0, 0);
lcd.print("Progress: ");
lcd.print(progress);
lcd.print("% ");
// Отображение прогресс-бара (10 клеток = 100%)
lcd.setCursor(0, 1);
int bars = map(progress, 0, 100, 0, 10); // 0-100% -> 0-10 клеток
for (int i = 0; i < 10; i++) {
if (i < bars) {
lcd.write(255); // Заполненный символ
} else {
lcd.print(" "); // Пустое пространство
}
}
// Заполняем оставшиеся 6 позиций пробелами
for (int i = 10; i < 16; i++) {
lcd.print(" ");
}
// Управление прогресс-баром
boolean LeftIsUp = digitalRead(BTN_LEFT);
if (LeftWasUp != LeftIsUp) {
delay(10);
LeftIsUp = digitalRead(BTN_LEFT);
if (!LeftIsUp) {
if (progress >= 10) {
progress -= 10;
} else {
progress = 0;
}
lcd.clear();
}
}
LeftWasUp = LeftIsUp;
boolean RightIsUp = digitalRead(BTN_RIGHT);
if (RightWasUp != RightIsUp) {
delay(10);
RightIsUp = digitalRead(BTN_RIGHT);
if (!RightIsUp) {
if (progress <= 90) {
progress += 10;
} else {
progress = 100;
}
lcd.clear();
}
}
RightWasUp = RightIsUp;
}