I am writing a sketch for a MIDI keyboard with up and down octave buttons. I have tried the code with if statements and while statements, but I cannot make the button operate once for every press. I get a continuous stream until I lift the button. I have put the "Serial.println" statements for tracing only.
Once you've got a pushbutton working, you often want to do some action based on how many times the button is pushed. To do this, you need to know when the button changes state from off to on, and count how many times this change of state happens. This is called state change detection or edge detection. In this tutorial we learn how to check the state change, we send a message to the Serial Monitor with the relevant information and we count four state changes to turn on and off an LED.
You need to know what level it was last time you checked as well as this time. If it was HIGH and is now LOW, that's the change to trigger action upon.
Caveat: contact switches like buttons will "bounce" for 2+ milliseconds (dirty buttons mash and rock) when pressed and released. Prepare to learn about debouncing, a necessary lesson!
Debouncing can be handled by looking for changes in state say, every 50ms.
A change in state is either HIGH to LOW or LOW to HIGH.
Assume a switch press is LOW.
When 50ms expires, and we see the lastState was HIGH and now the current State is LOW, we know the switch was pressed; hence we then do what we are supposed to do when the switch is closed.
In the next 50ms, lastState will be LOW and the current state is LOW, hence no change in state, hence we do not do anything this time.
How long before the OP is going to have to learn to Not Use Delay or Blocking Loops when trying to do more than one thing at a time as in watch a button while blinking a led?
That is not an advanced topic, it's what beginners learn to get past being beginners. It's a step past switch transitions and the one before state machines.
The ones it is hard for are the ones who have to UNLEARN "the right way" they learned first then rutted down into.
Do the delay() but don't get married to it, don't invest much time in it because before long you will want to have something running with a pause or stop button and that's when you will find out that delay code prevents that.
For sure, do some things with delay in them just to learn other lessons but keep them small. Any code that does One Thing At A Time works fine with delays and there are lots of projects OTAAT.
With pin state change and all code that works with change you use code that deals with time in the past/previous vs now sense and that is what to learn about... keeping track by using variables to hold and compare was to is. Watch for that and see how it works to do what you want. What to do depends on something changing changing, even the time as in is it lunch time then get lunch!
When you are ready to code for More Than One Thing At A Time, just ask and you will get lots of help!
As the delay() function is known to block the programme flow, a non-blocking timer function is necessary.
As a basis for this, I recommend the BlinkWithOutDelay example from the IDE as the mother of all Arduino timers.
The BWOD example can easily be converted into a timer module that can generally be used for all applications.