Пытаюсь содать меню

dxf001
Offline
Зарегистрирован: 17.04.2020

Пытаюсь сделать меню. Начал с простого для понимания, но пока не понятно почему так ведёт себя МК. Может кто разъяснит причину такой работы МК.

Первый код, строка на экранчике переключается нормально:

#define CLK 2
#define DT 3
#define SW 4

#include <Arduino.h>
#include <LCD_1602_RUS.h>
LCD_1602_RUS lcd(0x27, 16, 2);

#include <GyverEncoder.h>
Encoder enc1(CLK, DT, SW, TYPE2);

void setup() {
enc1.setType(TYPE2);
lcd.init();                      
lcd.backlight();
}

void lcdInit () {
  lcd.clear();
  lcd.setCursor(0, 0);
}

void menuGlobal_2 () {
 if (enc1.isRight()) {  
  lcdInit ();
    lcd.print(L"Вправо");
  }  
if (enc1.isLeft()) {
  lcdInit ();
    lcd.print(L"Влево");
  }
if (enc1.isHolded()) {  
  lcdInit ();
    lcd.print(L"Удержание");
  }
  if (enc1.isDouble()) {  
  lcdInit ();
    lcd.print(L"Двойной клик");
  }
  if (enc1.isClick()) {  
  lcdInit ();
    lcd.print(L"Нажатие");
  }
  }

void loop() {
enc1.tick();
menuGlobal_2 ();
 } 

Второй код, строка постоянно моргает, нормально не переключается:

#define CLK 2
#define DT 3
#define SW 4

#include <Arduino.h>
#include <LCD_1602_RUS.h>
LCD_1602_RUS lcd(0x27, 16, 2);

#include <GyverEncoder.h>
Encoder enc1(CLK, DT, SW, TYPE2);

int counter;

void setup() {
enc1.setType(TYPE2);
lcd.init();                      
lcd.backlight();
}

void lcdInit () {
  lcd.clear();
  lcd.setCursor(0, 0);
}

void encoderFunc () {
  if (enc1.isRight()) {  
  counter = 1;
  }  
if (enc1.isLeft()) {
  counter = 2;
  }
if (enc1.isHolded()) {  
  counter = 3;
  }
  if (enc1.isDouble()) {  
  counter = 4;
  }
  if (enc1.isClick()) {  
  counter = 5;
  }
}


void menuGlobal () {
  if (counter == 1) {  
      lcdInit ();
    lcd.print(L"Вправо");
  }  
  if (counter == 2) {  
      lcdInit ();
    lcd.print(L"Влево");
  }
    if (counter == 3) {  
      lcdInit ();
    lcd.print(L"Удержание");
  }
    if (counter == 4) {  
      lcdInit ();
    lcd.print(L"Двойной клик");
  }
    if (counter == 5) {  
      lcdInit ();
    lcd.print(L"Нажатие");
  }
}

void loop() {
enc1.tick();
encoderFunc ();
menuGlobal ();
} 

Пробовал тоже самое, но вместо if, case, понятно дело результат аналогичный

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Понятно - во втором случае Вы постоянно перерисовываете меню, а это время. Поэтому ничего нормально и не работает.

Меню должно реагировать только на изменение значения энкодера. Т е. во втором случае переменная counter должна разово принимать значение и опять становится 0 приблизительно так:

void menuGlobal () {
  if (counter == 1) {  
      lcdInit ();
    lcd.print(L"Вправо");
   counter =0;
  }  

 

 

dxf001
Offline
Зарегистрирован: 17.04.2020

Спасибо, что то сразу не дошло )

Если есть возможность покритикуйте пожалуйста. Сделал двухуровневое меню (если можно так назвать), во втором уровне не могу понять как сделать изменение установленных пременных нормально, глючит чего то малость меню. Не могу отобразить курсорчик когда делаю изменение величины и не понимаю почему выходит из подменю после изменения переменных countL или countH при простом нажатии на кнопку. То что закомментировано не работает у меня нормально.

// Термостат
#define CLK 2
#define DT 3
#define SW 4

#include <Arduino.h>
#include <LCD_1602_RUS.h>
LCD_1602_RUS lcd(0x27, 16, 2);

#include <GyverEncoder.h>
Encoder enc1(CLK, DT, SW, TYPE2);

bool flagAuto = 0, flagSecondMenu = 0, flagSwitchMenu = 0, flagMode = 1, flagSecondMenuRedraw = 0,
     flagArrow = 0, flagScroll = 0, flagArrowHold = 0, flagScrollHold = 0;

int8_t countH = 30, countL = 25;
String arrow = ">>";

void setup()
{
  enc1.setType(TYPE2);
  lcd.init();
  lcd.backlight();
}

