Very basic menu.

H, I have some simple code to turn on and off a relay (via an RTC)... to control a 240v light.

i also have an lcd display and rotary encoder and would love a simple menu to input the on/off times for the light. but im at the limits of my arduino knowledge!!!
i have read about menubackend and menwiz but didnt understand much. are there any good tutorials out there ?? i have looked but cant find much...

ultimately id like to click the encoder button and it display "menu" then turning the encoder show the menu options like "light settings" another click to select and then input the on/off times to control the lights...

any help appreciated !

onisuk:
i also have an lcd display and rotary encoder and would love a simple menu to input the on/off times for the light. but im at the limits of my arduino knowledge!!!
i have read about menubackend and menwiz but didnt understand much. are there any good tutorials out there ?? i have looked but cant find much...

I think I have read similar requests about a 'rotary encoder menu' several times before in this forum during the last few months. Without any suitable solution posted, as far as I remember.

If you don't need it at once, I can give it a try and develop something that will do the job.

onisuk:
ultimately id like to click the encoder button and it display "menu" then turning the encoder show the menu options like "light settings" another click to select and then input the on/off times to control the lights...

any help appreciated !

Any thoughts about a "cancel menu" function?
As the rotary encoder has just one additional button, perhaps all the menu functions are limited to

  • one rotary function
  • one button function

What if a menu had been enabled by mistake or even a value in the menu had been changed by mistake, don't you think there should be two different functions like "OK - save value" and "Cancel - abort" to quit the menu mode?

I could think of three possible solutions while using just one button:

  1. Press button ==> OK
    Timeout ==> Cancel
    So if neither the encoder is rotated nor the button pressed during a several seconds interval, the menu cancels itself after timeout time has passed.

  2. Press button long duration ==> OK
    Press button short duration ==> Cancel
    So you'd have to make a "long press" on the button to save any changes, a short press will about without changes

  3. Double click ==> OK
    Single click ==> Cancel
    So if you finish with a 'double click' (two button presses within a short time), changes will be saved, otherwise the menu is aborted

What would you prefer to aboirt/cancel a menu? 1, 2 or 3?

Or would it be enough for you, that every time a menu is activated, there is no difference between "OK" and "Cancel" when leaving the menu?

yes something along those lines, you would click "light times" then go on to "on time" turn the dial to set the number 1-24 then double click to enter the value etc... ?!

onisuk:
yes something along those lines, you would click "light times" then go on to "on time" turn the dial to set the number 1-24 then double click to enter the value etc... ?!

I've just made some preliminary work for a simple "rotary encoder menu".

Not yet finished, very rudimentary functions.

What works:

  • reading the button actions: for SHORTCLICK, DOUBLECLICK and LONGCLICK
  • reading the rotary encoder in full steps (just counting up and down)
  • activating/deactivating menu with output on Serial and LCD
    No time functions included.

But I haven't made yet made a decision whether it would be very easy to use such a programming logic for time and date settings with a rotary encoder. Perhaps not.

Meanwhile I tend to a solution where the user can activate some kind of time editor that works like that: The user is presented a time (or date) string along with "OK" and "Exit" messages, perhaps:

13:15  OK Exit

The user then can rotate left or right to change a cursor position on the LCD to select either a 'digit' of the time/date or "Ok" or "Exit". When pressing the button while the cursor is placed on a digit, the digit will increment and roll over from 9 to 0. When pressing the button while cursor is on "OK" or "Exit", the menu is finished accordingly.

If I find some time, I will do some further work on that, so that you can possibly use the encoder menu for

  • setting RTC date
  • setting RTC time
  • setting ON time for relay
  • setting OFF time for relay

Would it be enough to have a one minute resolution for time settings?
Or do you need to set times with a one second resolution?

And BTW: Whats your preferred date format? DMY, YMD, MDY? Here in Germany the date of today would be written:

13.04.2015

Which date representation would you prefer to show up in the rotary encoder menu for editing?

Library does not need installation, just unpack the folder within the ZIP file into the Arduino sketch folder on your harddisk.

encoderMenu.zip (1.93 KB)

well i have rotary encoder code that just increment or decrements a volatile unsigned int encoderPos = 0; // a counter for the dial
so surely you could just state that the relay turn on time would be = to encoderPos ??

minute resolution is fine...

also yes i was going to try to figure out how to code to adjust DTS on the RTC as the time is out unless i re-flash it ! not very practical

im for the uk so date format is the same here i believe

onisuk:
also yes i was going to try to figure out how to code to adjust DTS on the RTC as the time is out unless i re-flash it ! not very practical

What does 'DTS' mean?
Do you mean perhaps 'DST' (Daylight Saving Time)?

onisuk:
im for the uk so date format is the same here i believe

OK, so I'll give it a try with dd.mm.yyyy date format.

