Мне нужна помощь в создании меню с использованием библиотеки u8g2

Я хочу создать проект с дисплеем (Nokia 5110) с использованием библиотеки u8g2. Вот код моей программы:

#include <Arduino.h>
#include <U8g2lib.h>
#include <TM1637Display.h>
#include <EEPROM.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

#define LED_PIN 5
#define BUTTON_PIN 6
#define BUZZ_PIN 7
#define BUTTON_L 2
#define BUTTON_R 3
#define BUTTON_START 4


//48x84 дисп.
U8G2_PCD8544_84X48_F_4W_SW_SPI u8g2(U8G2_R2, 13, 11, 10, 12, 8); //поворот, clk, DIN, CE, DC, RST//

byte lastButtonState = 0;
byte ledState;
float cpu_gauge = 0.0;
char buffer[40];
int move = 7;
float cpu_gauge_step = 0.5;
byte eeprom_led;


void set_led(){
  if( digitalRead(LED_PIN) == 1 ) ledState = 1;
      if( digitalRead(LED_PIN) == 0 ) ledState = 0;}


void backlight(){
byte buttonState = digitalRead(BUTTON_PIN);  //следим за состоянием кнопки
  if (buttonState != lastButtonState) {  //проверить, если не равно
    lastButtonState = buttonState;       //если пред. правда, сделать равным
      if (buttonState == HIGH) {                
        ledState = (ledState == HIGH) ? LOW : HIGH;
          digitalWrite(LED_PIN, ledState);    }}}


void status_bar(){
  if (cpu_gauge > cpu_gauge_step*1) u8g2.drawBox(2,13,6,8); //x, y, размер по x, размер по y
    if (cpu_gauge > cpu_gauge_step*2) u8g2.drawBox(2 + 1*move,13,6,8);     
      if (cpu_gauge > cpu_gauge_step*3) u8g2.drawBox(2 + 2*move,13,6,8);   
        if (cpu_gauge > cpu_gauge_step*4) u8g2.drawBox(2 + 3*move,13,6,8);   
          if (cpu_gauge > cpu_gauge_step*5) u8g2.drawBox(2 + 4*move,13,6,8);     
            if (cpu_gauge > cpu_gauge_step*6) u8g2.drawBox(2 + 5*move,13,6,8);     
              if (cpu_gauge > cpu_gauge_step*7) u8g2.drawBox(2 + 6*move,13,6,8);      
                if (cpu_gauge > cpu_gauge_step*8) u8g2.drawBox(2 + 7*move,13,6,8);  
                  if (cpu_gauge > cpu_gauge_step*9) u8g2.drawBox(2 + 8*move,13,6,8);      
                    if (cpu_gauge >= cpu_gauge_step*10) u8g2.drawBox(2 + 9*move,13,6,8); 
}


void setup(void) {
  pinMode(LED_PIN, OUTPUT);
    pinMode(BUTTON_PIN, INPUT);
      pinMode(BUZZ_PIN, OUTPUT);
       pinMode(BUTTON_L, INPUT);
        pinMode(BUTTON_R, INPUT);
          pinMode(A7, INPUT);
            pinMode(BUTTON_START, INPUT);
              eeprom_led = EEPROM.read(0);
                digitalWrite(LED_PIN, eeprom_led);
                  set_led(); //устанавливает состояние светодиода на 1 или 0 в зависимости от цифровой записи
            Serial.begin(9600);
            u8g2.begin();

}

void loop(void) {
  
    EEPROM.update(0,ledState);
    /*pomiar = EEPROM[ 0 ];
    delay(2500);//
    Serial.println(pomiar);//
    Serial.println(cpu_gauge);
    int pomiar = digitalRead(BUTTON_START);
    Serial.println(pomiar);*/

  backlight();
  cpu_gauge = analogRead(A7) * (5.0/1022);

  u8g2.firstPage();
  do {
  u8g2.drawRFrame(0,12,74,10,3); //позиция X,Y длина, ширина, угол
  status_bar();
  
  u8g2.setFont(u8g2_font_busdisplay8x5_tr);
    u8g2.setCursor(0,8);
      char pomiar_str[5];
        dtostrf(cpu_gauge,0,2, pomiar_str);
          sprintf(buffer, "LOAD: %sV", pomiar_str);
            u8g2.print(buffer);

  u8g2.setCursor(0,36);
    u8g2.print("bckgrnd_tsks:");
      u8g2.setCursor(48,48);
        sprintf(buffer, "led: %d", ledState);
          u8g2.print(buffer);
            u8g2.drawStr(0,48,"buzz:");
              
  if (cpu_gauge > 4.80){
    digitalWrite(7,1);
      u8g2.setCursor(0,48);
        u8g2.setFont(u8g2_font_busdisplay8x5_tr);
          u8g2.setFont(u8g2_font_open_iconic_play_1x_t);
          u8g2.drawGlyph(27, 48, 0x0040);}
  else
    digitalWrite(7,0);
 

  } while ( u8g2.nextPage() );}

