Go Down

Topic: M2TKLIB - A User-Interface-Toolkit for the Arduino Hardware (Read 10572 times) previous topic - next topic



M2_STRLIST with the "l" format option set to 1 could replace M2_COMBO. M2_STRLIST is more powerful and has a dynamic number of elements. Let me know if M2_STRLIST will be ok for your application.

I miss an item type M2_DUMMY , that does not perform visual nothing but only to call a function.

I do not fully understand this. You need something which does not display anything, but will call a function.
Maybe you can describe your desired application for this so that i get a better understanding for this. Also note that there is now an additional callback procedure which might help: http://code.google.com/p/m2tklib/wiki/fnref#setRootChangeCallback



Thanks, I will try your suggestions.
I will update the library (was with 1.08.1)



I have added an issue on the project page to implement M2_COMBO with changeable number of elements. Hope this is what you have requested.
M2_STRLIST is close to your request, but maybe an improved M2_COMBO might be better.



M2_STRLIST, ok the msg parameter and operation.
But he is in between of other elements, and I can not move to the next or previous item.

In COMBO would be interesting to know if the value of combo has changed by a msg in cb function.

setRootChangeCallback , i think not server:

Code: [Select]

m2_menu_entry m2_2lmenu_data[] =
  { "Menu 1", NULL },
  { "Menu 2", NULL },
  { "Execute", &top_el_dummy },
  { NULL, NULL },

void dummy_fn(m2_el_fnarg_p fnarg)
  arr = (TimeAlarmsClass *) malloc(sizeof(TimeAlarmsClass) * 10);
  for(int i = 0; i < 10; i++)
delay (1000);



From a menu item. I want to execute a function
It is made with a button but I do not want to use the button.
I need an item that does not show anything and know that the menu item was who called

Thanks very much by the interest

Best Regards



M2_STRLIST: Yes, M2_STRLIST is more like a toplevel element and is difficult to use in between other elements.
I will add a more flexible M2_COMBO with dynamic number of elements.

In COMBO would be interesting to know if the value of combo has changed by a msg in cb function.

There is no value change callback. Instead you can observe the value, which is modified by M2_COMBO

Code: [Select]

uint8_t var_for_m2_combo;  // adr of this var is given to M2_COMBO
uint8_t prev_value;             // this is a backup value to detect changes by M2_COMBO
void loop(void)
   if ( prev_value != var_for_m2_combo )
     // value has changed, do some action
    prev_value = var_for_m2_combo;

From a menu item. I want to execute a function

With M2_2LMENU you can only call other menus. Use M2_STRLIST, which allows you to call other menues or execute procedures.

BTW: You should free the allocated memory in your callback proc.




I have added the requested functionality: M2_COMBOPTR and M2_SPACECB

M2_COMBOPTR is identical to M2_COMBO except that the cnt (len) parameter now is a pointer to a 8-bit variable:

Code: [Select]

uint8_t comboptr_val = 0;
uint8_t comboptr_cnt = 3;
const char *comboptr_idx_to_color(uint8_t idx)
  if ( idx == 0 )
    return "red";
  else if (idx == 1 )
    return "green";
  return "blue";
M2_COMBOPTR(el_comboptr, NULL, &comboptr_val, &comboptr_cnt, comboptr_idx_to_color);
M2_ALIGN(top_el_comboptr_menu, "W64H64", &el_comboptr);

M2_SPACECB is identical to M2_SPACE except that a callback procedure will be called as soon as a new menu is rendered on the screen. This makes M2_SPACECB a suitable element that implements a single action for the 2LMENU. In the following example, the 2LMenu does not refer to other menues, but instead calls M2_SPACECB and its action procedures. These action procedures modify a 8 bit variable in the following example:

Code: [Select]