And I think that UK meanwhile uses the same DST algorithm as the rest of Europe:
DST is active from last Sunday in March until last Sunday in October.

In that case I could also provide my own RTC routines which are dealing with DST like this:

  • RTC is always running in 'zone time'
  • two different read functions can read 'zone time' or 'local time' from the RTC as the user likes it

Which RTC do you use? DS1307? DS3231? Or something else?
My RTC code would be ready to use with DS1307 and DS3231 RTC at the moment.

DS3231 thanks

ok ill check it out ! thanks

I do like the idea of simplified I2C-LCD+encoder menu system, so kindly interested in the current status of the development

get back to jurs post:

Why not just enter into SetTime Menu with short-button,
then make blink the HH, rotary for change the value, wait for short-button like confirmation,
go blink MM, rotary for change the value, short-button for confirmation, and thats it,
hour and minutes are saved. Same solution can be used for YYYY-MM-DD. and no bother.

why dont we make the long_button as back, and doubleclick-button as cancel ?

since I am not writing the code, I feel adding options is easy.

one of the menu options might be:

to review.
press-long to save and review.

to cancel all and re-start....
press hold to cancel all and re-start

save settings in memory spot (1/2/3/4/5) for future use.

daemons:
I do like the idea of simplified I2C-LCD+encoder menu system, so kindly interested in the current status of the development

I must admit that I was lazy and did not finish any rotary-menu code yet.
At least not such finished, that I wanted to show the code to someone else.

Everytime I started something and asked somebody about, there was either no response or people told me that they needed it completely different than suggested by me.

But after I saw your posting today, I tried a bit something new with some old code of mine.
For me it works.

What I found out until now is that: I cannot create a all-in-one-code that will handle everything: Simple menus, 2D- and pull-down menus, menus with 2,3 or 4 level, menu items adding and removing at runtime, function calling menus, configuration settings menus, menus with 3, 4, 5 or 6 buttons, date and time editing in different international time/date formats.

So something will have to be limited and I'd say:
Display should be a LCD text display.
And control element a mechanical rotary encoder with momentary switch only.
Perhaps adaptable to common I2C LCDs by "conditional compile".

daemons:
get back to jurs post:

Why not just enter into SetTime Menu with short-button,
then make blink the HH, rotary for change the value, wait for short-button like confirmation,
go blink MM, rotary for change the value, short-button for confirmation, and thats it,
hour and minutes are saved. Same solution can be used for YYYY-MM-DD. and no bother.

why dont we make the long_button as back, and doubleclick-button as cancel ?

Even the user interface cannot be made for everyone, if everybody wants something different.

Currently I'm at this state of menu interaction:

  1. Menu works with a rotary encoder and just two actions: rotate or button press
    No sophisticated double-click or long-click actions

  2. Display can display menu items and edit date or time
    Date format is currently dd.mm.yyyy and time format is HH:MM:SS
    No fancy blinking, but a "cursor" is set under the character that can be edited

Usage and editing logic:

  • Button press ==> enabled menu
  • Rotate left/right ==> select menu item
  • If button is pressed on a "date" menu item ==> activate date editor
  • If button is pressed on a "time" menu item ==> activate time editor

Editor works like that:

  • display editable value and "OK"
  • rotate left/right ==> Move cursor for editing a single digit or for "OK"
  • rotate cursor right outside the LCD display ==> Abort editing
  • click button while on editable digit: increase digit (roll-over from 9 to 0)
  • click button while on "OK" ==> check validity of entered value and exit

The advantage of waiving "double clicks" and "long clicks" from the user control is: The user will be enabled for fast editing with fast clicking, because it is never required to wait for "double click time" or "long click time" that might create a different click from an initial button press.

If my time allows, I'll put some more comments into the code and put it in a form so I can upload an example program. Possibly a "timer switch with LCD and rotary encoder", that can: Display date and time, edit date and time, and also edit some daily switching times for ON/OFF of a device.

If I find some time this weekend, I hopefully will be able to send some experimental code for those who are interested by the beginning of next week.

I must admit that I was lazy and did not finish any rotary-menu code yet.
At least not such finished, that I wanted to show the code to someone else.

Everytime I started something and asked somebody about, there was either no response or people told me that they needed it completely different than suggested by me.

No problem, will appreciate your effort.

jurs:
If I find some time this weekend, I hopefully will be able to send some experimental code for those who are interested by the beginning of next week.

Sounds good, keen to look at it.

If my time allows, I'll put some more comments into the code and put it in a form so I can upload an example program. Possibly a "timer switch with LCD and rotary encoder", that can: Display date and time, edit date and time, and also edit some daily switching times for ON/OFF of a device.

Thats it what most of us might need as a starting point, Time, SetTime, SetOnOff- should be anough to start with.

