MasterIphone
Member
Написал код с выводом пунктов меню динамически(в цикле) из конструкции.
Сам код ниже
Не могу додумать, как задать условия, чтобы когда гуляешь по меню вниз или вверх, то меню "листалось".
Сейчас у меня обновление экрана нет, когда пункт уходит за пределы экрана.
Как бы это тоже, динамически сделать.
const char *menu_item[] = { "Контраст", "Подсвет", "Сброс", "Пункт 4", "Пункт 5"};
Сам код ниже
#include "PCF8574_PCD8544.h"
#include "GyverEncoder.h"
//display status variables
//boolean backlightStatus = 0;
int contrast = 30;
static uint32_t tmr; // переменная времени
int t_light = 2000; // время работы подсветки
//menu variables
int currentItem = 1;
int menuItems = 5;//количество выводимых пунктов меню
boolean up = false;
boolean down = false;
boolean middle = false;
#define ENC_A 12 //D6
#define ENC_B 14 //D5
#define ENC_KEY 13 //D7
#define NOKIA_BL 3 //ножка P3 на расширителе портов PCF8574
//EncButton2<EB_ENCBTN> enc(INPUT, ENC_A, ENC_B, ENC_KEY);
Encoder enc1(ENC_A, ENC_B, ENC_KEY);
// I2C to SPI via PCF8574 interface (slower updates, less pins):
// address (LCD interface: 0x20-0x27 selectable by connecting pads, all open=0x27)
// pcf-P7 - 5. Serial clock out (SCLK, CLK)
// pcf-P6 - 4. Serial data out (DIN)
// pcf-P5 - 3. Data/Command select (D/C, DC)
// pcf-P4 - 2. LCD chip select (CS, CE), can be set to -1 if not used (tie line low)
// pcf-P3 - 7. Backlight control (LIGHT), not used in i2c display constructor
// pcf-P2 - 1. LCD reset (RST), can be set to -1 if not used (tie line high or to reset of MCU)
PCF8574_PCD8544 display = PCF8574_PCD8544(0x27, 7, 6, 5, 4, 2);
const char *menu_item[] = { "Контраст", "Подсвет", "Сброс", "Пункт 4", "Пункт 5"};
void setup() {
Serial.begin(115200);
enc1.setType(TYPE2); // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип\=
// attachInterrupt(0, isr_ENC_A, CHANGE); // прерывание на 12 пине! CLK у энка
// attachInterrupt(1, isr_ENC_B, CHANGE); // прерывание на 14 пине! DT у энка
// attachInterrupt(2, isr_ENC_KEY, CHANGE);
display.cp437(true);
display.begin();
display.clearDisplay();
setContrast();
//updateBacklight();
drawMenu();
}
//ICACHE_RAM_ATTR void isr_ENC_A() {
// enc1.tick(); // отработка в прерывании
//}
//
//ICACHE_RAM_ATTR void isr_ENC_B() {
// enc1.tick(); // отработка в прерывании
//}
//
//ICACHE_RAM_ATTR void isr_ENC_KEY() {
// enc1.tick(); // отработка в прерывании
//}
void loop() {
readRotaryEncoder();
// bool buttonPressed = (up || down || middle);
//
if (up || down || middle) {
if (up && currentItem > 1) {
up = false;
currentItem --;
Serial.print("\n");
Serial.println(currentItem);
//drawMenu();
}
if (down && currentItem < menuItems) {
down = false;
currentItem ++;
Serial.print("\n");
Serial.println(currentItem);
//drawMenu();
}
//adjust contrast
if (middle && currentItem == 1) {
middle = false;
contrast = contrast + 2;
if (contrast > 60) {
contrast = 10;
}
Serial.print("\n");
Serial.println(currentItem);
//setContrast();
//drawMenu();
}
//toggle backlight status
if (middle && currentItem == 2) {
middle = false;
// if (backlightStatus = 0) {
// backlightStatus = 1;
// } else {
// backlightStatus = 0;
// }
Serial.print("\n");
Serial.println(currentItem);
//updateBacklight();
}
//toggle reset
if (middle && currentItem == 3) {
middle = false;
//backlightStatus = 0;
contrast = 30;
//updateBacklight();
Serial.print("\n");
Serial.println(currentItem);
//setContrast();
}
drawMenu();
setContrast();
// updateBacklight();
}
}
//обработка энкодера
void readRotaryEncoder() {
//enc.tick();
enc1.tick();
if (enc1.isRight()) { //Если вправо то курсор по меню вниз
turnBacklightOnFewSec();
Serial.print("\n");
Serial.println("Вправо");
// display.setTextSize(1);
// display.clearDisplay();
// display.setTextColor(BLACK, WHITE);
// display.setCursor(15, 0);
// display.print("RIGHT");
// display.display();
down = true;
//delay(150);
} else if (enc1.isLeft()) { //Если влево то курсор по меню вверх
turnBacklightOnFewSec();
Serial.print("\n");
Serial.println("Влево");
// display.setTextSize(1);
// display.clearDisplay();
// display.setTextColor(BLACK, WHITE);
// display.setCursor(15, 0);
// display.print("LEFT");
// display.display();
up = true;
//delay(150);
}
if (enc1.isClick()) //Если кликнуть то "проваливаемся" в пункт меню
{
turnBacklightOnFewSec();
Serial.print("\n");
Serial.println("1 Клик");
// display.setTextSize(1);
// display.clearDisplay();
// display.setTextColor(BLACK, WHITE);
// display.setCursor(15, 0);
// display.print("CLICK");
// display.display();
middle = true;
}
if (millis() - tmr >= t_light) { //Задаем время работы подсветки 1000ms = 1sec
turnBacklightOff();
}
}
void turnBacklightOff()
{
//digitalWrite(NOKIA_BL, LOW);
display.digitalWrite(NOKIA_BL, LOW);
}
void turnBacklightOn()
{
//digitalWrite(NOKIA_BL, HIGH);
display.digitalWrite(NOKIA_BL, HIGH);//на экспандере 2.2 вольта на ножке
}
void turnBacklightOnFewSec()//отключение подсветки через заданное время
{
turnBacklightOn();
tmr = millis();
}
//отрисовка меню
void drawMenu() {
display.setTextSize(1);
display.clearDisplay();
display.setTextColor(BLACK, WHITE);
display.setCursor(0, 0);
display.print(" DISPLAY MENU ");
display.drawFastHLine(0, 10, 83, BLACK);
for (int i = 0; i <= menuItems - 1; i++) {
drawMenuItem(i);
}
display.display();
}
void drawMenuItem(int item) {
int y = (item * 10) + 15;//вычисление вертикальной позиции меню
if (item == currentItem - 1) {
display.setTextColor(WHITE, BLACK);
} else {
display.setTextColor(BLACK, WHITE);
}
display.setCursor(0, y);
//русские шрифты заработали после замены файла
//glcdfont.c и добавление отдельного скетча utf8rus.ino
display.print(utf8rus(menu_item[item]));
//display.print(menu_item[item]);
}
void setContrast() {
display.setContrast(contrast);
display.display();
}
//void updateBacklight() {
// display.digitalWrite(NOKIA_BL, backlightStatus);//запись в пин через расширитель PCF8574
// //digitalWrite(NOKIA_BL, backlightStatus);
//}
#include "GyverEncoder.h"
//display status variables
//boolean backlightStatus = 0;
int contrast = 30;
static uint32_t tmr; // переменная времени
int t_light = 2000; // время работы подсветки
//menu variables
int currentItem = 1;
int menuItems = 5;//количество выводимых пунктов меню
boolean up = false;
boolean down = false;
boolean middle = false;
#define ENC_A 12 //D6
#define ENC_B 14 //D5
#define ENC_KEY 13 //D7
#define NOKIA_BL 3 //ножка P3 на расширителе портов PCF8574
//EncButton2<EB_ENCBTN> enc(INPUT, ENC_A, ENC_B, ENC_KEY);
Encoder enc1(ENC_A, ENC_B, ENC_KEY);
// I2C to SPI via PCF8574 interface (slower updates, less pins):
// address (LCD interface: 0x20-0x27 selectable by connecting pads, all open=0x27)
// pcf-P7 - 5. Serial clock out (SCLK, CLK)
// pcf-P6 - 4. Serial data out (DIN)
// pcf-P5 - 3. Data/Command select (D/C, DC)
// pcf-P4 - 2. LCD chip select (CS, CE), can be set to -1 if not used (tie line low)
// pcf-P3 - 7. Backlight control (LIGHT), not used in i2c display constructor
// pcf-P2 - 1. LCD reset (RST), can be set to -1 if not used (tie line high or to reset of MCU)
PCF8574_PCD8544 display = PCF8574_PCD8544(0x27, 7, 6, 5, 4, 2);
const char *menu_item[] = { "Контраст", "Подсвет", "Сброс", "Пункт 4", "Пункт 5"};
void setup() {
Serial.begin(115200);
enc1.setType(TYPE2); // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип\=
// attachInterrupt(0, isr_ENC_A, CHANGE); // прерывание на 12 пине! CLK у энка
// attachInterrupt(1, isr_ENC_B, CHANGE); // прерывание на 14 пине! DT у энка
// attachInterrupt(2, isr_ENC_KEY, CHANGE);
display.cp437(true);
display.begin();
display.clearDisplay();
setContrast();
//updateBacklight();
drawMenu();
}
//ICACHE_RAM_ATTR void isr_ENC_A() {
// enc1.tick(); // отработка в прерывании
//}
//
//ICACHE_RAM_ATTR void isr_ENC_B() {
// enc1.tick(); // отработка в прерывании
//}
//
//ICACHE_RAM_ATTR void isr_ENC_KEY() {
// enc1.tick(); // отработка в прерывании
//}
void loop() {
readRotaryEncoder();
// bool buttonPressed = (up || down || middle);
//
if (up || down || middle) {
if (up && currentItem > 1) {
up = false;
currentItem --;
Serial.print("\n");
Serial.println(currentItem);
//drawMenu();
}
if (down && currentItem < menuItems) {
down = false;
currentItem ++;
Serial.print("\n");
Serial.println(currentItem);
//drawMenu();
}
//adjust contrast
if (middle && currentItem == 1) {
middle = false;
contrast = contrast + 2;
if (contrast > 60) {
contrast = 10;
}
Serial.print("\n");
Serial.println(currentItem);
//setContrast();
//drawMenu();
}
//toggle backlight status
if (middle && currentItem == 2) {
middle = false;
// if (backlightStatus = 0) {
// backlightStatus = 1;
// } else {
// backlightStatus = 0;
// }
Serial.print("\n");
Serial.println(currentItem);
//updateBacklight();
}
//toggle reset
if (middle && currentItem == 3) {
middle = false;
//backlightStatus = 0;
contrast = 30;
//updateBacklight();
Serial.print("\n");
Serial.println(currentItem);
//setContrast();
}
drawMenu();
setContrast();
// updateBacklight();
}
}
//обработка энкодера
void readRotaryEncoder() {
//enc.tick();
enc1.tick();
if (enc1.isRight()) { //Если вправо то курсор по меню вниз
turnBacklightOnFewSec();
Serial.print("\n");
Serial.println("Вправо");
// display.setTextSize(1);
// display.clearDisplay();
// display.setTextColor(BLACK, WHITE);
// display.setCursor(15, 0);
// display.print("RIGHT");
// display.display();
down = true;
//delay(150);
} else if (enc1.isLeft()) { //Если влево то курсор по меню вверх
turnBacklightOnFewSec();
Serial.print("\n");
Serial.println("Влево");
// display.setTextSize(1);
// display.clearDisplay();
// display.setTextColor(BLACK, WHITE);
// display.setCursor(15, 0);
// display.print("LEFT");
// display.display();
up = true;
//delay(150);
}
if (enc1.isClick()) //Если кликнуть то "проваливаемся" в пункт меню
{
turnBacklightOnFewSec();
Serial.print("\n");
Serial.println("1 Клик");
// display.setTextSize(1);
// display.clearDisplay();
// display.setTextColor(BLACK, WHITE);
// display.setCursor(15, 0);
// display.print("CLICK");
// display.display();
middle = true;
}
if (millis() - tmr >= t_light) { //Задаем время работы подсветки 1000ms = 1sec
turnBacklightOff();
}
}
void turnBacklightOff()
{
//digitalWrite(NOKIA_BL, LOW);
display.digitalWrite(NOKIA_BL, LOW);
}
void turnBacklightOn()
{
//digitalWrite(NOKIA_BL, HIGH);
display.digitalWrite(NOKIA_BL, HIGH);//на экспандере 2.2 вольта на ножке
}
void turnBacklightOnFewSec()//отключение подсветки через заданное время
{
turnBacklightOn();
tmr = millis();
}
//отрисовка меню
void drawMenu() {
display.setTextSize(1);
display.clearDisplay();
display.setTextColor(BLACK, WHITE);
display.setCursor(0, 0);
display.print(" DISPLAY MENU ");
display.drawFastHLine(0, 10, 83, BLACK);
for (int i = 0; i <= menuItems - 1; i++) {
drawMenuItem(i);
}
display.display();
}
void drawMenuItem(int item) {
int y = (item * 10) + 15;//вычисление вертикальной позиции меню
if (item == currentItem - 1) {
display.setTextColor(WHITE, BLACK);
} else {
display.setTextColor(BLACK, WHITE);
}
display.setCursor(0, y);
//русские шрифты заработали после замены файла
//glcdfont.c и добавление отдельного скетча utf8rus.ino
display.print(utf8rus(menu_item[item]));
//display.print(menu_item[item]);
}
void setContrast() {
display.setContrast(contrast);
display.display();
}
//void updateBacklight() {
// display.digitalWrite(NOKIA_BL, backlightStatus);//запись в пин через расширитель PCF8574
// //digitalWrite(NOKIA_BL, backlightStatus);
//}
Не могу додумать, как задать условия, чтобы когда гуляешь по меню вниз или вверх, то меню "листалось".
Сейчас у меня обновление экрана нет, когда пункт уходит за пределы экрана.
Как бы это тоже, динамически сделать.