void lcdInit()
{
  lcd.clear();
  lcd.setCursor(0, 0);
}

void mainMenuEnc()
{
  if (enc1.isRelease() && flagMode == 0)
  {
    flagMode = 1;
  }
  if (enc1.isHolded())
  {
    flagSwitchMenu = 1;
  }
  if (enc1.isRight() && flagSecondMenu == 1)
  {
    flagArrow = 1;
    flagSecondMenuRedraw = 1;
  }
  if (enc1.isLeft() && flagSecondMenu == 1)
  {
    flagArrow = 1;
    flagSecondMenuRedraw = 1;
  }
  if (enc1.isRightH() && flagSecondMenu == 1)
  {
    flagArrowHold = 1;
    flagSecondMenuRedraw = 1;
    if (flagScroll == 1)
    {
      countH++;
    }
    else
    {
      countL++;
    }
  }
  if (enc1.isLeftH() && flagSecondMenu == 1)
  {
    flagArrowHold = 1;
    flagSecondMenuRedraw = 1;
    if (flagScroll == 1)
    {
      countH--;
    }
    else
    {
      countL--;
    }
  }
}

void mainMenuLcd()
{
  if (flagMode == 1 && flagSecondMenu == 0)
  {
    lcdInit();
    lcd.print(L"Температура");
    lcd.setCursor(0, 1);
    if (flagAuto == 0)
    {
      lcd.print(L"Ручной");
    }
    else
    {
      lcd.print(L"Автоматический");
    }
    flagMode = 0;
    flagAuto = !flagAuto;
  }
}

void secondMenuEnc()
{
  if (flagSwitchMenu == 1 && flagSecondMenu == 0)
  {
    flagSwitchMenu = !flagSwitchMenu;
    flagSecondMenu = 1;
    flagSecondMenuRedraw = 1;
    flagArrow = 1;
  }
  if (flagSwitchMenu == 1 && flagSecondMenu == 1)
  {
    flagSwitchMenu = !flagSwitchMenu;
    flagSecondMenu = 0;
    flagMode = 1;
  }
}

void secondMenuLcd()
{
  if (flagSecondMenu == 1 && flagSecondMenuRedraw == 1)
  {
    flagSecondMenuRedraw = 0;
    lcdInit();
    if (flagArrow == 1 && flagScroll == 0)
    {
      lcd.print(arrow);
      // if (flagArrowHold == 0)
      // {
      flagArrow = !flagArrow;
      // }
    }
    lcd.setCursor(2, 0);
    lcd.print(L"Верх.t");
    lcd.setCursor(9, 0);
    lcd.print(countH);
    lcd.setCursor(0, 1);
    if (flagArrow == 1 && flagScroll == 1)
    {
      lcd.print(arrow);
      // if (flagArrowHold == 0)
      // {
      flagArrow = !flagArrow;
      // }
    }
    lcd.setCursor(2, 1);
    lcd.print(L"Ниж.t");
    lcd.setCursor(9, 1);
    lcd.print(countL);
    if (flagArrowHold == 0)
    {
      flagScroll = !flagScroll;
    }
    flagArrowHold = 0;
  }
}

void loop()
{
  enc1.tick();
  mainMenuEnc();
  secondMenuEnc();
  mainMenuLcd();
  secondMenuLcd();
}

 

grabbly
Offline
Зарегистрирован: 14.04.2020
String arrow = ">>";
lcd.print(arrow);

Зачем так сложно? 

Если открыть таблицу знакогенератора, то можно симпатичную стрелочку выводить одним байтом. см. столбец строка 0111 1110 (7Е в 16 тиричном значении)

в программе выводится так: \xB7E

таким образом будет стрелочка, и память не занимает

lcd.print("\xB7E");

 

 

kalapanga
Offline
Зарегистрирован: 23.10.2016

grabbly пишет:

Если открыть таблицу знакогенератора, то можно симпатичную стрелочку выводить одним байтом.

Правильнее было бы так - Если открыть таблицу знакогенератора и там есть стрелочка, то....

grabbly
Offline
Зарегистрирован: 14.04.2020

kalapanga пишет:

grabbly пишет:

Если открыть таблицу знакогенератора, то можно симпатичную стрелочку выводить одним байтом.

Правильнее было бы так - Если открыть таблицу знакогенератора и там есть стрелочка, то....

Согласен, нужно убедиться какая таблица зашита в генераторе, но большинство использует дешевые дисплейчики на базеhd44780 или чуть дороже на st7066 о чем косвенно говорят строки:

#include <LCD_1602_RUS.h>
LCD_1602_RUS lcd(0x27, 16, 2);

где 0х27 адрес I2C преобразователя по этому написал "в лоб"