Great question! As demonstrated in this video it serves no obvious purpose, and I do not explain this well (likely to avoid going too far off track). But I want to point out that having pacing in this implementation does not have any negative effect either, as it is fast enough to ensure the human operator won’t notice it is being paced. So, there are various excuses I could make for my habit of liking to pace this loop, but I think there are only 2 clearly undeniable reasons I can give. The first is that I use it as a simple method to measure large chunks of time. For example, for a 25ms pacing, I know if I count 20 loops, then about half a second has passed. Obviously, you could use this for all types of things, but often I use it for flashing values on a physical display, or executing a repeat key (see later episodes). The second reason is related to processor usage management, specifically I want to minimize the amount of time spent processing the menu stuff to only as much as it needs to do its job. This opens up a large chunk of processing time which could be spent doing for more process intensive stuff. Let me give an example with some imaginary values. Say your menu loop code takes 1 millisecond to complete, and then your other things to do take at least 1 millisecond to execute a single cycle, if these operations simply ran back-to-back, then 50% of the processor time would be spent on doing the menu code, and only 50% of the time spent on what is likely the core purpose of the device, and that may mean a notable degradation of performance depending on the application. In the case we pace the same menu code at 25 milliseconds, then 1 millisecond is still used for the menu, but the remaining 24 milliseconds (96%) of the time can be used to focus on the actual purpose of the device. Anyway, hopefully I answered your question!
@wildfox19945 ай бұрын
@@ForOurGoodGreat explanation! Thank You! But wouldn't it be even better to execute menu loop only on button change? Like with button interrupt or something? But I guess it would require a completely different approach then the one shown in the video.
@ForOurGood5 ай бұрын
@@wildfox1994 I think you get the point, in fact there are so many different ways do achieve the same results in code, it's really hard to declare that something is the best way to do something or not. But there are a few measures to consider how good a specific coding might be, things like (1) how well it serves the purpose, taking into account performance, stability and functionality (2) how easy it is to maintain/manage/debug the code, and (3) how much effort is required to write the code in the first place. The truth is, this lesson is not great code, but it works, and should be understandable by a wider audience, and therefore get more people to their hoped destination. BTW: Check out my mini-lathe series EP11 to see this code working in a real world application. Also, if you want to see a more advanced version of this menu, check out episode 7 in this series.
@wildfox19945 ай бұрын
@@ForOurGood Maybe it's not a great code but I like how organized and clean it is. My code is often really messy so I'm planning to go through all of Your videos and try all of those examples and hopefully catch some of good coding habits.
@ForOurGood5 ай бұрын
@@wildfox1994 Thanks! Wishing you all the best with your coding endeavours.
@TeslaFactoryАй бұрын
This is by far the best, most well explained tutorial I have found on KZfaq for this topic! Fair dinkum, mate!
@ForOurGoodАй бұрын
@@TeslaFactory Actually it's my most viewed video, so I guess it is a good fit for some people. But taking over 2-years just to get 20K views, plainly indicates that other similar videos must do a far better job for a wider audience. It is what it is! Anyway, I'm always happy to hear that it was useful to someone. So thanks for taking the time to comment!
@zacharyreed85237 күн бұрын
Very much appreciate this video. It cleared up a LOT of my confusion with menus. Well done. Three questions: 1) How would you integrate this menu if there was a home screen on which live sensor data was displayed? E.g., showing present humidity values of a plant, device battery level, etc? In that case, I think a user pressing a button would enter the menu system, and exiting the menu system would default back to the "home screen". 2) How would you integrate user-changeable values within the menus? E.g., user wants to change the refresh rate of the humidity sensor from 5 min to 10 min or the brightness of an OLED. At the very least I know that this would have to be written to eeprom to not be lost on a power-cycle, but the execution of it is a bit fuzzy to me. 3) How would you incorporate a menu system for a screen that could only display a limited number of lines? Say a menu had 6 items, but the user can only see 4 at a time due to OLED limitations?
@ForOurGood7 күн бұрын
@@zacharyreed8523 Thanks for watching and thanks for your questions. 1) The great thing about this menu structure is that there really are not any limitations. If you want to start the application at the operating screen, then just set the menu start point to be the operating screen. You can then just have a button to go to the settings list page (for example). Please see EP6 where I do exactly that for a similar application. 2) I have a number of videos showing how to do just this, so please check them ALL out ;-) 3) I demonstrate how to do this in EP4, EP6 & EP7 (in different flavours) If you watch EP11 of my mini-lathe series, you can see where I use this exact menu structure for a complex graphics display. Unfortunately I have not had the time to do a video on graphics displays, but it is much the same as for the LCD displays (once you get it to the stage of printing text to the screen that is).
@TomLeg Жыл бұрын
You discuss things I haven't seen anywhere else ... I can't imagine why there are not more views & up-votes!
@ForOurGood Жыл бұрын
Thanks for the positive message. The problem is likely partially mine, because I don't use social media or other methods to promote the content. Also the lack of breaking things, blowing things up or cute 🦊dogs or 🐱kittens, probably does not help either.. It could also simply be that the content is just not good enough, so if that is the case, fair enough. But looking at the 💹statistics, the click-thru rate, time watched, and repeat views, is actually not that bad, so it can't be terrible. The stats also clearly show the KZfaq algorithm throttles carefully how many impressions I get, so to ensure the content is not viewed too much, regardless of the click-thru rate or other performance measures. I guess that is the way the KZfaq business model works nowadays, better to keep as many channels as possible under the ad-share revenue threshold. I suspect this all happened since they changed the policy to put ads on all content, regardless of if they need to share the revenue. For me I don't care too much about the 5 or 10 bucks revenue they might need to send me, but it's too bad I spend time making content, that I hoped would help people, but really only a few people will even get a chance to see it. But helping a few is better than helping none, so ultimately I am ok with it!
@snotabe Жыл бұрын
@@ForOurGood I appreciate you creating these, they help me build my photo macro rail, I am not there yet, but this content motivates me! Thanks
@ForOurGood Жыл бұрын
@@snotabe photo macro rail project sounds cool! FYI: New programming video coming out soon. Thanks for taking the time to leave a comment.
@snotabe Жыл бұрын
@@ForOurGood Yes actually, the macro photography started the journey for me because I need to move the focus point of the camera a fraction of a millimeter and then stack the images taken. Then I thought of a stepper motor to move it and arduino came to mind and I had to learn all that. So much fun. Looking forward to your next video! Much appreciated.
@leandroredondo4567 Жыл бұрын
Não falo inglês, ( Brazilian ) mas com a tradução sua explicação foi a melhor encontrada até agora sobre menu, parabéns pelo seu trabalho e pelo tempo dedicado. Obrigado
@ForOurGood Жыл бұрын
I am happy to hear it was useful to you, even with translation! Thanks very much for the comment and good luck with your programming!
@javierbarrera49354 ай бұрын
Amazing job BTW on the whole series. I’ve done A LOT of YouTubing to learn Arduino programming and HANDS DOWN, going through your series has been awesome. You plough through so many fundamental concepts and glue them all together in a totally logical and systematic way. I jumped into the whole Arduino/microcontroller world from scratch about 10 months ago and yours is the only series where I go back and review various bits and pieces over and over to extract everything you’ve crammed in here. Your command of coding is deep and your methods super sound. I’m now on PlatformIO and will never look back. I do all my work now on ESP32’s since it’s just such a stronger processor and I don’t have to deal with the first obstacle I hit in Arduino’s related to performance. Maybe think of adding ESP32 related capabilities in the future (BT and Wifi world). Great Job!!!
@ForOurGood4 ай бұрын
Well that has to be the best comment I ever received for my programming series, hands down! Actually, I’m always happy to hear that these videos are helping people like yourself, as that has always been my hope. Unfortunately, making these videos is a real slog, I guess it is just the way it is when making these types of videos. It’s only the fact that about 50% of my audience watch time comes from these handful of videos, that really keeps me making them. I do plan to do a couple of new programming videos in the coming months, topics will likely include using a menu with a rotary encoder, using a graphics-based display, and making a real-time web interface using a ESP32. If you comment on a specific comment or topic you are interested in, I will always keep that in mind too. Your choice of using a ESP32 is fully understandable, after using one in my solar project I grew a new respect for it. It does have its down sides however, especially the terrible ADC and limited finicky I/O’s. The great thing about with working in PIO and Arduino, is that it is fairly easy to work with a mix of different microcontrollers, and apply which ever one makes the most sense for your given project. Anyway, wish you the best of luck with your programming!
@javierbarrera49354 ай бұрын
Thanks for taking time to respond. It’s actually the programming and the various tips and tricks you stumble across as you work the problem that provide some of the most value VS the actual video title. You mention about another series on programming, but i would say you’ve already done the series! It just happens to be called “Menus” instead of programming being the focus and the menu project is simply a consequence. I’m out of step here with comment here because really the gems are spread out across the whole series. I think it’s good you don’t provide the code because it forces a better understanding by applying it directly as opposed to copy/paste. I’m not finished my project yet (camping van control console for FastLED light strips + environment sensors + accelerometer based LED van “level” when camping) - but I’ll tell you I wouldn’t be where I’m at without your vids (and ChatGPT!)
@johnparry35735 ай бұрын
Thanks for making this video. I'm still learning to program an Arduino and I'm currently working on a project that requires menus, so I found this one to be very informative.
@ForOurGood5 ай бұрын
You're very welcome, I am glad to hear it was useful to you! 😊
@TankTurk Жыл бұрын
As a relatively newbie, I found your video very informative and well explained. I found your sketch in a reply below and copy/pasted it and it works great. This should help me write a menu system for my project I am working on. Thank you so much, subscribed to your channel
@ForOurGood Жыл бұрын
Glad to hear it was helpful for you! Thanks for the comment, and thanks for subscribing ;-)
@kijijikhalid601 Жыл бұрын
this is an orthodox way to explain and build a menu, but it's the best ever I could meet. Thank you
@ForOurGood Жыл бұрын
Happy to hear it helped you. Thanks for commenting! 🙏
@stephanc7192Ай бұрын
Great video
@ForOurGoodАй бұрын
@@stephanc7192 Hey thanks! I am glad you found it useful 😃
@ottoklaasen211 Жыл бұрын
Great demo, I made it and it works fine. After that I modified the code from serial to TFT. Problem is that now the amount of used memory goes up to 47%. So my conclusion is better to use an ESP32 as it has more memory. The nano is imo a bit too small in case you use a TFT display
@ForOurGood Жыл бұрын
Thanks! and yes, your absolutely correct, if you are using a graphical display, you definitely want to be using a STM32 or ESP32 both for speed and programming space reasons. If you checked out my mini lathe series you will have seen the controller I made there, in that case I completely filled the 128MB of program space with a big part of that being fonts alone. On the other side of the scale, I have just finished up a project using ATtiny1616 with a LCD display, even then I could only just make it fit and feel satisfied using all of the 16KB program space. So, at the end of the day, it is a matter of the old horses for courses, all of these chips work well when applied to the right application.
@RBA--ROHITKUMAR Жыл бұрын
Great learning sir ,...Thanks 👍👍
@chrisross1408 ай бұрын
Thank you for this. As I'm still learning I was wondering if rather than adding a hundred pages to clear the screen use the button up to clear the screen?
@ForOurGood8 ай бұрын
I am sorry, I am not sure I follow your question correctly, so I will avoid answering directly. But to be honest, even when you're learning, it is still worthwhile to try different things, so if you think it will work then give it a go! If it does not work , then you have not wasted your time, you have actually learnt something. Often in code, there really are so many ways to achieve the same objective, it is nearly impossible to say what is the right or wrong way to do something. But if you manage to improve the user experience, or operation of a given system, then that's called progress! Enjoy your coding and thanks for taking the time to leave a comment ;-)
@claudedada6504 Жыл бұрын
Great lesson ever!!! I needed something like this because i'm trying to put a circuit with DS1307 and an OLED screen to make a weekly alarms for switching various things but to be honest i didn't understand much . I would like to ask if you could make another simple lesson on this topic. thanks
@ForOurGood Жыл бұрын
Thanks for the comment and idea! Actually I think I have a couple of those RTC modules that I bought but never used. I will have a think about a lesson using that. For now check out a couple of the other episodes which will help you with a few more basic concepts. Also, episode 6 is pretty epic, as it goes through from start to finish on how to build a real world application. The idea is to help people like yourself to build up enough skills so you can really make anything you like. Good luck with your endeavours!
@john24784 ай бұрын
Thanks for the video. I am new to Arduinos and to programming and I have been trawling though looking for ideas to try and hit on your menus. It is also very pleasing to see a super actual project like your lathe project, so we all know what is possible! I am currently using a Nextion screen and have managed to get the screen to talk to the arduino and send the signals back to the screen. You did say that you were working on an episode with a screen type like this? As an observation you have to spend a lot of time with the lcd displaying programming button press scenarios. If you have selected the menu items by pressing on the touch screen I suppose all this work is not required? John
@ForOurGood4 ай бұрын
I am glad you liked the video! They are a bit of a hassle to make, so I only release them on the occasion, but they do prove to be surprisingly popular. The graphics types of displays unfortunately adds a pretty complex layer to deal with, with so many ways of implementation, and so many different display types. Honestly, I sort have been avoiding it, and instead focusing on more basic and common stuff to hopefully give people a foot up regardless of the environment they are working in. Even so, I do still plan to do a graphics-based display in the near(ish) future, I just need to think of a good generic/simple way to teach it. Using a touch screen actually can add a different sort of problems compared to physical buttons, but there is allot of common stuff too, so in fact what I teach should be mostly applicable to touch screen buttons too. Touch screens definitely have their place, but allot of the cheap graphics displays touch screens seem pretty clunky and not so accurate. There is also the matter of the need to touch the display, which can obscure it, and make dirty or damaged if not implemented in a smart way, in fact this is why I did not use the touch screen that is on the display of my mini-lathe. Actually, I have been getting a couple of requests lately to demonstrate a rotary encoder type control to navigate the menu, so I think I will try do a quick video on then next.
@markus43348 ай бұрын
Thank you so much for specific details and most you. You can possibli help to get my degree.
@trailranger6602 Жыл бұрын
Loved this! Thank you.
@ForOurGood Жыл бұрын
Your welcome. Thanks for taking the time to comment! ☺️
@codewithdaniel-1 Жыл бұрын
Wow this is golden info 💖...I have watched and remade the same menu and works perfectly...I have some questions though.. 1.i wanted to implement the same with freertos but freertos tasks does not return if so it has to be deleted . How do I go about it Incase I want to go back na cancel the task without deleting it?. Second ...can you make a video taking input chars from button i.e you can enter a name using a button .. Thanks this video has been all that I was searching for 🙏.
@ForOurGood Жыл бұрын
Hey thanks for the comment and questions, glad to hear it was useful for you. 1. I have not used freetos before so I cant give an exact answer. I have however some pretty serious experience with multi-threaded programming in the PC domain, so I will try to answer the questions from that perspective. If this is just a menu then there seems to be no reason you would need to leave the primary thread for navigating the menu tree. The menu could however interact with other threads, launching, pausing, terminating them, or exchange data as need be. Sorry for the abstract answer. 2. I provide the basic information on how you might do with with up and down buttons in my EP3 of this series. Possibly I can expand that to show as character input if you need. Have a try yourself, 90% of the solution is in that video. There are also obviously so many ways to do text input interfaces, maybe I will touch on those in the future, but for now trying to keep it simple.
@krishnapatel23545 ай бұрын
Does this work with a 2.8” ILI9341 LCD (No touch) screen using a raspberry pi pico? And do I need the exact same buttons or are any buttons going to work? Sorry I'm new to this so I'm not sure
@ForOurGood5 ай бұрын
Please see my mini-lathe series where I show this menu structure being useing with a 2.4" ILI9341 LCD. So yes, the basic concept I show how to structure a menu will work for you, in fact I expect the concepts shown here will work on most any environments. But this lesson really only shows how to do the basic branching and managing button inputs, it does not show how to implement on a physical display. Some of my later lessons do that with a simple LCD display, but I have not demonstrated it being used with a ILI9341 driver. Likely the menu I teach in EP7 would be most easiest to adapt to a ILI9341 assuming you understood the basics of the driver. Good luck!
@Dandelionclover Жыл бұрын
Awesome video. It’s helped a lot. But I am currently stumped (I’m a noob). I’m using SPI. Without the switch case, I can seamlessly scroll through my main menu icons, highlighting the selected one. When I introduce the switch case for multiple sub menus and the while loop, it of course has to update the entire display with every click of the button. Not smooth looking at all. Is there a way to use switch case without having to update display?? Without all the loop and update display stuff, the main menu just refreshes like every .25 seconds. I’m trying to achieve the smoothness of the menu icon selection I had before while using switch case
@ForOurGood Жыл бұрын
So… there are probably too many unknowns here for me to answer accurately, but let me have a go. Maybe you have kept the "ClearScreen" call within the "UpdateDisplay" section. This is only needed here for the Serial Terminal type display were the only way to update the display is to clear it first. For a physical display, you only want to clear the screen when the system first boots (in Setup) or sometimes as you enter a given menu subroutine (before the loop). With that said, as you modify values and update the display you will want to make sure no unwanted stuff is left over. The best way to do that is to make sure the old info is fully covered up when you write the new value. Clearing the old value before you write the new one is also an option, but this will cause a little flicker, so not the best way. Most displays will sequentially write values to the screen, so even if you write the same value again, it should cause no flicker at all, and even writing a new value over an old one should be pretty smooth. I do suggest you write any static parts of the display before you enter the main loop, you don’t want to be constantly updating that for no reason. If you have a graphics heavy display, as I had with my mini-lathe project “run lathe” screens, you may want to avoid re-writing something things that have not changed. To do this you will need to add a tracking variable to store how the last value was updated to the screen, and then only write a new value to the screen when the value actually changes (then of course save again the newly updated value). For more information generally, please see episode 4 in this series where I show how this menu system can be used with a LCD display (plus other episodes in this series could be of help). Also, check out episode 11 of my mini-lathe series to see a fairly heavy graphical display implement with this menu system, without any flicker.
@Dandelionclover Жыл бұрын
@@ForOurGood Thank you so much! I can't wait to jump into the other videos and try to figure this out. I think my issue is having to deal with the static display parts. I just ran the code without the text and the icons highlighted seamlessly again with the button presses. You've really steered me in the right direction and got me thinking critically. Greatly appreciate you taking the time out!
@ForOurGood Жыл бұрын
@@Dandelionclover Happy to hear it helped you. Good luck with your programming endeavours!
@odiliomartinez68112 ай бұрын
i found it very helpful but had trouble reading off the screen...the code for me keeps flashing so fast so something is wrong with the millis, unsure if i have it wrong...would you have a copy of the code that i can compare against
@ForOurGood2 ай бұрын
You can find the code as a response to one of the older comments below! Hope that helps.
@odiliomartinez68112 ай бұрын
@@ForOurGood Thank you, it must have been a syntax error. question, how can i get the program to do something base on the screen option it landed...i'm rather new to this. so how would the program know the choice the user made..i want to be able to execute code based on let's say the submenu choice 1?
@ForOurGood2 ай бұрын
Sorry, I don't think I have a helpful answer to this question. For the very basics, maybe some other channels have a better video, there are also many other good resources available out there to learn from. I hope you succeed in what you are trying to do!
@bombasticcat11 ай бұрын
ill probably just copy paste the code and just change the code a bit for my usecases. Didnt learn anything but it will work
@ForOurGood11 ай бұрын
Whatever works for you, learning is also a choice. Hope it works well for your use cases!
@ericrandall92862 жыл бұрын
I really appreciate your thorough explanations, but I can't compile what I've integrated. Would you be so kind as to post the final code? Thank you! I especially like your double checking of button state-- I think that will solve a problem I've been having.
@ForOurGood2 жыл бұрын
Wow! A comment! Thanks soo much ;-) At least I know that the video might have actually been useful to someone. I don't have anyway to post the entire code at this time. But let me try an experiment by sending it as a comment reply to you. Thank again for the comment.
@ForOurGood2 жыл бұрын
HERE IS PART#1 #define ROOT_MENU_CNT 3 #define SUB_MENU1_CNT 4 #define SUB_MENU2_CNT 5 #define SUB_MENU3_CNT 2 // setup the emum with all the menu pages options enum pageType {ROOT_MENU, SUB_MENU1, SUB_MENU2, SUB_MENU3}; // holds which page is currently selected enum pageType currPage = ROOT_MENU; // selected item pointer for the root menu uint8_t root_Pos = 1; // constants holding port addresses const int BTN_ACCEPT = A0; const int BTN_UP = A2; const int BTN_DOWN = A1; const int BTN_CANCEL = A3; // ======================================================================================= // || SETUP || // ======================================================================================= void setup() { // init the serial port to be used as a display return Serial.begin(115200); // setup the basic I/O's pinMode(BTN_ACCEPT, INPUT_PULLUP); pinMode(BTN_UP, INPUT_PULLUP); pinMode(BTN_DOWN, INPUT_PULLUP); pinMode(BTN_CANCEL, INPUT_PULLUP); } // ======================================================================================= // || MAIN LOOP || // ======================================================================================= void loop() { switch (currPage){ case ROOT_MENU: page_RootMenu(); break; case SUB_MENU1: page_SubMenu1(); break; case SUB_MENU2: page_SubMenu2(); break; case SUB_MENU3: page_SubMenu3(); break; } } // ======================================================================================= // || PAGE - ROOT MENU || // ======================================================================================= void page_RootMenu(void) { //flag for updating the display boolean updateDisplay = true; // tracks when entered top of loop uint32_t loopStartMs; //tracks button states boolean btn_Up_WasDown = false; boolean btn_Down_WasDown = false; boolean btn_Accept_WasDown = false; //inner loop while (true){ // capture start time loopStartMs = millis(); // print the display if (updateDisplay){ // clear the update flag updateDisplay = false; //clear the display clearScreen(); //menu title Serial.println(F("[ MAIN MENU ]")); //print a divider line printDivider(); // print the items printSelected(1, root_Pos); Serial.println(F("Sub Menu One")); printSelected(2, root_Pos); Serial.println(F("Sub Menu Two")); printSelected(3, root_Pos); Serial.println(F("Sub Menu Three")); Serial.println(); Serial.println(); //print a divider line printDivider(); } // capture the button down states if (btnIsDown(BTN_UP)) {btn_Up_WasDown = true;} if (btnIsDown(BTN_DOWN)) {btn_Down_WasDown = true;} if (btnIsDown(BTN_ACCEPT)) {btn_Accept_WasDown = true;} //move the pointer down if (btn_Down_WasDown && btnIsUp(BTN_DOWN)){ if (root_Pos == ROOT_MENU_CNT) {root_Pos = 1;} else {root_Pos++;} updateDisplay = true; btn_Down_WasDown = false; } //move the pointer Up if (btn_Up_WasDown && btnIsUp(BTN_UP)){ if (root_Pos == 1) {root_Pos = ROOT_MENU_CNT;} else {root_Pos--;} updateDisplay = true; btn_Up_WasDown = false; } //move to the selected page if (btn_Accept_WasDown && btnIsUp(BTN_ACCEPT)){ switch (root_Pos) { case 1: currPage = SUB_MENU1; return; case 2: currPage = SUB_MENU2; return; case 3: currPage = SUB_MENU3; return; } } // keep a specific pace while (millis() - loopStartMs < 25) {delay(2);} } } // ======================================================================================= // || PAGE - SUB MENU1 || // ======================================================================================= void page_SubMenu1(void) { //flag for updating the display boolean updateDisplay = true; // tracks when entered top of loop uint32_t loopStartMs; //tracks button states boolean btn_Up_WasDown = false; boolean btn_Down_WasDown = false; boolean btn_Cancel_WasDown = false; // selected item pointer uint8_t sub_Pos = 1; //inner loop while (true){ // capture start time loopStartMs = millis(); // print the display if (updateDisplay){ // clear the update flag updateDisplay = false; //clear the display clearScreen(); //menu title Serial.println(F("[ SUB MENU #1 ]")); //print a divider line printDivider(); // print the items printSelected(1, sub_Pos); Serial.println(F("The First Item")); printSelected(2, sub_Pos); Serial.println(F("The Second Item")); printSelected(3, sub_Pos); Serial.println(F("The Third Item")); printSelected(4, sub_Pos); Serial.println(F("The Forth Item")); Serial.println(); //print a divider line printDivider(); } // capture the button down states if (btnIsDown(BTN_UP)) {btn_Up_WasDown = true;} if (btnIsDown(BTN_DOWN)) {btn_Down_WasDown = true;} if (btnIsDown(BTN_CANCEL)) {btn_Cancel_WasDown = true;} //move the pointer down if (btn_Down_WasDown && btnIsUp(BTN_DOWN)){ if (sub_Pos == SUB_MENU1_CNT) {sub_Pos = 1;} else {sub_Pos++;} updateDisplay = true; btn_Down_WasDown = false; } //move the pointer Up if (btn_Up_WasDown && btnIsUp(BTN_UP)){ if (sub_Pos == 1) {sub_Pos = SUB_MENU1_CNT;} else {sub_Pos--;} updateDisplay = true; btn_Up_WasDown = false; } //move to the go to the root menu if (btn_Cancel_WasDown && btnIsUp(BTN_CANCEL)){currPage = ROOT_MENU; return;} // keep a specific pace while (millis() - loopStartMs < 25) {delay(2);} } } // ======================================================================================= // || PAGE - SUB MENU2 || // ======================================================================================= void page_SubMenu2(void) { //flag for updating the display boolean updateDisplay = true; // tracks when entered top of loop uint32_t loopStartMs; //tracks button states boolean btn_Up_WasDown = false; boolean btn_Down_WasDown = false; boolean btn_Cancel_WasDown = false; // selected item pointer uint8_t sub_Pos = 1; //inner loop while (true){ // capture start time loopStartMs = millis(); // print the display if (updateDisplay){ // clear the update flag updateDisplay = false; //clear the display clearScreen(); //menu title Serial.println(F("[ SUB MENU #2 ]")); //print a divider line printDivider(); // print the items printSelected(1, sub_Pos); Serial.println(F("The First Item")); printSelected(2, sub_Pos); Serial.println(F("The Second Item")); printSelected(3, sub_Pos); Serial.println(F("The Third Item")); printSelected(4, sub_Pos); Serial.println(F("The Forth Item")); printSelected(5, sub_Pos); Serial.println(F("The Fifth Item")); //print a divider line printDivider(); } // capture the button down states if (btnIsDown(BTN_UP)) {btn_Up_WasDown = true;} if (btnIsDown(BTN_DOWN)) {btn_Down_WasDown = true;} if (btnIsDown(BTN_CANCEL)) {btn_Cancel_WasDown = true;} //move the pointer down if (btn_Down_WasDown && btnIsUp(BTN_DOWN)){ if (sub_Pos == SUB_MENU2_CNT) {sub_Pos = 1;} else {sub_Pos++;} updateDisplay = true; btn_Down_WasDown = false; } //move the pointer Up if (btn_Up_WasDown && btnIsUp(BTN_UP)){ if (sub_Pos == 1) {sub_Pos = SUB_MENU2_CNT;} else {sub_Pos--;} updateDisplay = true; btn_Up_WasDown = false; } //move to the go to the root menu if (btn_Cancel_WasDown && btnIsUp(BTN_CANCEL)){currPage = ROOT_MENU; return;} // keep a specific pace while (millis() - loopStartMs < 25) {delay(2);} } }
@ForOurGood2 жыл бұрын
HERE IS PART#2 (PS: It has been a while since I did this, so I am not sure this is the right code. Let me know if it works for you!) // ======================================================================================= // || PAGE - SUB MENU3 || // ======================================================================================= void page_SubMenu3(void) { //flag for updating the display boolean updateDisplay = true; // tracks when entered top of loop uint32_t loopStartMs; //tracks button states boolean btn_Up_WasDown = false; boolean btn_Down_WasDown = false; boolean btn_Cancel_WasDown = false; // selected item pointer uint8_t sub_Pos = 1; //inner loop while (true){ // capture start time loopStartMs = millis(); // print the display if (updateDisplay){ // clear the update flag updateDisplay = false; //clear the display clearScreen(); //menu title Serial.println(F("[ SUB MENU #3 ]")); //print a divider line printDivider(); // print the items printSelected(1, sub_Pos); Serial.println(F("The First Item")); printSelected(2, sub_Pos); Serial.println(F("The Second Item")); Serial.println(); Serial.println(); Serial.println(); //print a divider line printDivider(); } // capture the button down states if (btnIsDown(BTN_UP)) {btn_Up_WasDown = true;} if (btnIsDown(BTN_DOWN)) {btn_Down_WasDown = true;} if (btnIsDown(BTN_CANCEL)) {btn_Cancel_WasDown = true;} //move the pointer down if (btn_Down_WasDown && btnIsUp(BTN_DOWN)){ if (sub_Pos == SUB_MENU3_CNT) {sub_Pos = 1;} else {sub_Pos++;} updateDisplay = true; btn_Down_WasDown = false; } //move the pointer Up if (btn_Up_WasDown && btnIsUp(BTN_UP)){ if (sub_Pos == 1) {sub_Pos = SUB_MENU3_CNT;} else {sub_Pos--;} updateDisplay = true; btn_Up_WasDown = false; } //move to the go to the root menu if (btn_Cancel_WasDown && btnIsUp(BTN_CANCEL)){currPage = ROOT_MENU; return;} // keep a specific pace while (millis() - loopStartMs < 25) {delay(2);} } } // ======================================================================================= // || TOOLS - DISPLAY || // ======================================================================================= void printSelected(uint8_t p1, uint8_t p2){ if(p1 == p2){ Serial.print(F("--> ")); } else { Serial.print(F(" ")); } } void clearScreen(void){ for (uint8_t i = 0; i < 100; i++) {Serial.println();} } void printDivider(void){ for (uint8_t i = 0; i < 40; i++) {Serial.print("-");} Serial.println(); } // ======================================================================================= // || TOOLS - BUTTON PRESSING || // ======================================================================================= boolean btnIsDown(int btn){ return digitalRead(btn) == LOW && digitalRead(btn) == LOW; } boolean btnIsUp(int btn){ return digitalRead(btn) == HIGH && digitalRead(btn) == HIGH;
@ericrandall92862 жыл бұрын
@@ForOurGood you are awesome! Thank you! I'll study it in the morning. As button debounce is such a hot topic, I think it you did a video on just the way you handle debounce by checking up and down states, it would be very popular! Thanks again! Eric
@ForOurGood2 жыл бұрын
Thanks for the feedback, I will definately take it on board. I hope the code works and solves your problem.
@jasenolan7357 Жыл бұрын
This is a great video mate! I'm currently trying to write a program to control a stepper for a Galvo laser engraver Z height. I have all the Linear encoder stuff working but was looking for a way to select a lens (that defines a required Z height) on an OLED screen. Would you be willing to share this sketch so I don't have to re-write everything from the video? Then i can get into re-writting the menus for the 1306 display. I am looking forward to watching your other videos too, as ideally I'd like to be able to select a lens, then allow the user to input a specified part height and automatically add that to the required Z height to automatically move the lens to the correct total height as read by the linear encoder. Be more than happy to share my code if it's something you're interested in.
@ForOurGood Жыл бұрын
Thanks for your question. Generally I don't give out the raw code as the intention of these videos are educational, and typing something in is a good way to learn (probably not appreciated by some). In any case, for this menu, I did actually provide the raw code in a response a comment to Eric Randall, you can copy and paste it from there. (Must had been a moment of weakness 🤣)
@claudedada6504 Жыл бұрын
I forgot about the circuit i want to acces the variables via buttons where i can modify them . is it possible to get lessons from you? i will pay for it bcos i'm desperate of learning arduino programming...
@ForOurGood Жыл бұрын
I think I already have episodes on my channel that cover what you need, go check them out and see how you go! FYI: Everything is free here, of course you don't need to pay and not would I accept it! In fact, to-date, this channel has never earned a single cent.
@Lew1147 күн бұрын
Don’t you need to use interrupts?
@ForOurGood7 күн бұрын
@@Lew114 Not, not for this method. Generally I try to avoid interrupts, using them only when they are absolutely necessary.
@mafhper10 ай бұрын
Thanks ❤
@khalief_. Жыл бұрын
where is the circuit?
@ForOurGood Жыл бұрын
There is no need for a circuit really, it is very very simple. Just connect 4 buttons to the inputs you want to use. The buttons should all be connected to switch to Gnd. Thanks for your question!
@boukadidahamza8116 Жыл бұрын
it's another comment xD .. thanks too much for the 44 min of explanations that's was too awesome ... i got a educational project with an oled i appreciate if i can get some help at least some tips ..
@ForOurGood Жыл бұрын
Yay!! A Comment!! my favorite thing ;-) Please tell me the model of the OLED if you can, and I will see what I can do.
@boukadidahamza8116 Жыл бұрын
@@ForOurGood can u imagine that i don't know what the hell is the model but i've tried the adafruit_SSD1306 and didn't work well for me and when i tried the u8glib and u8g2 libraries it worked for me using the U8GLIB_SH1106_128X64 it worked perfectly but the instructions and the functions used was hard to understand cause i'm new and didn't find something that helped me until i met u xD 😂😂
@riteshpradhan9328 Жыл бұрын
One of the best nd i guess just only nd the best explaination i have got i need a help m creating a project using esp8266 wifi so i want menu items as all the scanned nearby SSID how could i do that any idea
@ForOurGood Жыл бұрын
Hi there thanks for your question. I don't have any experience with getting SSID list using ESP8266, so I am sorry I can't help with that. However if you figure out how to get the SSID list, then you could modify this menu system to show that list as your menu items. Good luck!
@riteshpradhan9328 Жыл бұрын
m trying ... i will let u know as soon as possible
@riteshpradhan9328 Жыл бұрын
@@ForOurGood i got it to work and its work but one thing m stuck now that is when printing a lots of menu item more than visible part of tft how to impliment menu scrolling up when cursor went at button of visible part of display btw m using tft_espi library with ST7735 128*160 Display
@ForOurGood Жыл бұрын
@@riteshpradhan9328 I am glad to hear you got it to work. Please see episode 4 of this series where I show how to adapt this same menu to a small 16x2 char display. I hope it helps!
@ukesharyal Жыл бұрын
Can you tell how you did make those block separator comments ? Is there any tools online !
@ForOurGood Жыл бұрын
Thanks for your question. I simply just manually type those blocks in once, then copy and paste to reuse them to save time. I am not aware of any specific tools for such, but that doesn't mean they don't exist!
@friendryan6 ай бұрын
wish youd shown us best practice
@ForOurGood6 ай бұрын
Thanks for subscribing and the feedback! Not making excuses, but I am fully self-taught, so I probably won't teach as you might be in university. But to be honest, when I look at the code written by those university trained, I find it pretty awful to follow. But I think if people are here and watching my stuff, they are probably not looking for university style training anyway, hopefully they just like coding, and get some satisfaction when they achieve what they were hoping to achieve. This first episode was intentionally raw and simple, and thankfully that seems to have worked as it well viewed, some of my newest episodes introduce some higher level concepts (and are less viewed) and are better structured. If you have the time, then check them out!
@teunlangebeeke8939 Жыл бұрын
THANK YOUUUUU
@ForOurGood Жыл бұрын
Your very welcome!
@johniekemon57487 ай бұрын
Your voice sound familiar, are you the guy from Asianometry...?
@ForOurGood7 ай бұрын
Nope, this is my only channel.
@mengweiting9044 Жыл бұрын
Does this code work for 16x2 LCD display?
@ForOurGood Жыл бұрын
Yes it can, and in episode 4 of this series I demonstrate this, go check it out! Actually this menu method can be adapted to nearly any display scenario. Thanks for your question!
@joechan823110 ай бұрын
Where can I get your code to practice?
@ForOurGood10 ай бұрын
Thanks for your question. Generally I don't give out the raw code as the intention of these videos are educational, and typing something in is a good way to learn (probably not appreciated by some). In any case, for this menu, I did actually provide the raw code in a response a comment to Eric Randall, you can copy and paste it from there. (Must had been a moment of weakness 🤣)
@RBA--ROHITKUMAR Жыл бұрын
Sir , can you plz help to creat a menu in Arduino ide .... For h Home automation like by timer system and mannual select by inputs to output . #main menu (Auto Run and Manual Run ) .. #Manual contain ( 4 devices to run by selecting ) Auto ( contain 4 devices run but by setting time menu with them and run according to set time after one another ) .
@ForOurGood Жыл бұрын
Hi there and thanks for your enquiry! Your idea sound very interesting and I will add it to my considerations for future lessons. In general I am trying to help people with the skills needed so they can be creative and solve problems for themselves, so most of my lessons focus on technique and not simply providing the code listings. Thanks again for your comment & support!👍
@RBA--ROHITKUMAR Жыл бұрын
@@ForOurGood Sir this vedio helped me a lot to learn ,.. But I am facing trouble in creating menu for I2C LCD display and it's settings of time to run outputs
@RBA--ROHITKUMAR Жыл бұрын
@@ForOurGood Thanks for your reply
@ForOurGood Жыл бұрын
@@RBA--ROHITKUMAR What is the model of the I2C LCD display you are using? In episode 4 I do cover using the LCD display with a PCF8574 I2C interface, but I did not have the PCF8574 interface myself so I have not tested it myself. Can you get the display to work at all with a basic test?
@RBA--ROHITKUMAR Жыл бұрын
@@ForOurGood PCF8574 I2C module with 16*2 LCD DISPLAY and facing problem in creating time editor menu
@Hsrt767.....93 Жыл бұрын
bro can you explain how to edit a variable using a keypad or pushbutton and print in real-time on an LCD using arduino.
@ForOurGood Жыл бұрын
I think I cover the editing the variable with the menu push buttons in episode 3 of this series, let me know if that is what you wanted to know. As for the LCD display, maybe I can show that in the next episode. Actually the menu works much the same, but the methodology for when and how to update the display is different of course. There are also generally 2 types of LCD displays, one is primarily alpha numeric (very easy) and the other graphics matrix display. Let me know which type of display you want to learn first, or if you are thinking of using a particular model then let me know the model so I can see if I have something similar on hand. Thanks for the comment and question!
@codewithdaniel-1 Жыл бұрын
Use LCD or TFT display
@Hsrt767.....93 Жыл бұрын
@@codewithdaniel-1 using lcd display
@ForOurGood Жыл бұрын
@@Hsrt767.....93 if you already have a LCD display you are thinking to use, then please give me the model number or info for my reference
@Hsrt767.....93 Жыл бұрын
@@ForOurGood pcf8574(0*27,16*2)
@rubancostror5061 Жыл бұрын
Sir, how to add the Back option in aurdino code
@ForOurGood Жыл бұрын
Hi there. Thanks for your question. Unfortunately I do not understand the meaning very well. If you wish, please edit the question to provide a little more background about what you would like to know.
@pakta936 ай бұрын
Source code.?
@ForOurGood6 ай бұрын
You can find it in a response to an existing comment. Enjoy!
@electronicsideas1361 Жыл бұрын
can u share code
@ForOurGood Жыл бұрын
The code is already included in a reply to one of the comments below. Please check it out.
@electronicsideas1361 Жыл бұрын
@@ForOurGood CODE NOT WORKING PLEASE HELP. MANY ERRORS
@ForOurGood Жыл бұрын
@@electronicsideas1361 Watch the video carefully, and try harder! Everyone else can make it work without any problems, you need to persist to learn. The idea of my videos are to learn. There are also many other videos by other people out there who describe how to make menus. Consider looking at those videos too if my video does not work for you. Good Luck!!
@user-mk6pt5no7t10 ай бұрын
I was following your step but you jumped from the very important detail. This was when you fix the Cancel setting. I think you are hiding something with an acting of teaching. Give it all if you are teaching.
@ForOurGood10 ай бұрын
The Cancel button is shown at 39:30. Everything is shown there and nothing is hidden, but I admit it is shown a little bit too fast in that section, sorry about that. Please press pause to see the details, this section is actually very simple. I cover this menu again in many other videos too, please check it there too if you want to learn more. Good luck with your learning and you are very welcome, and thanks for your feedback!
@sltechguy9422 Жыл бұрын
its great tutorial,can you share the code?
@ForOurGood Жыл бұрын
Thanks for the question, I get this one a lot. Please check the other comments to find the source code.
@sltechguy9422 Жыл бұрын
thanks for your repply brother......
@ForOurGood Жыл бұрын
@@sltechguy9422 your very welcome!
@khalief_. Жыл бұрын
mine is not working, it says: Sub Menu Three ---------------------------------------- A i⸮⸮⸮⸮Y ⸮⸮I⸮⸮⸮ if i try to upload it again it says the same thing edit: and I uploaded parts 1 and 2 together (I included the code you answered below) is that related?
@ForOurGood Жыл бұрын
So it looks like it is actually working, because it is running the section to print the main menu display. It looks like the top part of the menu is simply being lost, likely because of the way your serial monitor is configured. Try the down button a few times, if the screen refreshes and the menu selection arrow arrives at the Sub Menu Three item, then that will prove it is a problem with your serial monitor display. Good luck 🤞