uint8_t el_space_u8 = 0;
void fn_space_cb_zero(m2_el_fnarg_p fnarg) {
  el_space_u8 = 0;
  m2_SetRootExtended(&top_el_spacecb_menu, 0, 0);
void fn_space_cb_inc(m2_el_fnarg_p fnarg) {
  m2_SetRootExtended(&top_el_spacecb_menu, 1, 0);
void fn_space_cb_dec(m2_el_fnarg_p fnarg) {
  m2_SetRootExtended(&top_el_spacecb_menu, 2, 0);
M2_SPACECB(el_space_cb_zero, NULL, fn_space_cb_zero);
M2_SPACECB(el_space_cb_inc, NULL, fn_space_cb_inc);
M2_SPACECB(el_space_cb_dec, NULL, fn_space_cb_dec);
m2_menu_entry space_cb_menu_data[] = {
  { "Zero", &el_space_cb_zero },
  { "Inc", &el_space_cb_inc },
  { "Dec", &el_space_cb_dec },
  { NULL, NULL },
uint8_t el_2lspace_first = 0;
uint8_t el_2lspace_cnt = 3;
M2_U8NUM(el_2lspace_u8, "r1c3", 0, 255, &el_space_u8);
M2_2LMENU(el_2lspace_strlist, "l3e15F3W47", &el_2lspace_first, &el_2lspace_cnt, space_cb_menu_data, 65, 102, '\0');
M2_LIST(list_2lspace_strlist) = { &el_2lspace_u8, &el_2lspace_strlist };
M2_VLIST(el_2lspace_hlist, NULL, list_2lspace_strlist);
M2_ALIGN(top_el_spacecb_menu, "-1|1W64H64", &el_2lspace_hlist);

M2tklib for GLCD attached. Let me know if other variants are needed.



tested and perfect, this is what I needed.
I have trouble express my thoughts in english, very bad. :smiley-red:

Thanks you


Afternoon, is it possible for a user to input a negative number in the M2_U8NUM or U32NUM elements?

Code: [Select]

M2_U8NUM(el_u1, "c2", -20, 80, &n1);

I'm just playing around with the Rotary Encoder example at the moment to get to grips with this.

I'm trying to get a user to select a target temperature for a heater/cooler combination that can range from -20c to 80c.



Thanks for the request. I added issue 96 to the project for the implementation of M2_S8NUM.
It is almost finished:
Code: [Select]
M2_S8NUM(el_num_2, "+1c3", -128, 127, &s8num);

The new format option "+" controls visibibility of the "+" sign:
"+1": "+" is visible
"+0": "+" is not displayed

Let me know which m2tklib variant you need. I will add a prerelease here.



Ooh, thank you.
I'm using the Liquid Crystal varient.

I spent a few hours today just playing around with menu's. i must say i'm impressed, this is perfect for my project.

Now, only if i could get my damn weird bouncy rotary encoder working well! Accidentally bought a ABC switch type one.


The attached 1.10pre2 includes the "M2_S8NUM" element. It is identical to the M2_U8NUM object except for the additional "+" format option (see above).

Let me know if you have any further questions.



I think the archive may be corrupted, or prehaps my computors playing up.


I use both character and graphic lcds in different projects, both the expanded libraries are named m2tklib.
How can I install both, or do I have to uninstall one to use the other, then switch when I change displays?
Einstein once said you don't really understand anything until you can explain it to your Grandmother


I have uploaded the prerelease here: http://code.google.com/p/m2tklib/downloads/list.

You could merge files of two variants of m2tklib (must be the same release number). But in your sketch (.ino file) you must include both, LiquidChrystal and the GLCD header. In fact you must include both, even if you use only one output device.
If you do not include both headers, the Arduino IDE will fail to compile M2tklib: If you have only included LiquidCrystal, Arduino IDE will fail to compile GLCD specific files of M2tklib.
An other option is to install the Arduino IDE twice. Setup one instance for your character displays and the other for graphics displays.



Mar 12, 2013, 09:26 pm Last Edit: Mar 12, 2013, 11:25 pm by Veco Reason: 1
Cheers olikraus,

Is there a signed flavour of uint8_t?

Same goal as last time, trying to use a range of -20 to 80 within M2_S8NUM with my rotary encoder.

Finally got a standard rotary encoder, it works very smoothly with your implimentation.
Just begining to put together my menu now i've got my prototyping rig set up since this weekend.

Code: [Select]

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

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

// Forward declaration of the toplevel element

// Simple dialog: Input two values n1 and n2

sint8_t n1 = 0;
uint8_t n2 = 0;

M2_LABEL(el_l1, NULL, "Temperature:");
M2_S8NUM(el_u1, "c2", -20, 80, &n1);
M2_LABEL(el_l2, NULL, "Humidity:");
M2_U8NUM(el_u2, "c2", 0, 100, &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);

// m2 object and constructor
// Note: Use the "m2_eh_4bd" handler, which fits better to the "m2_es_arduino_rotary_encoder"
M2tk m2(&top_menu, m2_es_arduino_rotary_encoder, m2_eh_4bd, m2_gh_lc);

// Arduino Setup & Loop

void setup() {
 m2_SetLiquidCrystal(&lcd, 20, 4);
 // define button for the select message
 m2.setPin(M2_KEY_SELECT, 8);
 // The incremental rotary encoder is conected to these two pins
 m2.setPin(M2_KEY_ROT_ENC_A, 2);
 m2.setPin(M2_KEY_ROT_ENC_B, 3);

void loop() {
 if ( m2.handleKey() )

Also, what is the purpose of calling "m2.checkKey();" multiple times within the main loop?

I'm also confused about how i pass a value back through the callback procedure. I was looking at the example code and i'm unsure how i would use that. Say for example i wanted to do a Serial.print(); of the current S8NUM value for el_u1.

Code: [Select]

uint8_t global_value = 0;

uint8_t u8_cb(m2_rom_void_p element, uint8_t msg, uint8_t val)
 if ( msg == M2_U8_MSG_SET_VALUE )
   global_value = val;
 return global_value;

M2_U8NUMFN(el_u8_cb, NULL, 0, 10, u8_cb);

Thank you for putting up with me! I'm a determined Newb i'm afraid.

Go Up

Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

via Egeo 16
Torino, 10131