As I wrote in the topic, user upir created a great tutorial (Arduino OLED Menu Tutorial (for beginners - Arduino UNO, 128x64px SSD1306 OLED screen, u8g) - YouTube) to create a menu using the u8glib library. I would like to replace the buttons in his code with the use of an encoder (pins S1, S2, Key, 5V, GND). I don't know what I'm doing wrong but I've tried several times and the options in the menu keep jumping. I checked the encoder on another code and it works normally. So my question is how to convert the use of buttons to movement with the encoder?
Basically you change the code to take into account your new requirements.
However not knowing what you have done already or what is connected to what makes being more specific hard.
Please post your code in code tags and a schematic of your circuit, hand drawn is fine, Fritzing is not.
Also read the how to get the best from this forum sticky post.
Ok, so i wanted to just check how the encoder works. So i change a little bit the source code.
#include "U8glib.h"
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // Fast I2C / TWI
const unsigned char upir_logo [] PROGMEM = { // this is another way how to define images, using binary notation
B00010101, B11010111,
B00010101, B01000101,
B00010101, B10010110,
B00011001, B00010101
};
// 'icon_3dcube', 16x16px
const unsigned char bitmap_icon_liquid [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x20, 0x04, 0x20, 0x1c, 0x20, 0x04, 0x20, 0x3c, 0x20, 0x04,
0x20, 0x1c, 0x20, 0x04, 0x21, 0x24, 0x2a, 0xdc, 0x34, 0x04, 0x20, 0x04, 0x3f, 0xfc, 0x00, 0x00
};
// 'icon_battery', 16x16px
const unsigned char bitmap_icon_service [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x0b, 0xd0, 0x04, 0x20, 0x18, 0x18, 0x09, 0x90,
0x09, 0x90, 0x18, 0x18, 0x04, 0x20, 0x0b, 0xd0, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'icon_dashboard', 16x16px
const unsigned char bitmap_icon_work [] PROGMEM = {
0x00, 0x00, 0x02, 0x00, 0x72, 0xc6, 0x8a, 0xaa, 0x8a, 0x92, 0x8a, 0x82, 0xfa, 0x82, 0x8a, 0x82,
0x8a, 0x82, 0x8a, 0x82, 0x8a, 0x82, 0x8a, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 384)
const unsigned char* bitmap_icons[3] = {
bitmap_icon_liquid,
bitmap_icon_service,
bitmap_icon_work,
};
// 'scrollbar_background', 8x64px
const unsigned char bitmap_scrollbar_background [] PROGMEM = {
0x20, 0x70, 0x70, 0x70, 0x70, 0x70, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00
};
// 'item_sel_outline', 128x16px
const unsigned char bitmap_item_sel_outline [] PROGMEM = {
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// ------------------ end generated bitmaps from image2cpp ---------------------------------
const int NUM_ITEMS = 3; // number of items in the list and also the number of screenshots and screenshots with QR codes (other screens)
const int MAX_ITEM_LENGTH = 20; // maximum characters for the item name
char menu_items [NUM_ITEMS] [MAX_ITEM_LENGTH] = { // array with item names
{ "Liquid" },
{ "Service" },
{ "Work" },
};
// note - when changing the order of items above, make sure the other arrays referencing bitmaps
// also have the same order, for example array "bitmap_icons" for icons, and other arrays for screenshots and QR codes
#define BUTTON_UP_PIN 12 // pin for UP button
#define BUTTON_SELECT_PIN 8 // pin for SELECT button
#define BUTTON_DOWN_PIN 4 // pin for DOWN button
int button_up_clicked = 0; // only perform action when button is clicked, and wait until another press
int button_select_clicked = 0; // same as above
int button_down_clicked = 0; // same as above
int item_selected = 0; // which item in the menu is selected
int item_sel_previous; // previous item - used in the menu screen to draw the item before the selected one
int item_sel_next; // next item - used in the menu screen to draw next item after the selected one
int current_screen = 0; // 0 = menu, 1 = screenshot, 2 = qr
// encoder setup
#define CLK 2
#define DT 3
#define SW 4
int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir ="";
unsigned long lastButtonPress = 0;
void setup() {
u8g.setColorIndex(1); // set the color to white
// define pins for buttons
// INPUT_PULLUP means the button is HIGH when not pressed, and LOW when pressed
// since it´s connected between some pin and GND
pinMode(BUTTON_UP_PIN, INPUT_PULLUP); // up button
pinMode(BUTTON_SELECT_PIN, INPUT_PULLUP); // select button
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP); // down button
// Set encoder pins as inputs
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
pinMode(SW, INPUT_PULLUP);
// Setup Serial Monitor
Serial.begin(9600);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK);
}
void loop() {
//encoder moving
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT) != currentStateCLK) {
counter --;
currentDir ="CCW";
} else {
// Encoder is rotating CW so increment
counter ++;
currentDir ="CW";
}
Serial.print("Direction: ");
Serial.print(currentDir);
Serial.print(" | Counter: ");
Serial.println(counter);
}
// Remember last CLK state
lastStateCLK = currentStateCLK;
// Read the button state
int btnState = digitalRead(SW);
//If we detect LOW signal, button is pressed
if (btnState == LOW) {
//if 50ms have passed since last LOW pulse, it means that the
//button has been pressed, released and pressed again
if (millis() - lastButtonPress > 50) {
Serial.println("Button pressed!");
}
// Remember last button press event
lastButtonPress = millis();
}
// Put in a slight delay to help debounce the reading
delay(1);
// when pin 13 is LOW (DEMO_PIN), enable demo mode
// this could be done either by using a switch
// or simply by connecting the wire between pin 13 and GND
// (those pins are next to each other)
if (current_screen == 0) { // MENU SCREEN
// up and down buttons only work for the menu screen
if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0)) { // up button clicked - jump to previous menu item
item_selected = item_selected - 1; // select previous item
button_up_clicked = 1; // set button to clicked to only perform the action once
if (item_selected < 0) { // if first item was selected, jump to last item
item_selected = NUM_ITEMS-1;
}
}
else if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0)) { // down button clicked - jump to next menu item
item_selected = item_selected + 1; // select next item
button_down_clicked = 1; // set button to clicked to only perform the action once
if (item_selected >= NUM_ITEMS) { // last item was selected, jump to first menu item
item_selected = 0;
}
}
if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) { // unclick
button_up_clicked = 0;
}
if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) { // unclick
button_down_clicked = 0;
}
}
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0)) { // select button clicked, jump between screens
button_select_clicked = 1; // set button to clicked to only perform the action once
if (current_screen == 0) {current_screen = 1;} // menu items screen --> screenshots screen
else if (current_screen == 1) {current_screen = 2;} // screenshots screen --> qr codes screen
else {current_screen = 0;} // qr codes screen --> menu items screen
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) { // unclick
button_select_clicked = 0;
}
// set correct values for the previous and next items
item_sel_previous = item_selected - 1;
if (item_sel_previous < 0) {item_sel_previous = NUM_ITEMS - 1;} // previous item would be below first = make it the last
item_sel_next = item_selected + 1;
if (item_sel_next >= NUM_ITEMS) {item_sel_next = 0;} // next item would be after last = make it the first
u8g.firstPage(); // required for page drawing mode for u8g library
do {
if (current_screen == 0) { // MENU SCREEN
// selected item background
u8g.drawBitmapP(0, 0, 128/8, 16, bitmap_item_sel_outline);
// draw previous item as icon + label
u8g.setFont(u8g_font_6x13B);
u8g.drawStr(25, 12, menu_items[item_sel_previous]);
u8g.drawBitmapP( 6, 0, 16/8, 16, bitmap_icons[item_sel_previous]);
// draw selected item as icon + label in bold font
u8g.setFont(u8g_font_6x13);
u8g.drawStr(25, 12+16, menu_items[item_selected]);
u8g.drawBitmapP( 6, 16, 16/8, 16, bitmap_icons[item_selected]);
// draw next item as icon + label
u8g.setFont(u8g_font_7x14);
u8g.drawStr(25, 15+20+20+2+2, menu_items[item_sel_next]);
u8g.drawBitmapP( 4, 46, 16/8, 16, bitmap_icons[item_sel_next]);
// draw scrollbar background
u8g.drawBitmapP(128-8, 0, 8/8, 64, bitmap_scrollbar_background);
// draw scrollbar handle
u8g.drawBox(125, 64/NUM_ITEMS * item_selected, 3, 64/NUM_ITEMS);
// draw upir logo
u8g.drawBitmapP(128-16-4, 64-4, 16/8, 4, upir_logo);
}
} while ( u8g.nextPage() ); // required for page drawing mode with u8g library
}
And my question is why if I move the knob to right or even to left it's just typing me the moving CCW dirrection. Like on pic:
Pity you ignored that bit, it would have told you how to post code correctly.
I'm sorry, i'm getting better code below:
#include "U8glib.h"
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // Fast I2C / TWI
const unsigned char upir_logo [] PROGMEM = { // this is another way how to define images, using binary notation
B00010101, B11010111,
B00010101, B01000101,
B00010101, B10010110,
B00011001, B00010101
};
// 'icon_3dcube', 16x16px
const unsigned char bitmap_icon_liquid [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x20, 0x04, 0x20, 0x1c, 0x20, 0x04, 0x20, 0x3c, 0x20, 0x04,
0x20, 0x1c, 0x20, 0x04, 0x21, 0x24, 0x2a, 0xdc, 0x34, 0x04, 0x20, 0x04, 0x3f, 0xfc, 0x00, 0x00
};
// 'icon_battery', 16x16px
const unsigned char bitmap_icon_service [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x0b, 0xd0, 0x04, 0x20, 0x18, 0x18, 0x09, 0x90,
0x09, 0x90, 0x18, 0x18, 0x04, 0x20, 0x0b, 0xd0, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'icon_dashboard', 16x16px
const unsigned char bitmap_icon_work [] PROGMEM = {
0x00, 0x00, 0x02, 0x00, 0x72, 0xc6, 0x8a, 0xaa, 0x8a, 0x92, 0x8a, 0x82, 0xfa, 0x82, 0x8a, 0x82,
0x8a, 0x82, 0x8a, 0x82, 0x8a, 0x82, 0x8a, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 384)
const unsigned char* bitmap_icons[3] = {
bitmap_icon_liquid,
bitmap_icon_service,
bitmap_icon_work,
};
// 'scrollbar_background', 8x64px
const unsigned char bitmap_scrollbar_background [] PROGMEM = {
0x20, 0x70, 0x70, 0x70, 0x70, 0x70, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00
};
// 'item_sel_outline', 128x16px
const unsigned char bitmap_item_sel_outline [] PROGMEM = {
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// ------------------ end generated bitmaps from image2cpp ---------------------------------
const int NUM_ITEMS = 3; // number of items in the list and also the number of screenshots and screenshots with QR codes (other screens)
const int MAX_ITEM_LENGTH = 20; // maximum characters for the item name
char menu_items [NUM_ITEMS] [MAX_ITEM_LENGTH] = { // array with item names
{ "Liquid" },
{ "Service" },
{ "Work" },
};
// note - when changing the order of items above, make sure the other arrays referencing bitmaps
// also have the same order, for example array "bitmap_icons" for icons, and other arrays for screenshots and QR codes
#define BUTTON_UP_PIN 12 // pin for UP button
#define BUTTON_SELECT_PIN 8 // pin for SELECT button
#define BUTTON_DOWN_PIN 4 // pin for DOWN button
int button_up_clicked = 0; // only perform action when button is clicked, and wait until another press
int button_select_clicked = 0; // same as above
int button_down_clicked = 0; // same as above
int item_selected = 0; // which item in the menu is selected
int item_sel_previous; // previous item - used in the menu screen to draw the item before the selected one
int item_sel_next; // next item - used in the menu screen to draw next item after the selected one
int current_screen = 0; // 0 = menu, 1 = screenshot, 2 = qr
// encoder setup
#define CLK 2
#define DT 3
#define SW 4
int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir ="";
unsigned long lastButtonPress = 0;
void setup() {
u8g.setColorIndex(1); // set the color to white
// define pins for buttons
// INPUT_PULLUP means the button is HIGH when not pressed, and LOW when pressed
// since it´s connected between some pin and GND
pinMode(BUTTON_UP_PIN, INPUT_PULLUP); // up button
pinMode(BUTTON_SELECT_PIN, INPUT_PULLUP); // select button
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP); // down button
// Set encoder pins as inputs
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
pinMode(SW, INPUT_PULLUP);
// Setup Serial Monitor
Serial.begin(9600);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK);
}
void loop() {
//encoder moving
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT) != currentStateCLK) {
counter --;
currentDir ="CCW";
} else {
// Encoder is rotating CW so increment
counter ++;
currentDir ="CW";
}
Serial.print("Direction: ");
Serial.print(currentDir);
Serial.print(" | Counter: ");
Serial.println(counter);
}
// Remember last CLK state
lastStateCLK = currentStateCLK;
// Read the button state
int btnState = digitalRead(SW);
//If we detect LOW signal, button is pressed
if (btnState == LOW) {
//if 50ms have passed since last LOW pulse, it means that the
//button has been pressed, released and pressed again
if (millis() - lastButtonPress > 50) {
Serial.println("Button pressed!");
}
// Remember last button press event
lastButtonPress = millis();
}
// Put in a slight delay to help debounce the reading
delay(1);
// when pin 13 is LOW (DEMO_PIN), enable demo mode
// this could be done either by using a switch
// or simply by connecting the wire between pin 13 and GND
// (those pins are next to each other)
if (current_screen == 0) { // MENU SCREEN
// up and down buttons only work for the menu screen
if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0)) { // up button clicked - jump to previous menu item
item_selected = item_selected - 1; // select previous item
button_up_clicked = 1; // set button to clicked to only perform the action once
if (item_selected < 0) { // if first item was selected, jump to last item
item_selected = NUM_ITEMS-1;
}
}
else if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0)) { // down button clicked - jump to next menu item
item_selected = item_selected + 1; // select next item
button_down_clicked = 1; // set button to clicked to only perform the action once
if (item_selected >= NUM_ITEMS) { // last item was selected, jump to first menu item
item_selected = 0;
}
}
if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) { // unclick
button_up_clicked = 0;
}
if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) { // unclick
button_down_clicked = 0;
}
}
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0)) { // select button clicked, jump between screens
button_select_clicked = 1; // set button to clicked to only perform the action once
if (current_screen == 0) {current_screen = 1;} // menu items screen --> screenshots screen
else if (current_screen == 1) {current_screen = 2;} // screenshots screen --> qr codes screen
else {current_screen = 0;} // qr codes screen --> menu items screen
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) { // unclick
button_select_clicked = 0;
}
// set correct values for the previous and next items
item_sel_previous = item_selected - 1;
if (item_sel_previous < 0) {item_sel_previous = NUM_ITEMS - 1;} // previous item would be below first = make it the last
item_sel_next = item_selected + 1;
if (item_sel_next >= NUM_ITEMS) {item_sel_next = 0;} // next item would be after last = make it the first
u8g.firstPage(); // required for page drawing mode for u8g library
do {
if (current_screen == 0) { // MENU SCREEN
// selected item background
u8g.drawBitmapP(0, 0, 128/8, 16, bitmap_item_sel_outline);
// draw previous item as icon + label
u8g.setFont(u8g_font_6x13B);
u8g.drawStr(25, 12, menu_items[item_sel_previous]);
u8g.drawBitmapP( 6, 0, 16/8, 16, bitmap_icons[item_sel_previous]);
// draw selected item as icon + label in bold font
u8g.setFont(u8g_font_6x13);
u8g.drawStr(25, 12+16, menu_items[item_selected]);
u8g.drawBitmapP( 6, 16, 16/8, 16, bitmap_icons[item_selected]);
// draw next item as icon + label
u8g.setFont(u8g_font_7x14);
u8g.drawStr(25, 15+20+20+2+2, menu_items[item_sel_next]);
u8g.drawBitmapP( 4, 46, 16/8, 16, bitmap_icons[item_sel_next]);
// draw scrollbar background
u8g.drawBitmapP(128-8, 0, 8/8, 64, bitmap_scrollbar_background);
// draw scrollbar handle
u8g.drawBox(125, 64/NUM_ITEMS * item_selected, 3, 64/NUM_ITEMS);
// draw upir logo
u8g.drawBitmapP(128-16-4, 64-4, 16/8, 4, upir_logo);
}
} while ( u8g.nextPage() ); // required for page drawing mode with u8g library
}
Thanks that is the full picture.
The way I see it is that you are not reading the rotary encoder fast enough. Once you add extra stuff to your loop then it slows down the frequency you can read the rotary encoders.
The best bet is to use one of the rotary encoder libraries you can get. Unfortunately they are not all done in the "correct" way so you can still get problems.
However one that does read encoders correctly is this one:-
Encoder Library, for Measuring Quadarature Encoded Position or Rotation Signals
I would try this first and just read the count you get from it and see that it works first before you try and include it into your code. It uses interrupts so it still counts when ever the contacts of the encoder changes despite what the other code is doing.
Look at the examples that come with the library, to do things like reset the count.
Please edit your post #3 to add tags </> because is hard to understand what's code and what is explanation.
The encoder response is not fast enough because you are not using interrupt.
Try this:
#include <Arduino.h>
#include "U8glib.h"
#include <Rotary.h> // https://github.com/brianlow/Rotary/archive/refs/heads/master.zip
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // Fast I2C / TWI
const unsigned char upir_logo [] PROGMEM = { // this is another way how to define images, using binary notation
B00010101, B11010111,
B00010101, B01000101,
B00010101, B10010110,
B00011001, B00010101
};
// 'icon_3dcube', 16x16px
const unsigned char bitmap_icon_liquid [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x20, 0x04, 0x20, 0x1c, 0x20, 0x04, 0x20, 0x3c, 0x20, 0x04,
0x20, 0x1c, 0x20, 0x04, 0x21, 0x24, 0x2a, 0xdc, 0x34, 0x04, 0x20, 0x04, 0x3f, 0xfc, 0x00, 0x00
};
// 'icon_battery', 16x16px
const unsigned char bitmap_icon_service [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x0b, 0xd0, 0x04, 0x20, 0x18, 0x18, 0x09, 0x90,
0x09, 0x90, 0x18, 0x18, 0x04, 0x20, 0x0b, 0xd0, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'icon_dashboard', 16x16px
const unsigned char bitmap_icon_work [] PROGMEM = {
0x00, 0x00, 0x02, 0x00, 0x72, 0xc6, 0x8a, 0xaa, 0x8a, 0x92, 0x8a, 0x82, 0xfa, 0x82, 0x8a, 0x82,
0x8a, 0x82, 0x8a, 0x82, 0x8a, 0x82, 0x8a, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 384)
const unsigned char* bitmap_icons[3] = {
bitmap_icon_liquid,
bitmap_icon_service,
bitmap_icon_work,
};
// 'scrollbar_background', 8x64px
const unsigned char bitmap_scrollbar_background [] PROGMEM = {
0x20, 0x70, 0x70, 0x70, 0x70, 0x70, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00
};
// 'item_sel_outline', 128x16px
const unsigned char bitmap_item_sel_outline [] PROGMEM = {
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// ------------------ end generated bitmaps from image2cpp ---------------------------------
const int NUM_ITEMS = 3; // number of items in the list and also the number of screenshots and screenshots with QR codes (other screens)
const int MAX_ITEM_LENGTH = 20; // maximum characters for the item name
char menu_items[NUM_ITEMS] [MAX_ITEM_LENGTH] = { // array with item names
{ "Liquid" },
{ "Service" },
{ "Work" },
};
// note - when changing the order of items above, make sure the other arrays referencing bitmaps
// also have the same order, for example array "bitmap_icons" for icons, and other arrays for screenshots and QR codes
#define BUTTON_UP_PIN 12 // pin for UP button
#define BUTTON_SELECT_PIN 8 // pin for SELECT button
#define BUTTON_DOWN_PIN 4 // pin for DOWN button
int button_up_clicked = 0; // only perform action when button is clicked, and wait until another press
int button_select_clicked = 0; // same as above
int button_down_clicked = 0; // same as above
int item_selected = 0; // which item in the menu is selected
int item_sel_previous; // previous item - used in the menu screen to draw the item before the selected one
int item_sel_next; // next item - used in the menu screen to draw next item after the selected one
int current_screen = 0; // 0 = menu, 1 = screenshot, 2 = qr
// encoder setup
#define CLK 2
#define DT 3
#define SW 4
int counter = 0;
unsigned long lastButtonPress = 0;
Rotary r = Rotary(DT, CLK);
void encoderA() // DT
{
unsigned char result = r.process();
if (result == DIR_CCW)
{
counter--;
Serial.print("Direction: CCW");
Serial.print(" | Counter: ");
Serial.println(counter);
}
}
void encoderB() // CLK
{
unsigned char result = r.process();
if (result == DIR_CW)
{
counter++;
Serial.print("Direction: CW");
Serial.print(" | Counter: ");
Serial.println(counter);
}
}
void setup()
{
u8g.setColorIndex(1); // set the color to white
// define pins for buttons
// INPUT_PULLUP means the button is HIGH when not pressed, and LOW when pressed
// since it´s connected between some pin and GND
pinMode(BUTTON_UP_PIN, INPUT_PULLUP); // up button
pinMode(BUTTON_SELECT_PIN, INPUT_PULLUP); // select button
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP); // down button
// Set encoder pins as inputs
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
pinMode(SW, INPUT_PULLUP);
// Setup Serial Monitor
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(DT), encoderA, CHANGE);
attachInterrupt(digitalPinToInterrupt(CLK), encoderB, CHANGE);
}
void loop()
{
// Read the button state
int btnState = digitalRead(SW);
// If we detect LOW signal, button is pressed
if (btnState == LOW)
{
// if 50ms have passed since last LOW pulse, it means that the
// button has been pressed, released and pressed again
if (millis() - lastButtonPress > 50)
{
Serial.println("Button pressed!");
}
// Remember last button press event
lastButtonPress = millis();
}
// Put in a slight delay to help debounce the reading
delay(1);
// when pin 13 is LOW (DEMO_PIN), enable demo mode
// this could be done either by using a switch
// or simply by connecting the wire between pin 13 and GND
// (those pins are next to each other)
if (current_screen == 0) // MENU SCREEN
// up and down buttons only work for the menu screen
{
if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0)) // up button clicked - jump to previous menu item
{
item_selected = item_selected - 1; // select previous item
button_up_clicked = 1; // set button to clicked to only perform the action once
if (item_selected < 0) // if first item was selected, jump to last item
{
item_selected = NUM_ITEMS - 1;
}
}
else if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0)) // down button clicked - jump to next menu item
{
item_selected = item_selected + 1; // select next item
button_down_clicked = 1; // set button to clicked to only perform the action once
if (item_selected >= NUM_ITEMS) // last item was selected, jump to first menu item
{
item_selected = 0;
}
}
if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) // unclick
{
button_up_clicked = 0;
}
if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) // unclick
{
button_down_clicked = 0;
}
}
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0)) // select button clicked, jump between screens
{
button_select_clicked = 1; // set button to clicked to only perform the action once
if (current_screen == 0)
{
current_screen = 1;
} // menu items screen --> screenshots screen
else if (current_screen == 1)
{
current_screen = 2;
} // screenshots screen --> qr codes screen
else
{
current_screen = 0;
} // qr codes screen --> menu items screen
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) // unclick
{
button_select_clicked = 0;
}
// set correct values for the previous and next items
item_sel_previous = item_selected - 1;
if (item_sel_previous < 0)
{
item_sel_previous = NUM_ITEMS - 1;
} // previous item would be below first = make it the last
item_sel_next = item_selected + 1;
if (item_sel_next >= NUM_ITEMS)
{
item_sel_next = 0;
} // next item would be after last = make it the first
u8g.firstPage(); // required for page drawing mode for u8g library
do
{
if (current_screen == 0) // MENU SCREEN
// selected item background
{
u8g.drawBitmapP(0, 0, 128 / 8, 16, bitmap_item_sel_outline);
// draw previous item as icon + label
u8g.setFont(u8g_font_6x13B);
u8g.drawStr(25, 12, menu_items[item_sel_previous]);
u8g.drawBitmapP( 6, 0, 16 / 8, 16, bitmap_icons[item_sel_previous]);
// draw selected item as icon + label in bold font
u8g.setFont(u8g_font_6x13);
u8g.drawStr(25, 12 + 16, menu_items[item_selected]);
u8g.drawBitmapP( 6, 16, 16 / 8, 16, bitmap_icons[item_selected]);
// draw next item as icon + label
u8g.setFont(u8g_font_7x14);
u8g.drawStr(25, 15 + 20 + 20 + 2 + 2, menu_items[item_sel_next]);
u8g.drawBitmapP( 4, 46, 16 / 8, 16, bitmap_icons[item_sel_next]);
// draw scrollbar background
u8g.drawBitmapP(128 - 8, 0, 8 / 8, 64, bitmap_scrollbar_background);
// draw scrollbar handle
u8g.drawBox(125, 64 / NUM_ITEMS * item_selected, 3, 64 / NUM_ITEMS);
// draw upir logo
u8g.drawBitmapP(128 - 16 - 4, 64 - 4, 16 / 8, 4, upir_logo);
}
} while ( u8g.nextPage() ); // required for page drawing mode with u8g library
}
Hi, today I used this library. Code below:
#include "U8glib.h"
#include <Encoder.h>
Encoder myEnc(3, 2);
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // Fast I2C / TWI
const unsigned char upir_logo [] PROGMEM = { // this is another way how to define images, using binary notation
B00010101, B11010111,
B00010101, B01000101,
B00010101, B10010110,
B00011001, B00010101
};
// 'icon_3dcube', 16x16px
const unsigned char bitmap_icon_liquid [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x20, 0x04, 0x20, 0x1c, 0x20, 0x04, 0x20, 0x3c, 0x20, 0x04,
0x20, 0x1c, 0x20, 0x04, 0x21, 0x24, 0x2a, 0xdc, 0x34, 0x04, 0x20, 0x04, 0x3f, 0xfc, 0x00, 0x00
};
// 'icon_battery', 16x16px
const unsigned char bitmap_icon_service [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x0b, 0xd0, 0x04, 0x20, 0x18, 0x18, 0x09, 0x90,
0x09, 0x90, 0x18, 0x18, 0x04, 0x20, 0x0b, 0xd0, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'icon_dashboard', 16x16px
const unsigned char bitmap_icon_work [] PROGMEM = {
0x00, 0x00, 0x02, 0x00, 0x72, 0xc6, 0x8a, 0xaa, 0x8a, 0x92, 0x8a, 0x82, 0xfa, 0x82, 0x8a, 0x82,
0x8a, 0x82, 0x8a, 0x82, 0x8a, 0x82, 0x8a, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 384)
const unsigned char* bitmap_icons[3] = {
bitmap_icon_liquid,
bitmap_icon_service,
bitmap_icon_work,
};
// 'scrollbar_background', 8x64px
const unsigned char bitmap_scrollbar_background [] PROGMEM = {
0x20, 0x70, 0x70, 0x70, 0x70, 0x70, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00
};
// 'item_sel_outline', 128x16px
const unsigned char bitmap_item_sel_outline [] PROGMEM = {
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// ------------------ end generated bitmaps from image2cpp ---------------------------------
const int NUM_ITEMS = 3; // number of items in the list and also the number of screenshots and screenshots with QR codes (other screens)
const int MAX_ITEM_LENGTH = 20; // maximum characters for the item name
char menu_items [NUM_ITEMS] [MAX_ITEM_LENGTH] = { // array with item names
{ "Liquid" },
{ "Service" },
{ "Work" },
};
// note - when changing the order of items above, make sure the other arrays referencing bitmaps
// also have the same order, for example array "bitmap_icons" for icons, and other arrays for screenshots and QR codes
#define BUTTON_UP_PIN 12 // pin for UP button
#define BUTTON_SELECT_PIN 8 // pin for SELECT button
#define BUTTON_DOWN_PIN 4 // pin for DOWN button
int button_up_clicked = 0; // only perform action when button is clicked, and wait until another press
int button_select_clicked = 0; // same as above
int button_down_clicked = 0; // same as above
int item_selected = 0; // which item in the menu is selected
int item_sel_previous; // previous item - used in the menu screen to draw the item before the selected one
int item_sel_next; // next item - used in the menu screen to draw next item after the selected one
int current_screen = 0; // 0 = menu, 1 = screenshot, 2 = qr
void setup() {
u8g.setColorIndex(1); // set the color to white
// define pins for buttons
// INPUT_PULLUP means the button is HIGH when not pressed, and LOW when pressed
// since it´s connected between some pin and GND
pinMode(BUTTON_UP_PIN, INPUT_PULLUP); // up button
pinMode(BUTTON_SELECT_PIN, INPUT_PULLUP); // select button
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP); // down button
// Set encoder pins as inputs
Serial.begin(9600);
}
boolean a = false;
boolean b = false;
long oldPosition = -999;
void loop() {
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
if(newPosition % 4==0){
if(newPosition>oldPosition){
Serial.println("right");
a = true;
}
else
{
Serial.println("left");
b=true;
}
}
oldPosition = newPosition;
}
if (current_screen == 0) { // MENU SCREEN
// up and down buttons only work for the menu screen
if (a=true) { // up button clicked - jump to previous menu item
item_selected = item_selected - 1; // select previous item
button_up_clicked = 1; // set button to clicked to only perform the action once
if (item_selected < 0) { // if first item was selected, jump to last item
item_selected = NUM_ITEMS-1;
}
a=false;
}
else if (b=true) { // down button clicked - jump to next menu item
item_selected = item_selected + 1; // select next item
button_down_clicked = 1; // set button to clicked to only perform the action once
if (item_selected >= NUM_ITEMS) { // last item was selected, jump to first menu item
item_selected = 0;
}
b=false;
}
}
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0)) { // select button clicked, jump between screens
button_select_clicked = 1; // set button to clicked to only perform the action once
if (current_screen == 0) {current_screen = 1;} // menu items screen --> screenshots screen
else if (current_screen == 1) {current_screen = 2;} // screenshots screen --> qr codes screen
else {current_screen = 0;} // qr codes screen --> menu items screen
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) { // unclick
button_select_clicked = 0;
}
// set correct values for the previous and next items
item_sel_previous = item_selected - 1;
if (item_sel_previous < 0) {item_sel_previous = NUM_ITEMS - 1;} // previous item would be below first = make it the last
item_sel_next = item_selected + 1;
if (item_sel_next >= NUM_ITEMS) {item_sel_next = 0;} // next item would be after last = make it the first
u8g.firstPage(); // required for page drawing mode for u8g library
do {
if (current_screen == 0) { // MENU SCREEN
// selected item background
u8g.drawBitmapP(0, 0, 128/8, 16, bitmap_item_sel_outline);
// draw previous item as icon + label
u8g.setFont(u8g_font_6x13B);
u8g.drawStr(25, 12, menu_items[item_sel_previous]);
u8g.drawBitmapP( 6, 0, 16/8, 16, bitmap_icons[item_sel_previous]);
// draw selected item as icon + label in bold font
u8g.setFont(u8g_font_6x13);
u8g.drawStr(25, 12+16, menu_items[item_selected]);
u8g.drawBitmapP( 6, 16, 16/8, 16, bitmap_icons[item_selected]);
// draw next item as icon + label
u8g.setFont(u8g_font_7x14);
u8g.drawStr(25, 15+20+20+2+2, menu_items[item_sel_next]);
u8g.drawBitmapP( 4, 46, 16/8, 16, bitmap_icons[item_sel_next]);
// draw scrollbar background
u8g.drawBitmapP(128-8, 0, 8/8, 64, bitmap_scrollbar_background);
// draw scrollbar handle
u8g.drawBox(125, 64/NUM_ITEMS * item_selected, 3, 64/NUM_ITEMS);
// draw upir logo
u8g.drawBitmapP(128-16-4, 64-4, 16/8, 4, upir_logo);
}
} while ( u8g.nextPage() ); // required for page drawing mode with u8g library
}
And link to project wokwi : Menu Oled Rotary - Wokwi Arduino and ESP32 Simulator
I make sollution to make encdoer left and right by this library but i still have problem because the menu is jumping over and over i don't know why. Please help
I used this code but it's not working. If i switch encoder on monitor is nothing changed. I installed library which you paste on code.
Try
if((newPosition & 3)==0){
However, before you try and get it to do things at the menu, just get it to print the right values.
However I think your code is a bit ill thought out. What exactly do you want to do on the display when you turn the encoder?
Are you just interested in the direction of the turn rather than how far you have turned it?
Do you want it to cycle through the menus with one click moving onto the next menu and then after four menus going back to display the first one again?
One good way of getting a handle on what you need is to draw it out as a diagram.
I recently did something rather similar but I was working in Python so the code is not directly applicable to you. It was for setting up parameters in a MIDI sequencer.
Basically I had an extendable list of menus, each menu had five items. The logic I used was that a push on the button would change the active line on the menu as displayed by an arrow next to the line. Any rotation of the encoder would cause an action changing a variable for that line. When a menu screen was first entered it was always on line 4, being displayed at the top of the screen and was the menu change option. So a rotation would always take you to the next menu, when you reached the end of the menus it would wrap round and show the first menu again.
If on any menu you pushed the encoder button it would go to line 0, and a rotation would then alter that parameter in either a wrap round way or a move to a limit and then go no further, but would move back from there if you turned in the reverse direction.
This was my state diagram for one menu screen.
A state diagram is a sequence of states shown in boxes and the transition from one state to the next is shown by an action and where that action leads, hence the basic series of pushes showing it going from one line to the next. But note the rotation also does stuff as well. Look up a state diagram it is a real thing and will show you more about how they are constructed.
What you can get with this code?
#include <Rotary.h>
Rotary r = Rotary(2, 3);
int counter = 0;
void encoderA() // DT
{
unsigned char result = r.process();
if (result == DIR_CCW)
{
counter--;
Serial.print("Direction: CCW");
Serial.print(" | Counter: ");
Serial.println(counter);
}
}
void encoderB() // CLK
{
unsigned char result = r.process();
if (result == DIR_CW)
{
counter++;
Serial.print("Direction: CW");
Serial.print(" | Counter: ");
Serial.println(counter);
}
}
void setup()
{
Serial.begin(9600);
pinMode(2,INPUT);
pinMode(3,INPUT);
r.begin();
attachInterrupt(digitalPinToInterrupt(2), encoderA, CHANGE);
attachInterrupt(digitalPinToInterrupt(3), encoderB, CHANGE);
}
void loop()
{
}
I used mod 4 to just take information is is right or left.
To make more understandabl i will show want i want to make:
Rotate encoder to move on menu. Items of menu will jumping from 1 to 3. If i press the encoder i will go to option of item selected. On example shows 2 options 1 Liquid and 2 Liquid. If i press Liquid 1 i will go to change variable measurment of pumping liquid. If i click i can rotate to change this variable, then click to apply. Every back change screen menu -1.
Nothing shows on serial port monitor when i rotate the encoder. On Arduino IDE it shows that the program is loaded. The pins are also properly initialized according to Pin 2 and Pin 3.
Try the example directly from Rotary library.
Are you using Arduino uno?
Not a great one for using simulators, when I try and run this I get an error
sketch.ino:2:10: fatal error: Encoder.h: No such file or directory
#include <Encoder.h>
When the menu jumps about, is it doing this when you turn the knob or does it jump without you turning the knob?
If it does then it implies it is not wired up correctly, that is something on your bread board is not making proper contact and so you have a floating input.
Is this a simulated result or is it real? You will be better off doing this for real because simulators do not always simulate external components correctly.
If it is real then try adding a 0,1uF ceramic capacitor from pins 2 & 3 to ground.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.