Esp32 rotary encoder menu.....help!!!!!!!!
Posted: Tue Jan 04, 2022 4:20 am
Hello guys, I'm new to esp32 and learning programming....i am making a rc transmitter using esp32 and i need a menu system for that...i found one on internet but that code compiles on Arduino boards but dosent compile on esp32 dev module. Can someone please convert the code from Arduino to esp32???
Current code uses interrupts and timer for rotary encoder.it has support for st7920(128*64 glcd).
I want to use the lcd and a rotary encoder with esp32 instead of Arduino.
Someone please convert the code from Arduino to esp32. That will be so much helpful.
Current code uses interrupts and timer for rotary encoder.it has support for st7920(128*64 glcd).
I want to use the lcd and a rotary encoder with esp32 instead of Arduino.
Someone please convert the code from Arduino to esp32. That will be so much helpful.
Code: Select all
// ========================================================
// INCLUDES
// ========================================================
// for display
#include <U8g2lib.h>
// for timer
#include <TimerOne.h>
// for rotary encoder
#include <Rotary.h>
// ========================================================
// pin config
// ========================================================
// Rotary encoder with switch
#define ROTARY_SWITCH 4 // A1
#define ROTARY_PIN1 2
#define ROTARY_PIN2 3
#define ROTARY_ACCEL_OFFSET1 20
#define ROTARY_ACCEL_OFFSET2 50
#define ROTARY_ACCEL_OFFSET3 70
unsigned long rotaryLastMove;
bool rotaryButtonPressed = false;
// ========================================================
// INITS
// ========================================================
// Display
U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* CS=*/ 10, /* reset=*/ 8);
// Rotary Encoder
Rotary rotary = Rotary(ROTARY_PIN1, ROTARY_PIN2);
// ========================================================
// DEFAULTS
// ========================================================
// Timer
#define TIMER 100
// Display and menu stuff
int displayCurrentPage = 0;
bool setNeedsDisplay = true;
// Main menu fixed to 3 items, left, center, right...
#define MENU_SELECTED_TIMEOUT 40000
#define MENU_POS_Y 62
#define MENU_POS_Y_HIDDEN 76
#define MENU_ANIMATION_PIXEL_STEP 5
String menuItems[3] = {"HOME", "NETWORK", "SETUP"};
int menuActive = 1; // left active
int menuSelected = menuActive; // selected
bool menuPageMode = false; // true => rotary encoder control page and not menu
// Menu animation
bool menuAnimationRunning = false;
int menuPosY = MENU_POS_Y;
// Test slider
int sliderPosX = 64;
// ========================================================
// PAGES STUFF
// ========================================================
#define SETUP_MENU_ITEMS 9
char *setupMenuItems[SETUP_MENU_ITEMS] = {"CHINOOK", "HELI-COPTER", "BI-COPTER", "TRI-COPTER", "QUAD-COPTER", "RC-PLANE", "RC-JET V-1","RC-CAR V-2", "VERSION"};
int setupMenuSelected = 1;
// ========================================================
// SETUP
// ========================================================
void setup() {
// put your setup code here, to run once:
// Menu Button
pinMode(ROTARY_SWITCH, INPUT);
digitalWrite(ROTARY_SWITCH, INPUT_PULLUP);
// OLED Display
u8g2.begin();
setNeedsDisplay = true;
Timer1.initialize(TIMER);
Timer1.attachInterrupt(timerEvent);
//delay(1000);
}
// ========================================================
// LOOP
// ========================================================
void loop() {
// put your main code here, to run repeatedly:
if (menuAnimationRunning) {
if (menuPageMode && menuPosY < MENU_POS_Y_HIDDEN) {
// do animation
menuPosY = menuPosY + MENU_ANIMATION_PIXEL_STEP;
setNeedsDisplay = true;
}
if (!menuPageMode && menuPosY > MENU_POS_Y) {
// do animation
menuPosY = menuPosY - MENU_ANIMATION_PIXEL_STEP;
setNeedsDisplay = true;
}
}
if (menuAnimationRunning && (menuPosY == MENU_POS_Y || menuPosY == MENU_POS_Y_HIDDEN)) {
// looks like animation is done
menuAnimationRunning = false;
}
if (setNeedsDisplay) {
noInterrupts();
displayRenderCurrentPage();
setNeedsDisplay = false;
interrupts();
}
}
// ========================================================
// TIMER
// ========================================================
void timerEvent() {
// Menu logic
unsigned long timeOffset = millis() - rotaryLastMove;
if (timeOffset > MENU_SELECTED_TIMEOUT) {
// deselect menu
menuSelected = menuActive;
rotaryLastMove = millis();
setNeedsDisplay = true;
}
// Rotary Encoder
unsigned char result = rotary.process();
if (result) {
if (!menuPageMode) {
if (result == DIR_CW) {
// right
if (menuSelected < 3) {
menuSelected++;
}
} else {
// left
if (menuSelected > 1) {
menuSelected--;
}
}
setNeedsDisplay = true;
} else {
// Acceleration
byte acceleration = 1;
unsigned long timeOffset = millis() - rotaryLastMove;
//Serial.println(timeOffset);
if (displayCurrentPage == 0 || displayCurrentPage == 1) {
if (timeOffset < ROTARY_ACCEL_OFFSET1) {
acceleration = 16;
} else if (timeOffset < ROTARY_ACCEL_OFFSET2) {
acceleration = 4;
} else if (timeOffset < ROTARY_ACCEL_OFFSET3) {
acceleration = 2;
}
// Development test => control slider
if (result == DIR_CW) {
// right
if (sliderPosX < 128) {
sliderPosX = sliderPosX + acceleration;
}
} else {
// left
if (sliderPosX > 0) {
sliderPosX = sliderPosX - acceleration;
}
}
setNeedsDisplay = true;
}
if (displayCurrentPage == 2) {
if (result == DIR_CW) {
// right
setupMenuSelected++;
} else {
// left
setupMenuSelected--;
}
if (setupMenuSelected > SETUP_MENU_ITEMS - 1) {
setupMenuSelected = SETUP_MENU_ITEMS - 1;
}
if (setupMenuSelected < 1) {
setupMenuSelected = 0;
}
setNeedsDisplay = true;
}
}
rotaryLastMove = millis();
}
// Rotary button
if (buttonEvent()) {
rotaryLastMove = millis();
if (menuActive == menuSelected) {
if (!menuPageMode) {
// give controls to page (button press on selected page)
menuPageMode = true;
menuAnimationRunning = true;
sliderPosX = 64;
setNeedsDisplay = true;
#ifdef DEBUG
Serial.println("PAGE MODE ON");
#endif
} else {
menuPageMode = false;
menuAnimationRunning = true;
setNeedsDisplay = true;
sliderPosX = 64;
setupMenuSelected = 0;
#ifdef DEBUG
Serial.println("PAGE MODE OFF");
#endif
}
}
if (!menuPageMode) {
menuActive = menuSelected;
if (menuActive == 1) {
displayCurrentPage = 0;
}
if (menuActive == 2) {
displayCurrentPage = 1;
}
if (menuActive == 3) {
displayCurrentPage = 2;
}
setNeedsDisplay = true;
}
}
// Action button => reset page mode during development
#ifdef BUTTON1_PIN
if (digitalRead(BUTTON1_PIN) == 0 && menuPageMode) {
menuPageMode = false;
menuAnimationRunning = true;
setNeedsDisplay = true;
sliderPosX = 64;
#ifdef DEBUG
Serial.println("PAGE MODE OFF");
#endif
}
#endif
}
// ========================================================
// MENU BUTTON
// ========================================================
bool buttonEvent() {
bool result = false;
bool menuButton = false;
if (digitalRead(ROTARY_SWITCH) == 1) {
menuButton = true;
}
if (menuButton && !rotaryButtonPressed) {
rotaryButtonPressed = true;
} else if (!menuButton && rotaryButtonPressed) {
rotaryButtonPressed = false;
result = true;
// FIXME: debounce for try, check if it's really needed
//delay(4);
}
return result;
}
// ========================================================
// DISPLAY - Screen Drawing
// ========================================================
void displayRenderCurrentPage() {
// OLED Display update
u8g2.firstPage();
do {
if (displayCurrentPage == 0) {
u8g2.setFont(u8g2_font_8x13B_tr);
u8g2.drawStr(0, 12, "HOME");
}
if (displayCurrentPage == 1) {
u8g2.setFont(u8g2_font_8x13B_tr);
u8g2.drawStr(0, 12, "SETTINGS");
}
if (displayCurrentPage == 2) {
if (!menuPageMode) {
u8g2.setFont(u8g2_font_8x13B_tr);
u8g2.drawStr(0, 10, "models available");
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 18, "1) CHINOOK");
u8g2.drawStr(0, 25, "2) HELICOPTER");
u8g2.drawStr(0, 32, "3) BI-COPTER");
u8g2.drawStr(0, 39, "4) TRI-COPTER");
u8g2.drawStr(0, 46, "5) QUADCOPTER");
u8g2.drawStr(70, 18, "6) AIRPLANE");
u8g2.drawStr(70, 25, "7) RC-JET");
u8g2.drawStr(70, 32, "8) RC-CAR");
} else {
drawPageMenu();
if (setupMenuSelected == 0) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "CHINOOK");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 1) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "HELICOPTER");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 2) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "BI-COPTER");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 3) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "TRI-COPTER");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 4) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "QUADCOPTER");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 5) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "AIRPLANE");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 6) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "RC-JET");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 7) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "RC-CAR");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 8) {
// Version & Info
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.setCursor(0, 28);
u8g2.print("RC TRANSMITTER");
u8g2.setCursor(0, 38);
u8g2.print("SW-VER. - 0.1");
u8g2.setCursor(0, 48);
u8g2.print("HW-VER. - 2.0");
u8g2.setCursor(0, 58);
u8g2.print("BY- VARUN SINGH");
}
}
}
if (displayCurrentPage == 0 || displayCurrentPage == 1) {
u8g2.setFont(u8g2_font_5x7_tr);
if (menuPageMode) {
u8g2.drawStr(0, 28, "ROTARY CONTROL ON PAGE");
u8g2.setCursor(0, 46);
u8g2.print("VALUE ");
u8g2.print(sliderPosX);
} else {
u8g2.drawStr(0, 28, "ROTARY CONTROL ON MENU");
}
drawSlider(31);
}
drawMenuBar();
} while ( u8g2.nextPage() );
}
void drawPageMenu() {
u8g2.setFont(u8g2_font_5x7_tr);
if (displayCurrentPage == 2) {
// center text
u8g2.drawRBox(36, 0, 58, 10, 2); //(x,y,w,h,r)
u8g2.setDrawColor(0);
u8g2.setCursor(38, 8);
u8g2.print(setupMenuItems[setupMenuSelected]);
u8g2.setDrawColor(1);
bool drawLeftTriangle = false;
bool drawRightTriangle = false;
if (setupMenuSelected < SETUP_MENU_ITEMS - 1) {
drawRightTriangle = true;
}
if (setupMenuSelected > 0) {
drawLeftTriangle = true;
}
if (drawLeftTriangle) {
// Triangle left
u8g2.drawTriangle(4, 1, 4, 9, 0, 5);
}
if (drawRightTriangle) {
// Triangle right
u8g2.drawTriangle(128 - 5, 1, 128 - 5, 9, 127, 5);
}
//u8g2.drawHLine(0, 10, 128);
}
}
void drawSlider(int yPos) {
u8g2.drawFrame(0, yPos, 128, 6);
if (sliderPosX < 1) {
sliderPosX = 0;
}
if (sliderPosX > 128) {
sliderPosX = 128;
}
u8g2.drawVLine(sliderPosX, yPos, 6);
}
void drawMenuBar() {
int textY = menuPosY;
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.setDrawColor(1);
if (textY < MENU_POS_Y_HIDDEN) {
// left menu==================================================================================================
if (menuActive == 1) {
u8g2.drawRBox(0, 53, 25, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(0);
}
if (menuActive != menuSelected && menuSelected == 1) {
u8g2.drawRFrame(0, 53, 25, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(1);
}
u8g2.setCursor(3, 62);
u8g2.print("HOME");
u8g2.setDrawColor(1);
// center menu=================================================================================================
if (menuActive == 2) {
u8g2.drawRBox(45, 53, 40, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(0);
}
if (menuActive != menuSelected && menuSelected == 2) {
u8g2.drawRFrame(45, 53, 40, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(1);
}
u8g2.setCursor(48, 62);
u8g2.print("SETTING");
u8g2.setDrawColor(1);
// right menu==================================================================================================
if (menuActive == 3) {
u8g2.drawRBox(104, 53, 24, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(0);
}
if (menuActive != menuSelected && menuSelected == 3) {
u8g2.drawRFrame(104, 53, 24, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(1);
}
u8g2.setCursor(107, 62);
u8g2.print("MODE");
u8g2.setDrawColor(1);
}
}