What I found out until now is that: I cannot create a all-in-one-code that will handle everything: Simple menus, 2D- and pull-down menus, menus with 2,3 or 4 level, menu items adding and removing at runtime, function calling menus, configuration settings menus, menus with 3, 4, 5 or 6 buttons, date and time editing in different international time/date formats.

So something will have to be limited and I'd say:
Display should be a LCD text display.
And control element a mechanical rotary encoder with momentary switch only.
Perhaps adaptable to common I2C LCDs by "conditional compile".

Even the user interface cannot be made for everyone, if everybody wants something different.

Agree,
The basic means in my case similar,
Text LCD, /16x2, or better 20x4/ i2c sounds reliable.
one layer menu, no sub menus.
one rotary encoder with button.
-sounds simple.

  1. Menu works with a rotary encoder and just two actions: rotate or button press
    No sophisticated double-click or long-click actions

Also not a problem yet, can be "upgraded later" if required, i will try later then.

Usage and editing logic:

  • Button press ==> enabled menu
  • Rotate left/right ==> select menu item
  • If button is pressed on a "date" menu item ==> activate date editor
  • If button is pressed on a "time" menu item ==> activate time editor

Editor works like that:

  • display editable value and "OK"
  • rotate left/right ==> Move cursor for editing a single digit or for "OK"
  • rotate cursor right outside the LCD display ==> Abort editing
  • click button while on editable digit: increase digit (roll-over from 9 to 0)
  • click button while on "OK" ==> check validity of entered value and exit

Looks good for now, however i might want to play around the editor screen.

Actually as said before, your intention is preatty close to mine.

daemons:
Looks good for now, however i might want to play around the editor screen.

No problem, full source will be included. :slight_smile:

But if this is about your preferred date/time format, you better tell me before I finish some code. I then can possibly offer a variant to what I'm currently doing.

Currently the date editor uses European/German date format "dd.mm.yyyy".
And the time editor uses international 24 hour format "HH:MM:SS".

For the timer switch setting I also include a 'short time format' as "HH:MM" (no seconds) for editing.

If you need it formatted in a different way, please let me know about the desired date (and/or time) formatting in the editor screen.

I think I can include different formatting using "conditional compile" options, so that in the final code you just set a single line at the top of the sketch to a number:

#define DATEFORMAT 0  // 0=Germany 1=USA 2=India or something like that

and the different options are then compiled, dependent on the format setting

But if I should include a different date editing option, I'd need to know the format for it. I'm not able to include all possible options of the world for an initial release of the date/time editing menu.

will be following this to see the logic you are using. One of my first projects was a egg incubator with 28 settable options including setting times and dates using only 3 buttons (up/down/edit) and a 4x20 display. I ended up writing most of the code using switch/case arguments so it will be interesting to see a different approach.

So here comes some code for testing.

No external libraries needed (except those that come with the Arduino IDE) when using the Liquidcrystal library for LCD. Just unpack the folder in the ZIP file into your Arduino sketch folder.

Minimum hardware required for testing is an Arduino board, text LCD display and rotary encoder with button.

Optimum hardware is also an RTC module (DS1307 or DS3231). Set RTC option accordingly if you have or have not a RTC module for testing.

Preconfigured configuration for the LCD is a "LCD Keypad Shield" stacked on an Arduino UNO, the rotary encoder A/B connected to A1/A2 and the button connected to A3.

If you need to change the USEROPTION for different LCD or different pins, I have provided conditional compile options, so you need not modify the original configuration, but you can insert your configuration under "#elif (USEROPTION==2)" or "#elif (USEROPTION==3)" and set the conditional compile accordingly:
#define USEROPTION 1
or
#define USEROPTION 2
or
#define USEROPTION 3

While the program is running the menuState is either
MENUINACTIVE ==> The normal display is active
MENUACTIVE ==> After pressing the button, the menu becomes active, you can switch between items
MENUSELECTED ==> After pressing an item that is editable, the menu editor starts

Currently only three types of editable items are supported:

  • date editor, type 'D'
  • short time editor in HH:MM format, type 'D' and subtype 'S'
  • long time editor in HH:MM:SS format, type 'D' and any other subtype (except 'S')

A menu item of type ' ' (space character) stands for "exit menu".

The editor can finish and save or abort editing without saving the edited value:
OK and save ==> place the cursor on "OK", then press the button
Abort editing ==> rotate the cursor "right out" the LCD display

The "OK and save" option can only be used, if the entered date or time is valid. If the edited value is invalid, the editor will stay active to allow further change of the value until it is valid. That way you are unable to enter invalid time like "25:01" or invalid date as "20.20.2015".

The example program is not yet a fully working "timer switch", but until now these functions are working:

  • setting current date (if using RTC, the RTC date will be updated)
  • setting current time (if using RTC, the RTC time will be updated)
  • setting ON/OFF times for 4 timers (will be saved permanently in EEPROM)

