The most important concept with the loop function is that it loops. So, you need to get looping code into your head. Anything you code will go round and round really fast (preferably). The way you are thinking is linear and the fast loop appears like a problem so you have filled it with massive delays to make it slow down and do what you want, one thing after another. This seems intuitive but basically your “human” thinking has broken the microcontrollers (uC) main benefit of machine speed. It can loop thousands of times a second and be responsive to buttons, sensors etc in microseconds. A human-timescale “delay” says to the uC to stop and wait and skip checking the button for a few hundred thousand cycles. What a waste!
There are 2 main concepts to understand when thinking loop.
- timing
- states
Timing must be done, not by delays, but by checking the internal clock (millis) storing a StartTimer variable in your code and then checking it every loop to see if required time has elapsed. The “blink without delay” example explains this in detail. Remember every time through loop the uC is checking the clock but also doing anything else you have coded.
States and state machines are the way you get the uC to remember what bit of code you want it to run otherwise, as you have found it will run the same code over and over again in an endless loop. The simple way to do it is decide how many distinct states your project needs. Eg:
1 waiting for button to be pushed
2 button has been pushed
In the first state all you need to do is continuously loop round checking the buttons. As soon as a button is pushed you need to change the state, so take an appropriately named variable such as “state” and increment it to 1 from 0. Now every time through loop the uC sees that variable is 1 not 0. So it is easy to code; if state ==1 do this new thing.
Next you will need to work on debouncing and detecting the moment a button becomes pushed etc