Проблема с созданием меню на дисплее.
- Войдите на сайт для отправки комментариев
Здравствуйте друзья! И снова я к вам за подсказкой:
Прикупил себе дисплейчик ST7920 128x64 и решил сделать менюшку для управления шаговиком пока он в пути.Воспользовался библиотекой U8glib и её примером создания меню,немного пределав его под себя.А застрял на многоуговневости. Нужно создать в меню "Setings" подменю с пунктами "Zero point" и "Calibration",но почему - то не удается это осуществить.При входе в меню "Setings" ничего нету,пустой экран.
#include "U8glib.h"
U8GLIB_ST7920_128X64_4X u8g(52, 51, 53);
#include <Keypad.h>
const byte ROWS = 4; //Количество строк клавиатуры
const byte COLS = 4; //Количество колонок клавиатуры
//Определяем символы соответствия клавиатуры
char hexaKeys[ROWS][COLS] = {
{'1','2','3','^'},
{'4','5','6','V'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {38, 24, 26, 30}; //Подключам строки клавиатуры на пинах 8 1 2 4
byte colPins[COLS] = {28, 32, 34, 36}; //Подключам колонки клавиатуры на пинах 3 5 6 7
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
char customKey = customKeypad.getKey();
int KEY;
int Length = 0;
int data=0;
#define MENU_ITEMS 3
const char *menu_strings[MENU_ITEMS] = { "MANUAL", "AUTO", "SETINGS",};
#define MENU_SEC_ITEMS 3
const char *menu2_strings[MENU_SEC_ITEMS] = {"ZERO POINT", "CALIBRATION"};
uint8_t menu_current = 0;
uint8_t menu_redraw_required = 0;
uint8_t menu_sec_current = 0;
uint8_t menu_sec_redraw_required = 0;
void drawMenu(void) {
uint8_t i, h;
u8g_uint_t w, d;
u8g.setFont(u8g_font_timB18);
u8g.setFontRefHeightText();
u8g.setFontPosTop();
h = u8g.getFontAscent()-u8g.getFontDescent();
w = u8g.getWidth();
for( i = 0; i < MENU_ITEMS; i++ ) {
d = (w-u8g.getStrWidth(menu_strings[i]))/2;
u8g.setDefaultForegroundColor();
if ( i == menu_current ) {
u8g.drawBox(0, i*h-1, w, h-1);
u8g.setDefaultBackgroundColor();
}
u8g.drawStr(d, i*h, menu_strings[i]);
}
}
void DrawMenu(void){
uint8_t i, h;
u8g_uint_t w, d;
u8g.setFont(u8g_font_timB18);
u8g.setFontRefHeightText();
u8g.setFontPosTop();
h = u8g.getFontAscent()-u8g.getFontDescent();
w = u8g.getWidth();
for( i = 3; i < MENU_SEC_ITEMS; i++ ) {
d = (w-u8g.getStrWidth(menu2_strings[i]))/2;
u8g.setDefaultForegroundColor();
if ( i == menu_sec_current ) {
u8g.drawBox(0, i*h-1, w, h-1);
u8g.setDefaultBackgroundColor();
}
u8g.drawStr(d, i*h, menu_strings[i]);
}
}
void setup() {
menu_redraw_required = 1; // force initial redraw
Serial.begin(115200);
}
void loop() {
char customKey = customKeypad.getKey();
if (customKey){
if(customKey >= '0' && customKey <= '9'){ //если нажата кнопка от 0-9
data = data*10+customKey-48; //передвигаем каретку в право и присваеваем data это значение
}
if(customKey == 'D' || customKey == 'C'){
Length = data;
}
Serial.print("Input = ");
Serial.println(data);
Serial.print("OUT = ");
Serial.println(Length);
}
if (customKey == '^'){
if ( menu_current == 0 )
menu_current = MENU_ITEMS;
menu_current--;
menu_redraw_required = 1;}
if (customKey == 'V'){
menu_current++;
if ( menu_current >= MENU_ITEMS )
menu_current = 0;
menu_redraw_required = 1;}
////////////////////////////////////////////
// Пункт меню Manual
if(menu_current == 0){
if (customKey == 'C' || customKey == 'D' ){
u8g.firstPage();
do {
u8g.setFont(u8g_font_helvB10);
u8g.setPrintPos( 13, 12);
u8g.print("MANUAL SIZE");
u8g.drawLine(0, 13, 127, 13);
u8g.setFont(u8g_font_fub30);
u8g.setPrintPos( 18, 55);
u8g.print(data); }
while( u8g.nextPage() );
}
}
// Пункт меню Auto
if(menu_current == 1){
if (customKey == 'C' || customKey == 'D' ){
u8g.firstPage();
do {
u8g.setFont(u8g_font_8x13);
u8g.setPrintPos( 3, 10);
u8g.print("No.SIZE No.SIZE");
u8g.drawLine(63, 0, 63, 63);
u8g.drawLine(0, 12, 127, 12);
u8g.setFont(u8g_font_timB14);
//Первая колонка
u8g.setPrintPos( 2, 29);
u8g.print("99.3000");
u8g.setPrintPos( 2, 45);
u8g.print("99.3000");
u8g.setPrintPos( 2, 61);
u8g.print("99.3000");
//Вторая колонка
u8g.setPrintPos( 66, 29);
u8g.print("99.3000");
u8g.setPrintPos( 66, 45);
u8g.print("99.3000");
u8g.setPrintPos( 66, 61);
u8g.print("99.3000");}
while( u8g.nextPage() );
}
}
// Пункт меню Setings
if(menu_current == 2){
if (customKey == 'C' || customKey == 'D' ){
menu_sec_redraw_required = 1;
u8g.firstPage();
do {
DrawMenu();
}
while( u8g.nextPage() );
}
}
if ( menu_redraw_required != 0 ) {
u8g.firstPage();
do {
drawMenu();
} while( u8g.nextPage() );
menu_redraw_required = 0;
}
if ( menu_sec_redraw_required != 0 ) {
u8g.firstPage();
do {
DrawMenu();
} while( u8g.nextPage() );
menu_sec_redraw_required = 0;
}
}
И ещё одна проблемма,в пункте "Manual" я ввожу данные,но они начинают отображатся только тогда когда нажму на "C" либо "D" а нужно чтобы при вводе они одновременно отображались на экран и после нажатия на "C" либо "D" через 5 секунд обнулились.
Я не гуру,пока учусь.Пожалуйста подскажите что сделал не так.
Нашел ещё один косяк,нету выхода из подменю,сейчас если зайти допустим в MANUAL и нажать на стрелку вверх или вниз то оно автоматом выходит из подменю на главное меню.
void drawMenu(void){ ... } void DrawMenu(void){ ... }Давать такие малоразличимые имена, плохая практика.
И void, в скобках, писать не нужно.
Да,понимаю,написал и забыл преименовать.
кстати нашел косяк почему не отображалось ничего при переходе в Setings.
вместо
было
Исправил.Осталось теперь понять как сделать чтобы в подменю Setings можно было выбирать пункты так как сейчас при нажатии вниз или вверх возвращается назад на начальное меню.
Исправленый код:
#include "U8glib.h" U8GLIB_ST7920_128X64_4X u8g(52, 51, 53); #include <Keypad.h> const byte ROWS = 4; //Количество строк клавиатуры const byte COLS = 4; //Количество колонок клавиатуры //Определяем символы соответствия клавиатуры char hexaKeys[ROWS][COLS] = { {'1','2','3','^'}, {'4','5','6','V'}, {'7','8','9','C'}, {'*','0','#','D'} }; byte rowPins[ROWS] = {38, 24, 26, 30}; //Подключам строки клавиатуры на пинах 8 1 2 4 byte colPins[COLS] = {28, 32, 34, 36}; //Подключам колонки клавиатуры на пинах 3 5 6 7 Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); char customKey = customKeypad.getKey(); int KEY; int Length = 0; int data=0; #define MENU_ITEMS 3 const char *menu_strings[MENU_ITEMS] = { "MANUAL", "AUTO", "SETINGS",}; #define MENU_SEC_ITEMS 2 const char *menu2_strings[MENU_SEC_ITEMS] = {"ZERO POINT", "CALIBRATION"}; uint8_t menu_current = 0; uint8_t menu_redraw_required = 0; uint8_t menu_sec_current = 0; uint8_t menu_sec_redraw_required = 0; void drawMenu(void) { uint8_t i, h; u8g_uint_t w, d; u8g.setFont(u8g_font_timB18); u8g.setFontRefHeightText(); u8g.setFontPosTop(); h = u8g.getFontAscent()-u8g.getFontDescent(); w = u8g.getWidth(); for( i = 0; i < MENU_ITEMS; i++ ) { d = (w-u8g.getStrWidth(menu_strings[i]))/2; u8g.setDefaultForegroundColor(); if ( i == menu_current ) { u8g.drawBox(0, i*h-1, w, h-1); u8g.setDefaultBackgroundColor(); } u8g.drawStr(d, i*h, menu_strings[i]); } } void Second_Menu(void){ uint8_t i, h; u8g_uint_t w, d; u8g.setFont(u8g_font_ncenB10); u8g.setFontRefHeightText(); u8g.setFontPosTop(); h = u8g.getFontAscent()-u8g.getFontDescent(); w = u8g.getWidth(); for( i = 0; i < MENU_SEC_ITEMS; i++ ) { d = (w-u8g.getStrWidth(menu2_strings[i]))/2; u8g.setDefaultForegroundColor(); if ( i == menu_sec_current ) { u8g.drawBox(0, i*h-1, w, h); u8g.setDefaultBackgroundColor(); } u8g.drawStr(d, i*h, menu2_strings[i]); } } void setup() { menu_redraw_required = 1; // force initial redraw u8g.setRot180(); Serial.begin(115200); } void loop() { char customKey = customKeypad.getKey(); if (customKey){ if(customKey >= '0' && customKey <= '9'){ //если нажата кнопка от 0-9 data = data*10+customKey-48; //передвигаем каретку в право и присваеваем data это значение } if(customKey == 'D' || customKey == 'C'){ Length = data; } Serial.print("Input = "); Serial.println(data); Serial.print("OUT = "); Serial.println(Length); } //Кнопка вверх if (customKey == '^'){ if ( menu_current == 0 ) menu_current = MENU_ITEMS; menu_current--; menu_redraw_required = 1;} //Кнопка вниз if (customKey == 'V'){ menu_current++; if ( menu_current >= MENU_ITEMS ) menu_current = 0; menu_redraw_required = 1;} //Кнопка возврат "*" if (customKey == '*'){ menu_current = 0; menu_redraw_required = 1;} //////////////////////////////////////////// // Пункт меню Manual if(menu_current == 0){ if (customKey == 'C' || customKey == 'D' ){ u8g.firstPage(); do { u8g.setFont(u8g_font_helvB10); u8g.setPrintPos( 13, 12); u8g.print("MANUAL SIZE"); u8g.drawLine(0, 13, 127, 13); u8g.setFont(u8g_font_fub30); u8g.setPrintPos( 18, 55); u8g.print(Length); if(customKey == 'D' || customKey == 'C'){ Length = data; data = 0; } } while( u8g.nextPage() ); } } // Пункт меню Auto if(menu_current == 1){ if (customKey == 'C' || customKey == 'D' ){ u8g.firstPage(); do { u8g.setFont(u8g_font_8x13); u8g.setPrintPos( 3, 10); u8g.print("No.SIZE No.SIZE"); u8g.drawLine(63, 0, 63, 63); u8g.drawLine(0, 12, 127, 12); u8g.setFont(u8g_font_timB14); //Первая колонка u8g.setPrintPos( 2, 29); u8g.print("99.3000"); u8g.setPrintPos( 2, 45); u8g.print("99.3000"); u8g.setPrintPos( 2, 61); u8g.print("99.3000"); //Вторая колонка u8g.setPrintPos( 66, 29); u8g.print("99.3000"); u8g.setPrintPos( 66, 45); u8g.print("99.3000"); u8g.setPrintPos( 66, 61); u8g.print("99.3000");} while( u8g.nextPage() ); } } // Пункт меню Setings if(menu_current == 2){ if (customKey == 'C' || customKey == 'D' ){ menu_sec_redraw_required = 1; u8g.firstPage(); do { Second_Menu(); } while( u8g.nextPage() ); } } if ( menu_redraw_required != 0 ) { u8g.firstPage(); do { drawMenu(); } while( u8g.nextPage() ); menu_redraw_required = 0; } if ( menu_sec_redraw_required != 0 ) { u8g.firstPage(); do { Second_Menu(); } while( u8g.nextPage() ); menu_sec_redraw_required = 0; } }Ну и пока не разобрался с отображение данных во время ввода в пункте MANUAL.
Странно, что Вы проверяете состояние customKey только при вводе чисел.
Вот тут:
// Пункт меню Manual if(menu_current == 0){ if (customKey == 'C' || customKey == 'D' ){ u8g.firstPage(); do { ... if(customKey == 'D' || customKey == 'C'){ Length = data; data = 0; } } while( u8g.nextPage() ); } }Зачем второй раз проверять, что код клавиши 'D' или 'C'? Если проверка выше как раз обеспечивает это условие. И в самом начале loop() уже выполнялось присвоение "Length = data;", второй-то раз зачем?
Не думали перейти на использование конструкции switch-case?
Спасобо за подсказку,убрал лишнюю проверку.
Не совсем понял что вs имели введу
"Странно, что Вы проверяете состояние customKey только при вводе чисел." .
Про switch-case пока не думал,да и облегчит ли это задачу?
Пока Вы правы,это за гранью моего понимания.
Но если у Вас есть настолько большие знания то може поможете в решении проблеммы?
И void, в скобках, писать не нужно.
Что, Клапа успел и это запретить?
Пока Вы правы,это за гранью моего понимания.
Но если у Вас есть настолько большие знания то може поможете в решении проблеммы?
Понял,я по сути и сразу написал что не знаток,по этому и прошу помощи чтобы понять и разобраться.Спасибо и на этом.