Menus for Micropython

Simple but powerful, multitasking menus for Micropython, using a little display board and a rotary encoder.

Public Chat
Similar projects worth following
This is a simple GUI menu system for micropython using a rotary encoder and a display.

Menus are defined as lists and do not require complex programming.

The root menu may have unlimited submenus.

Data can be entered in the form of string selections through the menu or as integers by twiddling the encoder.

Extra Information can be displayed, such as status information.

A menu-item calls a function to perform an action. The action can be a normal python function or a co-routine (for multitasking) .

Multitasking allows long running functions (for instance a neopixel display) to run without stopping the menu system.


                                                 MENU OVERVIEW

Hardware used in development

The menu system was developed on a Raspberry Pi Pico with  Micropython and standard hardware libraries.  The encoder  was from Sparkfun and had a switched and illuminated shaft.  An 128x64 pixel OLED  was used for the display. The switch or button used was just the shaft switch on the encoder.

The neopixel example uses a "GlowBit rainbow" from Core electronics which is a convenient form of neopixels for development.  The neopixel driver software was adapted from the PIO examnple in the Raspberry Pi documentation.

The test setup was built on a breadboard with DuPont connector and crocodile clips and seemed to work fine.

Menu item

A menu item has two parts, a caption which is a string,  and an action which is a function.  The function  is called when the menuitem is clicked.. The action  function that takes no parameters (more about this later).

Menu (wrap_menu)

A menu is defined as a list of menuitems and is "wrapped" into a function that makes the menu active.  

The action of menuitem can be another menu. This way we can have any depth of submenus.

Entering information.

Get Numerical input (get_integer)

We might need to enter some numerical information to our system. For instance we may need to enter  hours, minutes and seconds in to set up a clock.  A function called get_integer is provided for this purpose.

Getting text input (get_selection)

We can enter some string or text value similar to the select box in HTML.   A selection is defined as list of pairs composed of  caption,data.  This is similar to the definition of a menu.

Show textual information (info)

info allows us to show some text on the screen.  The text can be just a simple string or can be a function that returns a string.  The function could, for instance allow us to show the current time.


Often we need to enter a sequence of numbers, for instance hour,minute second or year, month day which is the function of a wizard. While wizards are not essential they are useful .  Wizards are defined a bit like menus and selections.

Getting data out of a menu

We need some way to read the information that we entered with get_integer or selection.  To do this, the information getting functions have a field.  The field is used a key for in a global dictionary called data.

For instance after we entered a values for hours (by clicking on the value) it then becomes available as  the global variable .['hours'] = 10

What about actions?

Actions are just python functions that have no parameters.  

For instance a function could fill a neopixel string with a color.  The colour could be fixed but we could use the value in the data dictionary  set previously with selection.

What about parameters for action functions?

Having functions with no parameters seems a bit limiting.  Fortunately there a couple of  workarounds. 

1.  A function can have default parameters.  These are used as the parameters if the function is called with no parameters.  

2. Another way is to use closures.  Most people are less familiar with closures but they  are actually very simple and are  equivalent to and a little bit more flexible than default parameters.  This is the way we we wrap up  menus and selections and wizards.

  • 1 × Breadboard (China) Electronic Components / Misc. Electronic Components
  • 1 × Oled display 128 x64 pixels (SSD1306) (China)
  • 1 × Rotary encoder with switch in shaft (Sparkfun)
  • 1 × Glowbit rainbow (Core electronics, Australia)
  • 1 × Raspberry Pi Pico (Core electronics)

View all 9 components

  • Project changes

    sgall17a05/16/2021 at 11:29 0 comments

    The comments on this project have been very helpful in two ways.  The comments have been useful in themselves and the presence of some interest in the project inspires me to do a bit more work on it.  My plans are listed below:

    1.  Do a short video of the menu functioning.  I will do this but and have made a start.  I come to realise that I am pretty challenged in the video department and it is not quite as simple as I thought to make even a passable video.

    2. Make the two main driver events (on_scroll, and on_click) much more explicit.  These two events and all function and class definitions  should be factored  out into  their own module so that it does not depend on any particular hardware.   This should make the hardware module cleaner.

    3.  Having made cleaner separation of hardware code and menu code I want to make a "pseudo-hardware" version for Jupyter that uses widgets in a notebook.  This means that menus could be be built and tested in Jupyter before running on actual hardware.

    I am hoping that  the method defining menus wont change.  

    3.   John suggested in a comment that there should be some indicators of the role and/or state of menu-items.  In order to keep it to simple text we could do this with some special characters or small strings.  I think a lot of this could be done just by convention when we define the menus.  For instance a submenu could be shown as "> Submenu", instead of just "Submenu" or an an information item could be written as "# Information" rather than just "Information".  These would give the user some indication of what the menu item does.  Obviously other markers could be used.   Instead of convention would could make the various classes add a specific indicator to their caption on construction.

View project log

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates