Currently i'm using the library 'LCDMenuLib' with an example to create a menu structure from this library.
This library also has some built in support for controlling of the menus with a rotary encoder, however i'm not getting it to work.
I've been looking around the whole example and its subfiles but can't seem to find a way to enable the rotary encoder to work.
I've tried several setups/wirings, but unfortunately haven't been able to get the rot. encoder to work yet, currently it doesn't react to the encoder at all.
I've checked the rotary encoder from errors by using some simple sketches to prove functionality of the rotary encoder, which is OK.
I've put the code in the attachment.
Can anyone tell me how to get the rotary encoder working? (And double-check me on how to wire the encoder?)
I am reluctant to download and open a zip file. Please post the code in code tags. If the code is too large, attach the ino file. You can post images like this.
Please read the "how to use this forum-please read" stickies.
groundFungus:
I am reluctant to download and open a zip file. Please post the code in code tags. If the code is too large, attach the ino file. You can post images like this.
Please read the "how to use this forum-please read" stickies.
Thanks for your reply, I've now attached the .ino files separately instead of in a .zip file.
to enable the rotary encoder open the "LCDML_CONTROL.ino and change _LCDML_CONTROL_cfg from 0 to 3
Then scroll down until you find a comment like this:
// *********************************************************************
// *************** (3) CONTROL WITH ENCODER ****************************
// *********************************************************************
Here you can define your "pins" where you can connect the encoder. I use the encoder with low active logic and internal pullups. (Common Pin on GND and Pin A and B directly to the arduino, one pin from the switch to gnd and the other directly to the arduino)
Great! The setting of 0 to 3 did the job! That was the one i was looking for!
Now another question, i'd like to implement the function of the 'back-button' when the knob is pressed >= X ms.
Unfortunately, also this won't work yet..
This is the rotary encoder-part of the code in which i'd like to implement the 'go_back-on-hold' function.
Going back can be achieved by running this line:
LCDML_BUTTON_quit();
Only thing to be added to the code underneath is to notice when the button is pressed for more than X milliseconds, and then run the 'LCDML_BUTTON_quit();' line.
Any ideas on how to implement this? (Preferably without delays)
Thanks in advance!
// *********************************************************************
// *************** (3) CONTROL WITH ENCODER ****************************
// *********************************************************************
#elif(_LCDML_CONTROL_cfg == 3)
// settings
#define _LCDML_CONTROL_encoder_pin_a 10 // pin encoder b
#define _LCDML_CONTROL_encoder_pin_b 11 // pin encoder a
#define _LCDML_CONTROL_encoder_pin_button 12 // pin taster
#define _LCDML_CONTROL_encoder_high_active 0 // (0 = low active (pullup), 1 = high active (pulldown)) button
// // http://playground.arduino.cc/CommonTopics/PullUpDownResistor
// global defines
uint8_t g_LCDML_CONTROL_encoder_t_prev = 0;
uint8_t g_LCDML_CONTROL_encoder_a_prev = 0;
// *********************************************************************
// setup
void LCDML_CONTROL_setup()
{
// set encoder update intervall time
LCDML_BACK_dynamic_setLoopTime(LCDML_BACKEND_control, 5UL); // 5ms
// init pins
pinMode(_LCDML_CONTROL_encoder_pin_a , INPUT_PULLUP);
pinMode(_LCDML_CONTROL_encoder_pin_b , INPUT_PULLUP);
pinMode(_LCDML_CONTROL_encoder_pin_button , INPUT_PULLUP);
}
// *********************************************************************
// loop
void LCDML_CONTROL_loop()
{
// read encoder status
unsigned char a = digitalRead(_LCDML_CONTROL_encoder_pin_a);
unsigned char b = digitalRead(_LCDML_CONTROL_encoder_pin_b);
unsigned char t = digitalRead(_LCDML_CONTROL_encoder_pin_button);
// change button status if high and low active are switched
if (_LCDML_CONTROL_encoder_high_active == 1) {
t != t;
}
// check encoder status and set control menu
if (!a && g_LCDML_CONTROL_encoder_a_prev) {
g_LCDML_CONTROL_encoder_t_prev = 1;
if (!b) { LCDML_BUTTON_up(); }
else { LCDML_BUTTON_down(); }
}
else {
// check button press time for enter
if((millis() - g_LCDML_DISP_press_time) >= _LCDML_DISP_cfg_button_press_time) {
g_LCDML_DISP_press_time = millis(); // reset button press time
// press button once
if (!t && g_LCDML_CONTROL_encoder_t_prev == 0) {
LCDML_BUTTON_enter();
}
else {
g_LCDML_CONTROL_encoder_t_prev = 0;
}
}
}
g_LCDML_CONTROL_encoder_a_prev = a; // set new encoder status
}
// *********************************************************************
// ******************************* END *********************************
// *********************************************************************
...
...
#elif(_LCDML_CONTROL_cfg == 3)
// settings
#define _LCDML_CONTROL_encoder_pin_a A0 // pin encoder b
#define _LCDML_CONTROL_encoder_pin_b A1 // pin encoder a
#define _LCDML_CONTROL_encoder_pin_button 8 // pin taster
#define _LCDML_CONTROL_encoder_high_active 1 // (0 = low active (pullup), 1 = high active (pulldown)) button
// // http://playground.arduino.cc/CommonTopics/PullUpDownResistor
// global defines
uint8_t g_LCDML_CONTROL_encoder_t_prev = 0;
uint8_t g_LCDML_CONTROL_encoder_a_prev = 0;
uint8_t g_LCDML_CONTROL_reminder_button_press = 0; // <-- NEW
uint8_t g_LCDML_CONTROL_reminder_wait_time = 0; // <-- NEW
Change something in the loop function for rotary encoder
void LCDML_CONTROL_loop()
{
// read encoder status
unsigned char a = digitalRead(_LCDML_CONTROL_encoder_pin_a);
unsigned char b = digitalRead(_LCDML_CONTROL_encoder_pin_b);
unsigned char t = digitalRead(_LCDML_CONTROL_encoder_pin_button);
// change button status if high and low active are switched
if (_LCDML_CONTROL_encoder_high_active == 1) {
t != t;
}
// check encoder status and set control menu
if (!a && g_LCDML_CONTROL_encoder_a_prev) {
g_LCDML_CONTROL_encoder_t_prev = 1;
if (!b) { LCDML_BUTTON_up(); }
else { LCDML_BUTTON_down(); }
}
else {
// check if button is pressed
if(!t)
{
// button is pressed
if(g_LCDML_CONTROL_reminder_wait_time < 255) { // check overrun (uint8_t)
g_LCDML_CONTROL_reminder_wait_time++; // currently increments every 5 ms with the loop time
}
}
else
{
// button is not pressed
if(g_LCDML_CONTROL_reminder_button_press == 1)
{
// check waittime for quit >= 300 ms
if((g_LCDML_CONTROL_reminder_wait_time * LCDBL_BACK_dynamic_getLoopTime(LCDML_BACKEND_control)) >= 300)
{
// call quit
Serial.println("call quit");
LCDML_BUTTON_quit();
}
else
{
// call enter
Serial.println("call enter");
LCDML_BUTTON_enter();
}
g_LCDML_CONTROL_reminder_wait_time = 0;
g_LCDML_CONTROL_reminder_button_press = 0;
}
}
// check button press time for enter
if((millis() - g_LCDML_DISP_press_time) >= _LCDML_DISP_cfg_button_press_time) {
g_LCDML_DISP_press_time = millis(); // reset button press time
// press button once
if (!t && g_LCDML_CONTROL_encoder_t_prev == 0)
{
// button was pressed, but how long ?
g_LCDML_CONTROL_reminder_button_press = 1;
}
else {
g_LCDML_CONTROL_encoder_t_prev = 0;
}
}
}
g_LCDML_CONTROL_encoder_a_prev = a; // set new encoder status
}
To add back buttons it is easy to create a menuitem with "Back" and use only the "enter" function on this.
You can add in the main setup this line to enable menu rollover to jump fast from the last element to the first element.
LCDML.enRollover(); // add this after the group initialisation
// check button press time for enter
if((millis() - g_LCDML_DISP_press_time) >= _LCDML_DISP_cfg_button_press_time) {
g_LCDML_DISP_press_time = millis(); // reset button press time
// press button once
if (!t && g_LCDML_CONTROL_encoder_t_prev == 0)
{
// button was pressed, but how long ?
g_LCDML_CONTROL_reminder_button_press = 1;
}
else {
g_LCDML_CONTROL_encoder_t_prev = 0;
}
}
}
g_LCDML_CONTROL_encoder_a_prev = a; // set new encoder status
}
To add back buttons it is easy to create a menuitem with "Back" and use only the "enter" function on this.
You can add in the main setup this line to enable menu rollover to jump fast from the last element to the first element.
LCDML.enRollover(); // add this after the group initialisation
Thanks for your reply!
Using this code gives an error:
LCDML_BACKEND_control' was not declared in this scope
I've already checked the spelling of 'LCDML_BACKEND_control' and it's the same as used in other places in the (already existing and working) code. To make sure the spelling is exactly the same i've also copied the text, but unfortunately it's still 'not declared in this scope'.
Any ideas on how to fix this error? I can't seem to find/understand the cause of it.
Well, with the code from johononline i've received so many errors, solved many of them but they keep coming, that's why i'd prefer using the code supplied by you (Jomelo).
In addition i've got another question on how to change a variable when in a submenu?
For instance when i click/open the Brightness menu, i've now made a menu which shows the current Brightness value, but i'd also like to be able to adjust it by rotating the rotary encoder when this submenu is active.
The information is currently displayed by:
void LCDML_DISP_loop(BrightnessSet)
{
// loop
// is called when it is triggert
// - with LCDML_DISP_triggerMenu( millisecounds )
// - with every button status change
u8g.firstPage();
do {
u8g.setFont(_LCDML_DISP_font);
u8g.drawStr(15, 20, "Brightness: ");
u8g.setFont(_LCDML_DISP_fontLarge1);
//u8g.drawStr(8, 30, "Eeee");
char buf[9];
sprintf (buf, "%d", BRIGHTNESS);
u8g.drawStr(25, 55, buf);
} while( u8g.nextPage() );
delay(200);
// check if any button is presed (enter, up, down, left, right)
if(LCDML_BUTTON_checkAny()) {
LCDML_DISP_funcend();
}
}