Попытка создать систему меню с OLED и ESP32. ⇐ C++
Попытка создать систему меню с OLED и ESP32.
I'm working on a personal project, involving an ESP32-S2, OLED (SH1106) and generic button encoder. Right now I'm at a stage where I want to put together a simple menu system that's just 3 levels deep.
Main Menu Sub Menu 1 Preset1 Preset2 Preset3 . . . Sub Menu 2 Number Selector Found a library that partially helps me to put together what I wanted. OLEDDisplayUi specifically, single page options with an indicator above.
I'm fairly new to C++ so I might have tried to bite more than I can chew. This is my code so far
#include "SPI.h" #include "Wire.h" #include "SH1106Wire.h" #include "AiEsp32RotaryEncoder.h" #include "OLEDDisplayUi.h" #include "images.h" #define ROTARY_ENCODER_A_PIN 7 #define ROTARY_ENCODER_B_PIN 5 #define ROTARY_ENCODER_BUTTON_PIN 3 #define ROTARY_ENCODER_STEPS 4 AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS); SH1106Wire display(0x3c, 8, 9); OLEDDisplayUi ui ( &display ); unsigned long shortPressAfterMiliseconds = 50; unsigned long longPressAfterMiliseconds = 600; void shortPress() { Serial.println("Button SHORT press"); Serial.println(ui.getUiState()->frameState); } void longPress() { Serial.println("Button LONG press"); } void IRAM_ATTR readEncoderISR() { rotaryEncoder.readEncoder_ISR(); } void encoderButton() { static unsigned long lastTimeButtonDown = 0; static bool wasButtonDown = false; static bool wasLong = false; bool isEncoderButtonDown = rotaryEncoder.isEncoderButtonDown(); if ( isEncoderButtonDown ) { if ( !wasButtonDown ) { lastTimeButtonDown = millis(); wasButtonDown = true; } if ( !wasLong ) { if ( millis() - lastTimeButtonDown >= longPressAfterMiliseconds ) { longPress(); wasLong = true; } } return; } if ( wasButtonDown && !wasLong ) { if ( millis() - lastTimeButtonDown >= shortPressAfterMiliseconds ) { shortPress(); wasLong = false; } } wasButtonDown = false; wasLong = false; } void encoderLoop() { if (rotaryEncoder.encoderChanged()) { static int8_t prev = 0; int8_t curr = rotaryEncoder.readEncoder(); if ( curr > prev ) { ui.nextFrame(); } else if ( curr < prev ) { ui.previousFrame(); } prev = rotaryEncoder.readEncoder(); } encoderButton(); } void frame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_24); display->drawString(64 + x, 19 + y, "Presets"); } void frame2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_24); display->drawString(64 + x, 19 + y, "Precise"); } FrameCallback frames[] = { frame1, frame2 }; int frameCount = 2; void setupMainMenu() { ui.setTargetFPS(60); ui.setActiveSymbol(activeSymbol); ui.setInactiveSymbol(inactiveSymbol); ui.setIndicatorPosition(TOP); ui.setIndicatorDirection(LEFT_RIGHT); ui.setFrameAnimation(SLIDE_LEFT); ui.setFrames(frames, frameCount); ui.disableAutoTransition(); ui.setTimePerTransition(60); ui.init(); } void setup() { Serial.begin(115200); Serial.println(); Serial.println(); pinMode(ROTARY_ENCODER_A_PIN, INPUT_PULLUP); pinMode(ROTARY_ENCODER_B_PIN, INPUT_PULLUP); rotaryEncoder.begin(); rotaryEncoder.setup(readEncoderISR); rotaryEncoder.setAcceleration(80); setupMainMenu(); display.flipScreenVertically(); } void loop() { encoderLoop(); ui.update(); } Also a Wokwi link.
Idea is to rotate the encoder to select a frame, short press to move down a submenu, long press to move up. I tried messing around with Classes and Objects, migrating frame functions to achive a modular system. Primarily because the number of Presets can vary depending on the situation. Everything else is fairly static. My knowledge on C++ is still limited, and some examples or pointers would be greatly appreciated.
Источник: https://stackoverflow.com/questions/780 ... -and-esp32
I'm working on a personal project, involving an ESP32-S2, OLED (SH1106) and generic button encoder. Right now I'm at a stage where I want to put together a simple menu system that's just 3 levels deep.
Main Menu Sub Menu 1 Preset1 Preset2 Preset3 . . . Sub Menu 2 Number Selector Found a library that partially helps me to put together what I wanted. OLEDDisplayUi specifically, single page options with an indicator above.
I'm fairly new to C++ so I might have tried to bite more than I can chew. This is my code so far
#include "SPI.h" #include "Wire.h" #include "SH1106Wire.h" #include "AiEsp32RotaryEncoder.h" #include "OLEDDisplayUi.h" #include "images.h" #define ROTARY_ENCODER_A_PIN 7 #define ROTARY_ENCODER_B_PIN 5 #define ROTARY_ENCODER_BUTTON_PIN 3 #define ROTARY_ENCODER_STEPS 4 AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS); SH1106Wire display(0x3c, 8, 9); OLEDDisplayUi ui ( &display ); unsigned long shortPressAfterMiliseconds = 50; unsigned long longPressAfterMiliseconds = 600; void shortPress() { Serial.println("Button SHORT press"); Serial.println(ui.getUiState()->frameState); } void longPress() { Serial.println("Button LONG press"); } void IRAM_ATTR readEncoderISR() { rotaryEncoder.readEncoder_ISR(); } void encoderButton() { static unsigned long lastTimeButtonDown = 0; static bool wasButtonDown = false; static bool wasLong = false; bool isEncoderButtonDown = rotaryEncoder.isEncoderButtonDown(); if ( isEncoderButtonDown ) { if ( !wasButtonDown ) { lastTimeButtonDown = millis(); wasButtonDown = true; } if ( !wasLong ) { if ( millis() - lastTimeButtonDown >= longPressAfterMiliseconds ) { longPress(); wasLong = true; } } return; } if ( wasButtonDown && !wasLong ) { if ( millis() - lastTimeButtonDown >= shortPressAfterMiliseconds ) { shortPress(); wasLong = false; } } wasButtonDown = false; wasLong = false; } void encoderLoop() { if (rotaryEncoder.encoderChanged()) { static int8_t prev = 0; int8_t curr = rotaryEncoder.readEncoder(); if ( curr > prev ) { ui.nextFrame(); } else if ( curr < prev ) { ui.previousFrame(); } prev = rotaryEncoder.readEncoder(); } encoderButton(); } void frame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_24); display->drawString(64 + x, 19 + y, "Presets"); } void frame2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_24); display->drawString(64 + x, 19 + y, "Precise"); } FrameCallback frames[] = { frame1, frame2 }; int frameCount = 2; void setupMainMenu() { ui.setTargetFPS(60); ui.setActiveSymbol(activeSymbol); ui.setInactiveSymbol(inactiveSymbol); ui.setIndicatorPosition(TOP); ui.setIndicatorDirection(LEFT_RIGHT); ui.setFrameAnimation(SLIDE_LEFT); ui.setFrames(frames, frameCount); ui.disableAutoTransition(); ui.setTimePerTransition(60); ui.init(); } void setup() { Serial.begin(115200); Serial.println(); Serial.println(); pinMode(ROTARY_ENCODER_A_PIN, INPUT_PULLUP); pinMode(ROTARY_ENCODER_B_PIN, INPUT_PULLUP); rotaryEncoder.begin(); rotaryEncoder.setup(readEncoderISR); rotaryEncoder.setAcceleration(80); setupMainMenu(); display.flipScreenVertically(); } void loop() { encoderLoop(); ui.update(); } Also a Wokwi link.
Idea is to rotate the encoder to select a frame, short press to move down a submenu, long press to move up. I tried messing around with Classes and Objects, migrating frame functions to achive a modular system. Primarily because the number of Presets can vary depending on the situation. Everything else is fairly static. My knowledge on C++ is still limited, and some examples or pointers would be greatly appreciated.
Источник: https://stackoverflow.com/questions/780 ... -and-esp32
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение