Go Down

Topic: LCD menus with rotary encoder troubles. Using m2tklib (Read 481 times) previous topic - next topic

Bob808

Hello.
I am trying to make an interactive menu using a rotary encoder on a 20x4 LCD. I tried to use m2tklib but failed :)
So basically I want to create a simple menu with submenu Set Time (into a variable that I'll manage later in the code) and submenu Set Alarm (also a variable that I'll store later on eeprom).
Also I want to use two separate buttons for Enter/Back. The encoder will be used as Left/Right and scrolling thru values.
I'm using an Arduino Uno. I attached the hardware setup of the encoder.
Right now I have the Left/Right pins of the encoder connected on A0/A1 and Enter/Back buttons on A2/A3.
I managed to get this code working:
Code: [Select]
#include <Wire.h>
#include <LiquidCrystal.h>
#include "M2tk.h"
#include "utility/m2ghlc.h"
LiquidCrystal lcd(12, 14, 11, 5, 4, 3, 2);
M2_EXTERN_ALIGN(top_menu);
uint8_t n1 = 0;
uint8_t n2 = 0;
M2_LABEL(el_l1, NULL, "value 1:");
M2_U8NUM(el_u1, "c2", 0, 99, &n1);
M2_LABEL(el_l2, NULL, "value 2:");
M2_U8NUM(el_u2, "c2", 0, 99, &n2);
M2_LIST(list) = { &el_l1, &el_u1, &el_l2, &el_u2 };
M2_GRIDLIST(el_gridlist, "c2", list);
M2_ALIGN(top_menu, "-1|1W64H64", &el_gridlist);
M2tk m2(&top_menu, m2_es_arduino_rotary_encoder, m2_eh_4bd, m2_gh_lc);

void setup() {
  m2_SetLiquidCrystal(&lcd, 20, 4);
  m2.setPin(M2_KEY_SELECT, A3);
  m2.setPin(M2_KEY_ROT_ENC_A, A0);
  m2.setPin(M2_KEY_ROT_ENC_B, A1);
}

void loop() {
  m2.checkKey();
  m2.checkKey();
  if ( m2.handleKey() )
    m2.draw();
  m2.checkKey();
}


But I'd like to know how to add a Back button, create submenus with proper values for time (that's all that I'm going to deal with, time, 0-23 for hours and 0-59 for minutes). And store those values into variables.

olikraus

#1
Sep 14, 2014, 01:17 pm Last Edit: Sep 14, 2014, 01:21 pm by olikraus Reason: 1
Hi

Let me start with the buttons: M2tklib assumes that the pushed button connects the ground, because there is an internal pull-up resistor, which is also activated. This means, your external resistor is not required (if the button connects to GND). Additionally, m2tklib includes a debounce algorithm. So also the cap is not required.

The encoder seems to be connected correctly. Also the software setup seems to be fine (but i can not verify this).

I think the first step should be to setup your input devices correctly and make the examples work.

Additionally here is some code from my projects with a time input dialog box:

Code: [Select]
/* edit time dialog */

uint8_t td_hour;
uint8_t td_min;
uint8_t td_sec;

void td_get_from_RTC(void)
{
  RTC.getTime();
  td_hour = RTC.hour;
  td_min = RTC.minute;
  td_sec = RTC.second;
}

void td_put_to_RTC(void)
{
  RTC.getTime();
  RTC.fillByHMS(td_hour, td_min, td_sec);
  RTC.setTime();
  RTC.startClock(); 
}

void td_ok_fn(m2_el_fnarg_p fnarg)
{
  td_put_to_RTC();
  m2.setRoot(&el_top);
}

M2_U8NUM(el_td_hour, "c2", 0,23,&td_hour);
M2_LABEL(el_td_sep1, NULL, ":");
M2_U8NUM(el_td_min, "c2", 0,59,&td_min);
M2_LABEL(el_td_sep2, NULL, ":");
M2_U8NUM(el_td_sec, "c2", 0,59,&td_sec);

M2_LIST(list_time) = { &el_td_hour, &el_td_sep1, &el_td_min, &el_td_sep2, &el_td_sec };
M2_HLIST(el_time, NULL, list_time);

M2_ROOT(el_td_cancel, NULL, "cancel", &el_top);
M2_BUTTON(el_td_ok, NULL, "ok", td_ok_fn);
M2_LIST(list_td_buttons) = {&el_td_cancel, &el_td_ok };
M2_HLIST(el_td_buttons, NULL, list_td_buttons);

