Rotary encoder example #56
-
I'm wanting to incorporate LiquidMenu into a project that I'm working on. The only input will be a rotary encoder & button. I'm using the EasyButton library which will do the denounce, plus allow for a short-press & long-press (essentially, 2 buttons in 1). The idea is to use the encoder for selecting the menu line, or sub-menus, using LiquidSystem. The encoder would also be used to increase or decrease the value of a setting. The "enter" (short-press) button would be used to select the menu line & to make the change active. The "back" (long-press) button would return the main "running" menu screen. I'm just not sure how to implement this into LiquidMenu. Edit: I don't HAVE to use a long-press for the return. I can idea new menu line to trigger that. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
I use something like this: void onEncoderEvent() {
if (_encoder->rotation == _encoder->ROTARY_CCW) {
Serial.println("< CCW");
menu.switch_focus(false);
} else {
Serial.println("> CW");
menu.switch_focus(true);
}
menu.update();
} |
Beta Was this translation helpful? Give feedback.
-
Hi, @malaki86. Sorry for the delay. Since you want to use the encoder's inputs for 3 different actions, you need to have a variable holding the current state of the encoder (the action it is doing currently). And you can use the buttons (short-press and long-press) to manipulate the encoder's state. enum EncoderState : uint8_t {
ENC_ST_SCREEN = 0, // in this state the encoder cycles the screens
ENC_ST_LINE = 1, // in this state it cycles the focus through the lines
ENC_ST_SETTING = 2, // in this state it "increases or decreases" the value of a setting
ENC_ST_OUT_OF_BOUNDS, // this is automatically set to 3
};
EncoderState encoderState = ENC_ST_SCREEN; // global variable holding the encoder's state
void onEncoderEvent() {
// check in which state the encoder is currently in
switch (encoderState) {
case ENC_ST_SCREEN: // cycling screens
if (_encoder->rotation == _encoder->ROTARY_CCW) {
menu.previous_screen();
} else { // CW
menu.next_screen();
}
break;
case ENC_ST_LINE: // cycling focus through the lines
if (_encoder->rotation == _encoder->ROTARY_CCW) {
menu.switch_focus(false);
} else {
menu.switch_focus(true);
}
break;
case ENC_ST_SETTING: // changing a setting
if (_encoder->rotation == _encoder->ROTARY_CCW) {
menu.call_function(2);
} else {
menu.call_function(1);
}
break;
default: // invalid state
encoderState = 0; // return to a valid state
break;
}
menu.update();
}
// example of short-press handler
void onShortPress() {
if (encoderState + 1 < ENC_ST_OUT_OF_BOUNDS) { // check if the next state is valid
encoderState = (EncoderState)(encoderState + 1); // increment to the next state (ENC_ST_SCREEN -> ENC_ST_LINE -> ENC_ST_SETTING)
} else {
encoderState = 0; // in case of short-press while changing a setting - wrap around to state ENC_ST_SCREEN for convenience
}
}
void onLongPress() {
if (encoderState > 0) {
(EncoderState)(encoderState - 1); // go back to a previous state (ENC_ST_SETTING -> ENC_ST_LINE -> ENC_ST_SCREEN)
}
}
...
void setup() {
...
} Hope this helps. |
Beta Was this translation helpful? Give feedback.
Hi, @malaki86. Sorry for the delay.
Since you want to use the encoder's inputs for 3 different actions, you need to have a variable holding the current state of the encoder (the action it is doing currently). And you can use the buttons (short-press and long-press) to manipulate the encoder's state.