For a fully working timer switch I'd need to add

  • on/off switching logic as a seperate task

Please let me know if you get the rotary encoder menu working in your Arduino and what features you'd like to see next.

Change:
The posted file attachment was faulty and only partly working as expected.
Please download fixed programming example attached to reply #34.

well, that was fast, looks promissing.

I dont have arduino with me yet (in office), so can comment just the code, and replay for your questions.

My preference would be: 2015/08/31_09:56:13 (but you can keep it as it is for now, will play around later)

(in my code it looks exactly as above, below i have a "cursor", the intention is if the cursor moves with rotary, staying at 2015+button press, the encoder will adjust the year...and so...in the end the OK button as yours-very good idea, i like it. 2015/08/31_09:56_OK)

USEROPTIONS is a good idea, but i would rather call this something like INPUTOUTPUTBOARD,
-in my case i have i2c lcd , connected A4,A5, and rotary_A-B-SW on D2,D3,D4
(I dont mind reconnect it to A1,A2,A3) However worth thinking - if we might need analog lines ex irrigation, then probably digital channels would be more welcome.

Unfartunatelly im not a "deep" coder, so might need more time to get clear.

daemons:
My preference would be: 2015/08/31_09:56:13 (but you can keep it as it is for now, will play around later)

(in my code it looks exactly as above, below i have a "cursor", the intention is if the cursor moves with rotary, staying at 2015+button press, the encoder will adjust the year...and so...in the end the OK button as yours-very good idea, i like it. 2015/08/31_09:56_OK)

That line is longer than 16 characters, which is the width of my LCD. With wider LCDs also a date-and-time editing in one line would be an option, if implemented. Currently I cannot provide that.

daemons:
(I dont mind reconnect it to A1,A2,A3) However worth thinking - if we might need analog lines ex irrigation, then probably digital channels would be more welcome.

The USEROPTIONS in the sketch is as it says: You tell what to use. If you want to use I2C LCD, include the library file for use with your I2C LCD. And if you want the encoder pins to be D2, D3, D4, just change them. My example provides a possibility to hold three different USEROPTIONS in the same code, you can easily change between them by changing one line of code. In my case, the LCD is no I2C model but it is in 4-bit parallel mode and needs already 7 digital pins (including backlight pin).

Thanks for sending feedback at least after looking at the code!

Next things to do on my list for the example sketch are probably:

  • add the "timer switch" logic, switching an output by using the RTC time and timer settings
  • add a line editor for boolean configuration values (ON/OFF, true/false, 0/1)
  • add a line editor for numeric configuration values (with 1, 2, 3, 4, 5, etc. digits)

jurs:
Next things to do on my list for the example sketch are probably:

  • add the "timer switch" logic, switching an output by using the RTC time and timer settings
  • add a line editor for boolean configuration values (ON/OFF, true/false, 0/1)
  • add a line editor for numeric configuration values (with 1, 2, 3, 4, 5, etc. digits)

not yet had time to check, will try do so in comming days..

back to your todo list,

will you do that in kind of procedures? or in the code itself?

daemons:
back to your todo list,

will you do that in kind of procedures? or in the code itself?

The most important thing on my to-do-list today is packing bags, as I'm going for a vacation trip to the Mediterranean Sea.

For finishing a timer switch function, this is already done:

  • defined a data structure to hold 4 timers (= 4x on/off per day)
  • editing on/off times
  • saving edited on/off times to EEPROM
  • loading on/off times from EEPROM on power-on

And this has to be done:

  • define a pin for switching
  • set that pin to OUTPUT in setup
  • create a function for switching by time
  • call that function from within the loop()
    The "function for switching by time" has to be non-blocking, meaning that you cannot use "delay()" or any "busy waiting" loops in it.

I should be back again by the last week this month, if you need an example sketch that is further worked out than what I have posted as a rotary menu before.

@ jurs
Sorry for my english , i am dutch.
I like to adjust a DIY bench power supply with a rotary knob.

For now the menu structure i think:

mainmenu: Outputrelais on/off with the button (panic)
Adjust Volt
Adjust Current

submenu Volt -> 5 x preset
-> adjust 0-35 volt
submenu Current -> 5 x preset
->adjust current limiter

Therefor I have setup a nano3 + LCD 2x16 + rotary knob with button.

I found your sketch and a test with that give me a very nice and smooth control feeling. :slight_smile:
I like it.

I have loaded your sketch and edit the LCD and knob pinning.
The start menu is OK.
Then i press button , ive get the next menu started with "Set Date" and if a rotate i get the next items till "Exit".
When i push the button at Ëxit" i return to main menu. All fine.

My problem: I can not change the "Set Date" item or other items in the submenu. :confused:

Can you help me.

Ben