M2_LIST(list_td) = {&el_time, &el_td_buttons };
M2_VLIST(el_top_td, NULL, list_td);


Oliver

Edit: Pull-up Resistor

Bob808

Yes, I connected the buttons as you recommended and managed to run your examples.
I like this approach:
Code: [Select]


#include <LiquidCrystal.h>
#include "M2tk.h"
#include "utility/m2ghlc.h"

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

uint8_t uiKeySelectPin = A3;
uint8_t uiKeyNextPin = A2;
int t =0;

uint32_t number = 0;

void fn_ok(m2_el_fnarg_p fnarg) {
  /* do something with the number */
  //t = number;
  Serial.println(number); 
}

M2_LABEL(el_label, NULL, "Hour: ");
M2_U32NUM(el_num, "a1c2", &number);
M2_BUTTON(el_ok, "", "ok", fn_ok);
M2_LIST(list) = { &el_label, &el_num, &el_ok };
M2_HLIST(top_el_hlist, NULL, list);
M2tk m2(&top_el_hlist, m2_es_arduino_rotary_encoder, m2_eh_4bd, m2_gh_lc);

void setup()
{
  Serial.begin(57600);
    m2_SetLiquidCrystal(&lcd, 20, 4);
  m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
  m2.setPin(M2_KEY_ROT_ENC_A, A0);
  m2.setPin(M2_KEY_ROT_ENC_B, A1);
  m2.setPin( M2_KEY_EXIT, uiKeyNextPin);
}

void loop() {
  m2.checkKey();
  m2.checkKey();
  if ( m2.handleKey() )
    m2.draw();
  m2.checkKey();
}


The issue is that your code does not work for me:
I used it like this:

Code: [Select]

#include "Wire.h"

#include <DS1307new.h>
#include <LiquidCrystal.h>
#include "M2tk.h"
#include "utility/m2ghlc.h"


LiquidCrystal lcd(12, 14, 11, 5, 4, 3, 2);


M2_EXTERN_ALIGN(top_menu);
uint8_t td_hour;
uint8_t td_min;
uint8_t td_sec;

M2_U8NUM(el_td_hour, "c2", 0,23,&td_hour);
M2_LABEL(el_td_sep1, NULL, ":");
M2_U8NUM(el_td_min, "c2", 0,59,&td_min);
M2_LABEL(el_td_sep2, NULL, ":");
M2_U8NUM(el_td_sec, "c2", 0,59,&td_sec);

M2_LIST(list_time) = { &el_td_hour, &el_td_sep1, &el_td_min, &el_td_sep2, &el_td_sec };
M2_HLIST(el_time, NULL, list_time);

M2_ROOT(el_td_cancel, NULL, "cancel", &el_top);
M2_BUTTON(el_td_ok, NULL, "ok", td_ok_fn);
M2_LIST(list_td_buttons) = {&el_td_cancel, &el_td_ok };
M2_HLIST(el_td_buttons, NULL, list_td_buttons);

M2_LIST(list_td) = {&el_time, &el_td_buttons };
M2_VLIST(el_top_td, NULL, list_td);




void setup() {
 

  m2_SetLiquidCrystal(&lcd, 20, 4);
  m2.setPin(M2_KEY_SELECT, A3);
  m2.setPin(M2_KEY_ROT_ENC_A, A0);
  m2.setPin(M2_KEY_ROT_ENC_B, A1);
}

void loop() {
  m2.checkKey();
  m2.checkKey();
  if ( m2.handleKey() )
    m2.draw();
  m2.checkKey();
}

void td_get_from_RTC(void)
{
  RTC.getTime();
  td_hour = RTC.hour;
  td_min = RTC.minute;
  td_sec = RTC.second;
}

void td_put_to_RTC(void)
{
  RTC.getTime();
  RTC.fillByHMS(td_hour, td_min, td_sec);
  RTC.setTime();
  RTC.startClock(); 
}

void td_ok_fn(m2_el_fnarg_p fnarg)
{
  td_put_to_RTC();
  m2.setRoot(&el_top);
}



And I get this error:

Code: [Select]
sketch_sep14a:27: error: 'el_top' was not declared in this scope
sketch_sep14a.ino: In function 'void setup()':
sketch_sep14a:42: error: 'm2' was not declared in this scope
sketch_sep14a.ino: In function 'void loop()':
sketch_sep14a:48: error: 'm2' was not declared in this scope
sketch_sep14a.ino: In function 'void td_get_from_RTC()':
sketch_sep14a:57: error: 'RTC' was not declared in this scope
sketch_sep14a.ino: In function 'void td_put_to_RTC()':
sketch_sep14a:65: error: 'RTC' was not declared in this scope
sketch_sep14a.ino: In function 'void td_ok_fn(_m2_el_fnarg*)':
sketch_sep14a:74: error: 'm2' was not declared in this scope
sketch_sep14a:74: error: 'el_top' was not declared in this scope


Right now I like the first approach style as I can rotate the encoder and set the hour for example, then press OK. I don't know how the code you gave me runs, but I'd like to be able to rotate the encoder between 00-23 for hours, then press ok, get back one level, select Minutes and set between 00-59. The example that works for me has 2 digits but I have to adjust each, and also they go 0-9 so that's not needed.
I need to wrap my head around what you did with the functions. Also I don't know what's what, how to declare them etc.
For example I have no clue as to how I could add a second "Minutes: [00]" to the first sketch, and move Hours down with Minutes and make another parent that's called "Settings" with OK button.

olikraus

Hi

Of course my code example is not complete. It was just intended as an example, how to construct the menu.

As a second step, let us create a simple numeric entry with the encoder. You have already selected, a nice example, but "M2_U32NUM" is not what you want. Instead, Please use M2_U8NUM, which will (hopefully) behave as intended by you.
So let me replace U32NUM by U8NUM and let me discuss the example more closely

Code: [Select]

#include <LiquidCrystal.h>
#include "M2tk.h"
#include "utility/m2ghlc.h"

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

uint8_t uiKeySelectPin = A3;
uint8_t uiKeyNextPin = A2;
int t =0;

// instead of the uint32_t data type, we just need a uint8_t
//uint32_t number = 0;
uint8_t number = 0;

// i just keep this function, println will take care on the changed datatype
void fn_ok(m2_el_fnarg_p fnarg) {
  /* do something with the number */
  //t = number;
  Serial.println(number); 
}

// M2_LABEL just places a constant string on the screen, i guess you already noticed this
M2_LABEL(el_label, NULL, "Hour: ");
// now, i just replace the U32NUM with U8NUM
//M2_U32NUM(el_num, "a1c2", &number);
// however the options and arguments are different and also the behavior is different
// please learn to look at the reference manual. I did my very best to describe these option and arguments.
// They ARE important.
// https://code.google.com/p/m2tklib/wiki/elref#U8NUM
// first arg: name of the element
// second arg: format string, c2 defines two digits (columns) for the input, this means numbers from 00 to 99
// third arg: minimum value, here 0
// forth arg: maximum value, here 23
// fifth arg: pointer to the variable
M2_U8NUM(el_num, "a1c2", 0, 23, &number);

// just a button
M2_BUTTON(el_ok, "", "ok", fn_ok);

// list is used to nest elements and construct/group more complex dialog boxes (which can also be reused)
M2_LIST(list) = { &el_label, &el_num, &el_ok };
M2_HLIST(top_el_hlist, NULL, list);
M2tk m2(&top_el_hlist, m2_es_arduino_rotary_encoder, m2_eh_4bd, m2_gh_lc);

void setup()
{
  Serial.begin(57600);
    m2_SetLiquidCrystal(&lcd, 20, 4);
  m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
  m2.setPin(M2_KEY_ROT_ENC_A, A0);
  m2.setPin(M2_KEY_ROT_ENC_B, A1);
  m2.setPin( M2_KEY_EXIT, uiKeyNextPin);
}

void loop() {
  m2.checkKey();
  m2.checkKey();
  if ( m2.handleKey() )
    m2.draw();
  m2.checkKey();
}


Actually i do not remember whether the a option has an influence here. Please check by yourself, whether this
Code: [Select]
M2_U8NUM(el_num, "a1c2", 0, 23, &number);

or this
Code: [Select]
M2_U8NUM(el_num, "a0c2", 0, 23, &number);

makes a difference for you with respect to the user input. M2tklib can be adjusted in a lot of different ways regarding the user input. But i guess, this needs to be specified first by you.

Oliver

olikraus

One more suggestion. I think with the rotary encoder it is better to use the 6-button handler:
Code: [Select]
M2tk m2(&top_el_hlist, m2_es_arduino_rotary_encoder, m2_eh_6bd, m2_gh_lc);

Additionally, you my want to change the events, which are sent by the rotary encoder:
Locate m2esarduino.c and
change line 233 to
Code: [Select]
      return M2_KEY_EVENT(M2_KEY_DATA_UP); /* disable debounce by M2tk algoritm */      

change line 245 to
Code: [Select]
      return M2_KEY_EVENT(M2_KEY_DATA_DOWN); /* disable debounce by M2tk algoritm */      


I think this will make more sense for you.

Oliver

Bob808

#5
Sep 15, 2014, 09:13 pm Last Edit: Sep 15, 2014, 11:02 pm by Bob808 Reason: 1
If I use the 6 button handler I get an error: "
sketch_sep15a:35: error: 'm2_eh_6bd' was not declared in this scope"
If I use m2_eh_6bs then it works but I have to scroll thru the numbers with the select button. The encoder rotates the options in the menu.
But it works fine with the 4 button one.
I only have 4 inputs anyway, left-right from the encoder and select/exit from two buttons.
"a1c2" vs "a0c2" doesn't produce any difference but I managed to understand the XY positioning system, and the fact that M2_U8NUM accepts C2 as well to define the number of digits.
And if I change the m2esarduino.c with your suggestions then I get an error, forgot to write it down, I changed it back.

I managed to add a second option for minutes as well, thank you for your help.
Indeed it helps to document each function.
Now, another issue. My display is all messed up. It's a common 20x4 LCD, and it's defined as such in the Setup. But the thing is that "Hour:" appears on the lowest line.
Well, I managed to make my menu page. Now I need to add a root menu that this sub-menu is part of. Something like:

              Settings
               /         \
   Set Time   Set Alarm
          |                  |
The menu I        Similar
just made           menu


This is my latest code:

Code: [Select]
#include "Wire.h"
#include <LiquidCrystal.h>
#include "M2tk.h"
#include "utility/m2ghlc.h"

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

uint8_t uiKeySelectPin = A3;
uint8_t uiKeyExitPin = A2;
uint8_t hours = 0;
uint8_t minutes = 0;

void fn_set(m2_el_fnarg_p fnarg)
 {
 Serial.print(hours);
 Serial.print(":");
 Serial.println(minutes);
 }
void fn_back(m2_el_fnarg_p fnarg)
 {
//back command
 }


M2_LABEL(el_set_time, "x5y3", "Set time:");
M2_LABEL(el_hour, "x3y2", "hour   -");
M2_U8NUM(el_num, "x12y2c2", 0, 23, &hours);
M2_LABEL(el_minute, "x3y1", "minute -");
M2_U8NUM(el_num2, "x12y1c2", 0, 59, &minutes);

M2_BUTTON(el_set, "x3y0", "set", fn_set);
M2_BUTTON(el_back, "x10y0", "back", fn_back);
M2_LIST(list) = {&el_set_time, &el_hour, &el_minute, &el_num, &el_num2, &el_set, &el_back};
M2_XYLIST(el_gridlist, NULL, list);
M2tk m2(&el_gridlist, m2_es_arduino_rotary_encoder, m2_eh_4bd, m2_gh_lc);



void setup() {
 
 Serial.begin(57600);
 m2_SetLiquidCrystal(&lcd, 20, 4);
 
 m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
 m2.setPin( M2_KEY_EXIT, uiKeyExitPin);
 m2.setPin(M2_KEY_ROT_ENC_A, A0);
 m2.setPin(M2_KEY_ROT_ENC_B, A1);
 
}

void loop() {
 m2.checkKey();
 m2.checkKey();
 if ( m2.handleKey() )
   m2.draw();
 m2.checkKey();
}



olikraus

Hi

I am sorry, that some of my suggestions lead to a syntax error. I actually did not test anything. But i am glad you figured out a configuration, that works for you.

A typical top menu looks like this:
Code: [Select]

M2_ROOT(el_root_set_time, "", "set time", &top_el_set_time);
M2_ROOT(el_root_set_alarm, "", "set alarm", &top_el_set_alarm);

M2_LIST(list_main_menu) = {
    &el_root_set_time,
    &el_root_set_alarm
};

M2_VLIST(el_main_menu_vlist, NULL, list_main_menu);
M2_ALIGN(top_el_main_menu, "-1|1W64H64", &el_main_menu_vlist);


Instead of VLIST you can also use XYLIST, but VLIST automatically calculates the correct possition and ALIGN will center everything on the screen (so you do not need to deal with the xy position).

Of course for the constructor, you need to provide "top_el_main_menu" as a startingpoint for your menu structure.
Basically something like this will appear on the screen:


........................................
...........[set time]...................
...........[set alarm]..................
........................................