Я успешно создал программу, которая:

-Имеет кнопку выключения и включения подсветки при каждом нажатии
-Записывает в EEPROM состояние светодиода и считывает его при запуске
-Отображает значение AnalogRead от потенциометра, а также отображает индикатор выполнения заданного значения
-Отображает состояние подсветки
-Включает зуммер, если значение AnalogRead превышает какое-то значение
-Отображает индикатор, если зуммер включен

Теперь давайте предположим, что то, что делает эта программа, называется опцией "А", и А в этом примере работает все время, потому что ничего другого нет. Я хочу создать меню, в котором будут варианты A, B, C, D. Предположим, что форматирование и действия кнопок пока не имеют значения.

A: Это то, что было описано ранее.
Б: Часы. Просто покажите часы.
C: Секундомер.
D: Установка времени.

Я вижу два способа создания такого меню.

1: создать выбираемое/прокручиваемое меню с метками, и, выбирая и нажимая кнопку, мы могли бы входить в нужную функцию.
2: отказаться от выбираемого меню. Одна кнопка переключает с варианта A на D. Что-то вроде часов Casio.

Я бы предпочел второй вариант, думаю, так будет проще

Чего я не понимаю, так это справочного руководства по U8G2. Я не очень понимаю концепцию буфера, sendBuffer, userInterfaceSelectionList и еще кое-чего, что пока не могу назвать.

Я понимаю, что мне нужно сделать некоторый массив функций. Нравится:

Array [] = {default_display();, clock();, stopwatch();, setting();)

И с помощью кнопки я бы прошел через этот массив следующим образом:

Array = 0;
 If (digitalRead(some_button_pin) == High){
  Array + 1;}
If (Array > 3){
 Array = 0;}

И в этих функциях были бы реализованы опции, например включение подсветки или что-то еще, что угодно,

Теперь я не знаю, имеет ли это какой-то смысл. Если это можно перевести в код. Я не знаю, нужно ли мне очищать дисплей и как это сделать только один раз перед вводом опции. Как мне сделать так, чтобы все переменные, связанные с часами, секундомером все еще работали, даже если я его не показываю. Я, честно говоря, растерялся, и мне просто нужно руководство по этому поводу, потому что у меня был только C в течение 1 семестра по электротехнике. Я не програмист, но очень хочется, чтобы это работало, но просто не объяснено так, как я не знаю, подтягивающие резисторы, где можно сделать какие-то предположения, и с их помощью объяснить, как что-то работает . Нет, это выглядит так:

void u8g2_SetBufferPtr(u8g2_t *u8g2, uint8_t *buf)

И да, я просто не знаю, как мне его обойти, как мне в нем ориентироваться. Спасибо за любую помощь.

, 👍-1

Обсуждение

ваш код очень плохо отформатирован... например, операторы if внутри функции void status_bar() не являются вложенными, все они должны иметь одинаковый отступ... то же самое со строками программы в setup( ) функция, @jsotola

Извините, меня не учили/не изучали этику кодирования, в смысле форматирования. Код был легко читаем для меня, и я мог легко найти нужные мне части :) В следующий раз я буду использовать автоформатирование перед публикацией, @kshysztof

Кстати, почему вы используете программный SPI для дисплея?, @Juraj

Потому что это дисплей 5110, и, насколько я знаю, он поддерживает только связь SPI., @kshysztof


1 ответ


Лучший ответ:

0

Я разобрался. Первое, что нужно сказать. Если вы привыкли создавать определения функций перед установкой, вы не сможете сделать это с библиотекой u8g2. Вы можете создавать определения функций после вызова u8g2.begin в настройках. Теперь есть два способа, как вы можете это сделать, в "часах Casio" fashion, но сначала создайте переменную, которая будет считывать, сколько раз вы нажали, и сохраните ее где-нибудь, а также добавьте условие, которое вернет ее к 1 после некоторого количества кликов. 1-й способ: Создайте кейс-переключатель, где переменная будет вашим переключателем, а в кейсах (от x до n) напишите что хотите, графику, текст, что угодно. Теперь проблема, с которой я столкнулся, заключается в том, что когда я вставил тот же код и изменил только небольшой текст, все это дало сбой. Прошел 1 и 2, нормально, а потом все из дела 3 и 4 слилось воедино, а дело 4 было пустым, как и экран. Я не мог это исправить, поэтому я придумал второй подход. Создайте столько условий ЕСЛИ, сколько у вас есть в меню. Итак, это выглядит так: If (menu_counter == 1){ //ваш ввод на экран// } И так для остальных. Насколько я проверял, это работает, даже если код одинаков для обоих операторов IF. Теперь мне нужно реализовать список выбора меню сверху. Оставляю ответ на свой вопрос, надеюсь, кому-то он будет полезен.

,