#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "CustomChars.h"
#define ENCODER_CLK 2
#define ENCODER_DT 3
#define ENCODER_SW 4
#define LED 5
#define LED_POWER 12
LiquidCrystal_I2C lcd(0x27, 16, 2);
//--Значёк стрелка
byte arrow[8] = {
B10000,
B11000,
B11100,
B11110,
B11110,
B11100,
B11000,
B10000
};
void setup() {
Serial.begin(115200);
pinMode(ENCODER_CLK, INPUT);
pinMode(ENCODER_DT, INPUT);
pinMode(ENCODER_SW, INPUT);
pinMode(LED, OUTPUT);
pinMode(LED_POWER, OUTPUT);
digitalWrite(LED_POWER, HIGH); // включить светодиод начала работы устройства
LCD_Start(); //---запуск экрана приветсвия
lcd.createChar(0, arrow);
}
//Отображение экрана приветствтвия
void LCD_Start()
{
lcd.init();
lcd.noBacklight();
// Загружаем пользовательские символы один раз
lcd.createChar(0, arrow);
delay(1000);
lcd.backlight();
delay(1000);
//Пишем первое приветсвие
lcd.setCursor(4, 0);
lcd.print("ANYCUBIC");
lcd.setCursor(0, 1);
lcd.print("ILLUMINATION BOX");
delay(2000);
lcd.clear();
delay(1000);
}
bool ButtonClick(short button)
{
static bool lastStableState = HIGH; // последнее стабильное состояние
static unsigned long lastDebounce = 0;
const int currentState = digitalRead(button);
const unsigned long now = millis();
// Если состояние изменилось — начинаем отсчёт debounce
if (currentState != lastStableState) {
if (now - lastDebounce > 50) {
// Сигнал стабилен — подтверждаем изменение
lastStableState = currentState;
lastDebounce = now;
// Обнаружено нажатие (HIGH → LOW)
if (currentState == LOW) {
return true;
}
}
} else {
// Сигнал не менялся — можно сбросить таймер (опционально)
lastDebounce = now;
}
return false;
}
//--Работа логики поворачивающего энкодера
bool Rotary_Encoder(short& cursor_value, // подсчет оборотов
bool& left_right_turn, // направление оборота
bool& rotation_status, // Проверка произошел ли поворот энкодера
bool border = true) // Ограничение захода в минусовые значения (true - вкл ограничение)
{
static bool clk = 0; // Центральное нажатие
static bool dt = 0; // поворот против часовой
static bool sw = 0; // поворот по часовой
clk = !digitalRead(ENCODER_CLK);
dt = digitalRead(ENCODER_DT);
sw = digitalRead(ENCODER_SW);
// --- Обработка поворота ---
if (clk != rotation_status) {
rotation_status = clk;
if (clk == HIGH) { // фронт считаем при LOW (стандарт для KY-040)
if (dt == HIGH) {
cursor_value++; // поворот по часовой
left_right_turn = 1;
} else {
left_right_turn = 0;
//Ограничение захода в минусовые значения
if (border == true && cursor_value <= 0)
cursor_value = 0;
else cursor_value--; // против часовой
}
}
}
return ButtonClick(ENCODER_SW);
}
//---Работа логики перемещения стрелочки по главному экрану
void Moving_Cursor_Menu(LiquidCrystal_I2C& lcd, // Объект экрана LCD
short& cursor_value, // подсчет оборотов
const bool& left_right_turn, // направление оборота
const bool& rotation_status, // Проверка произошел ли поворот энкодера
const short& count) // Кол-во элементов в массиве
{
//Запуск при не нулевом меню
if (count)
{
//Ограничение стрелочки концом и началом массива списка меню
if (cursor_value > count)
{
cursor_value = count;
}
//Первое отображение стрелочки
static bool first_position = true;
if (!rotation_status && first_position)
{
lcd.clear();
lcd.setCursor(0, 1);
lcd.write(byte(0));
}
// //Перемещать курсор только если в меню больше одной строчки
// if (count > 1)
// {
// if (rotation_status)
// {
// if (left_right_turn == true) {
// lcd.clear();
// lcd.setCursor(0, left_right_turn);
// lcd.write(byte(0));
// } else {
// lcd.clear();
// lcd.setCursor(0, left_right_turn);
// lcd.write(byte(0));
// }
// }
// }
first_position = false;
}
}
// //---Работа логики перемещения курсора по экрану
// void Moving_Cursor(LiquidCrystal_I2C& lcd, //Объект экрана LCD
// short& cursor_position, //Позиция курсора
// short& cursor_position_line) //Позиция курсора по линии
// {
// lcd.cursor();
// short display_line = 15;
// //Запрет заходить курсору за минусовую зону
// if (cursor_position < 0)
// {
// cursor_position = 0;
// }
// //Запрет заходить курсору за зону экрана
// else if (cursor_position > 31)
// {
// cursor_position = 31;
// }
// //Перемещение курсора по экрану
// if (cursor_position <= display_line)
// {
// lcd.setCursor(cursor_position, 0);
// cursor_position_line = 0;
// }
// else if (cursor_position > display_line)
// {
// lcd.setCursor((cursor_position - 1) - display_line, 1);
// cursor_position_line = 1;
// }
// }
void Menu(const char* name_menu, // имя меню в верхней строчке
short& cursor_value, // подсчет оборотов
const bool& left_right_turn, // направление оборота
const bool& rotation_status, // Проверка произошел ли поворот энкодера
const char* list[], // Массив меню
const short& count) // Кол-во элементов в массиве
{
if (cursor_value >= count) {
cursor_value = count - 1;
}
short n = cursor_value;
// Первое отображение меню
static bool first_position = true;
if (!rotation_status && first_position)
{
//поствить стрелку
lcd.clear();
lcd.setCursor(0, 1);
lcd.write(byte(0));
//отрисовать меню
lcd.setCursor(0, 0);
lcd.print(name_menu);
lcd.setCursor(2, 1);
lcd.print(list[n]);
}
// Отображение меню из массива
if (rotation_status)
{
if (count > 1)
{
//поствить стрелку
lcd.clear();
lcd.setCursor(0, 1);
lcd.write(byte(0));
//отрисовать меню
lcd.setCursor(0, 0);
lcd.print(name_menu);
lcd.setCursor(2, 1);
lcd.print(list[n]);
}
}
first_position = false;
}
short cursor_click = 0;
bool left_right_turn = 0;
bool lastClk = 0;
short cursor_position_line = 0;
const short size_menuItems = 5;
const char* menuItems[size_menuItems] =
{
"LED1",
"LED2",
"LED3",
"LED4",
"LED5",
};
const short size_menuItems2 = 5;
const char* menuItems2[size_menuItems2] =
{
"LED10",
"LED21",
"LED32",
"LED43",
"LED54",
};
void TEST(short index, // Индекс на курсоре
const char* text, // Текст сообщения
short indent, // Отступ от края
short line, // Строка на экране
bool& rotation_status, // Проверка есть ли ротация энкодера
const short& cursor_click) // направление оборота)
{
if(!rotation_status)
{
// lcd.print("rotation");
lcd.clear();
}
if (cursor_click == index)
{
lcd.setCursor(indent, line);
lcd.print(text);
}
}
void loop()
{
// //Нажим на ky040 Encoder Reference
Rotary_Encoder(cursor_click, left_right_turn, lastClk);
// TEST(5, "TEST", 2, 0, left_right_turn, cursor_click);
// TEST(1, "TEST2", 2, 0, left_right_turn, cursor_click);
// //Пробежка курсора по экрану
// Moving_Cursor_Menu(lcd, cursor_click, left_right_turn, lastClk, size_menuItems);
// Menu(" MAIN MENU",cursor_click, left_right_turn, lastClk, menuItems, size_menuItems);
if(cursor_click==0)
{
lcd.setCursor(0, 0);
lcd.print("TEST");
}
else if(cursor_click==1)
{
lcd.setCursor(0, 0);
lcd.print("TEST2");
}
lcd.clear();
// Serial.print("cursor_click: ");
// Serial.println(cursor_click);
// if (cursor_click == 2 && ButtonClick(ENCODER_SW))
// {
// digitalWrite(LED, HIGH); // включить
// }
// else
// digitalWrite(LED, LOW); // выключить
// #define ENCODER_CLK 2
// #define ENCODER_DT 3
// #define ENCODER_SW 4
// Serial.print("cursor_click: ");
// Serial.println(cursor_click);
// Serial.print("encoder_CLK: ");
// Serial.println(encoder_CLK);
// Serial.print("cursor_position_line: ");
// Serial.println(encoder_DT);
// Serial.print("encoder_DT: ");
// Serial.println(encoder_SW);
// Serial.print("cursor_position_line: ");
// Serial.println(encoder_SW);
// delay(500);
}