In fact it is usually a good idea to draw the desired layout before coding the menu.

Now it is time to code the "set time" dialog box. Let me just create a very simple input box. Sure it can be extended and enriched with some buttons:

[00]:[00]:[00]................................
[ok] [cancel]...........................
........................................
........................................


Now i think it is time to copy the data from my initial answer.

First, some tmporary variables are required for m2tklib:
Code: [Select]
uint8_t td_hour;
uint8_t td_min;
uint8_t td_sec;

You need to communicate through these variables. Values are taken from this global variables and user input is written to this variables.

Here is the code:
Code: [Select]
void td_ok_fn(m2_el_fnarg_p fnarg)
{
// store the input data somewhere
}

M2_U8NUM(el_td_hour, "c2", 0,23,&td_hour);
M2_LABEL(el_td_sep1, NULL, ":");
M2_U8NUM(el_td_min, "c2", 0,59,&td_min);
M2_LABEL(el_td_sep2, NULL, ":");
M2_U8NUM(el_td_sec, "c2", 0,59,&td_sec);

M2_LIST(list_time) = { &el_td_hour, &el_td_sep1, &el_td_min, &el_td_sep2, &el_td_sec };
M2_HLIST(el_time, NULL, list_time);

M2_ROOT(el_td_cancel, NULL, "cancel", &el_top);
M2_BUTTON(el_td_ok, NULL, "ok", td_ok_fn);
M2_LIST(list_td_buttons) = {&el_td_cancel, &el_td_ok };
M2_HLIST(el_td_buttons, NULL, list_td_buttons);

M2_LIST(list_td) = {&el_time, &el_td_buttons };
M2_VLIST(top_el_set_time, NULL, list_td);

Please note, that the toplevel element has the name "top_el_set_time", which is refered by M2_ROOT from your top level menu. In fact M2_ROOT is like a goto statement. I acts like a button. Once pressed, it will give control to another dialog box.
Again, you could replace the nested VLIST and HLIST elements with a single XYLIST, but i prefer the automatic calculation of positions. So i hope you can read most of the code and maybe the only new element is M2_BUTTON.
M2_BUTTON is very similar to M2_ROOT: It adds a button. But once pressed, it just calls a function. In this case the function is "td_ok_fn". You can use any name of course. In fd_ok_fn, you will know, that the user has pressed the ok button and you need to do something with the values in the three global values.

A similar structure needs to be added for the date input.

Hope i have you enough information for proceeding here. If not, please continue to ask.

Oliver

Bob808

Thank you very much for your help.
I must say that your software is a real powerhouse  8)

I used XY as VLIST was making it look very weird, it would start on the lowest line then continue inline with everything on the top line. So I just used XY as I didn't know what else to do.
Actually I think I've done what I wanted. I borrowed code from Menu2L example and it worked out great.
I will now look at your examples and try to understand them and try it other ways as well. It's a real gem what you have here :) Lots of options for a menu!

So I am finished right now with this code. It allows one to input the current time, and store it in a variable (you can use that to program the RTC). Then you can set the alarm time, another variable that can be written on EEPROM and with alarms library can trigger events at certain times. The beauty with RTC and EEPROM is that it has redundancy on power failure :)

I will come back and ask a few questions if I can't sort it out myself.
Actually, is there a way to have an idle screen with the clock? I have two variables from RTC library that store hour and minutes separately. Something that kicks in after 20 seconds of inactivity or I can call from the menu with Exit button. At the moment I dropped that button as I have the graphical "Back" selection that gets me back to root.

Thank you once again and I hope that this thread will help others better understand how to use your library. It has a bit of a steep learning curve but after a short while you kinda start figuring stuff out.

Code: [Select]

#include <LiquidCrystal.h>
#include "M2tk.h"
#include "utility/m2ghlc.h"
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
uint8_t uiKeySelectPin = A3;
uint8_t t_hours = 0;
uint8_t t_minutes = 0;
uint8_t a_hours = 0;
uint8_t a_minutes = 0;
M2_EXTERN_HLIST(top_el_expandable_menu);
M2_LABEL(el_set_time, "x5y3", "Set time:");
M2_LABEL(el_ht, "x3y2", "hour   -");
M2_U8NUM(el_t_hour, "x12y2c2", 0, 23, &t_hours);
M2_LABEL(el_mt, "x3y1", "minute -");
M2_U8NUM(el_t_minute, "x12y1c2", 0, 59, &t_minutes);
M2_BUTTON(el_set_t, "x3y0", "set", fn_set_t);
M2_BUTTON(el_back_t, "x10y0", "back", fn_back);
M2_LIST(timelist) = {&el_set_time, &el_ht, &el_mt, &el_t_hour, &el_t_minute, &el_set_t, &el_back_t};
M2_XYLIST(el_set_Time, NULL, timelist);
M2_LABEL(el_set_alarm, "x5y3", "Set Alarm:");
M2_LABEL(el_ah, "x3y2", "hour   -");
M2_U8NUM(el_a_hour, "x12y2c2", 0, 23, &a_hours);
M2_LABEL(el_am, "x3y1", "minute -");
M2_U8NUM(el_a_minute, "x12y1c2", 0, 59, &a_minutes);
M2_BUTTON(el_set_a, "x3y0", "set", fn_set_a);
M2_BUTTON(el_back_a, "x10y0", "back", fn_back);
M2_LIST(alarmlist) = {&el_set_alarm, &el_ah, &el_am, &el_a_hour, &el_a_minute, &el_set_a, &el_back_a};
M2_XYLIST(el_set_Alarm, NULL, alarmlist);
m2_menu_entry m2_2lmenu_data[] =
{
  { "Settings", NULL },
  { ". Set Time:", &el_set_Time },
  { ". Set Alarm:", &el_set_Alarm },
  { NULL, NULL },
};
uint8_t m2_2lmenu_first;
uint8_t m2_2lmenu_cnt;
M2_2LMENU(el_2lmenu,"l4e1w12", NULL, &m2_2lmenu_cnt, m2_2lmenu_data, NULL, NULL, '\0');
M2_LIST(list_2lmenu) = { &el_2lmenu};
M2_HLIST(top_el_expandable_menu, NULL, list_2lmenu);
M2tk m2(&top_el_expandable_menu, m2_es_arduino_rotary_encoder, m2_eh_4bd, m2_gh_lc);

void setup() {
  Serial.begin(57600);
  m2_SetLiquidCrystal(&lcd, 20, 4);
  m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
  m2.setPin(M2_KEY_ROT_ENC_A, A0);
  m2.setPin(M2_KEY_ROT_ENC_B, A1);
}

void loop() {
  m2.checkKey();
  m2.checkKey();
  if ( m2.handleKey() )
    m2.draw();
  m2.checkKey();
}


void fn_set_t(m2_el_fnarg_p fnarg)
  {
    Serial.print(t_hours);
    Serial.print(":");
    Serial.println(t_minutes);
  }
void fn_set_a(m2_el_fnarg_p fnarg)
  {
    Serial.print(a_hours);
    Serial.print(":");
    Serial.println(a_minutes);
  }
void fn_back(m2_el_fnarg_p fnarg)
  {
    m2.setRoot(&top_el_expandable_menu);
  }

olikraus

#8
Sep 15, 2014, 11:58 pm Last Edit: Sep 16, 2014, 12:00 am by olikraus Reason: 1

Quote
Actually, is there a way to have an idle screen with the clock?


Sure, this is possible. First you need to figure out the inactivity. This is, if you never enter the if block in your main loop (m2.draw() is not executed for some seconds). For example, you can store the last active time in the if block. I created some code for this, but i did not test this. Same background information is also given here: https://code.google.com/p/m2tklib/wiki/t06glcd

Code: [Select]

int32_t last_action_time = 0;
uint8_t is_menu_active = 1;

void loop() {
  m2.checkKey();
  m2.checkKey();
  if ( is_menu_active != 0 ) {
    if ( m2.handleKey() ) {
      last_action_time = millis();  // user input append, store event time
      m2.draw();
    }
    if ( last_action_time > millis() + 20000 ) {  // nothing has happend for 20 sec.
     is_menu_active = 0;  // deactivate menu
      m2.setRoot(&m2_null_element);  // assign a predefined empty menu
   }
  else {
    // here you can use lcd.print() to output time on the lcd.
    // ...

    // menu is deactivated, but key detection still works
   // check for any user input
    if ( m2.getKey() != M2_KEY_NONE ) {
      // input has happend, store event time, activate menu
      last_action_time = millis();
      is_menu_active = 0;
      m2.setRoot(&top_el_expandable_menu);  // restore the toplevel dialog box
   }
  }
}
}


Glad to see, that you managed to climb up the learning curve.

Oliver

Bob808

The code as is floods my LCD with the test message, instantly after boot. Need to look at it more :/

Go Up