Buttons and other electro-mechanical inputs (comments)

If you have any comments or feedback on either:

Buttons and other electro-mechanical inputs (introduction)

Buttons and other electro-mechanical inputs (advanced)

Please post them as replies here.

Thank you.

Any comment on the old school RC switch debounce circuit ?

R-C-Debouncing.png

R-C-Debouncing.png

Yes.

I considered putting something in and I was indeed asked by one of my reviewers if I should include something along those lines. I decided that my tutorial is about what you do now, not what you might have done many years ago. My tutorial is not intended to be a history lesson.

Now you've included it folk can read about it.

And in answer to your other comment, the one that was deleted, if you are a person of authority in a university somewhere I'll be happy to consider your offer of an honorary doctorate.

Might be too late but maybe use the word ‘Switches’ instead of ‘Buttons’.

For completeness, could add N.C. switches.

Mention why using an external low value ‘pullup’ resistor might want to be considered in some situations.

Maybe add a modified version of this:


Edit

Personally, I think the input protection diodes should be included in the image(s).

Input pin button and pull up connected.jpg


“ Intended audience
This tutorial is intended for people who have learned the basics of electronics and programming in C/C++ from other tutorials and are now realising there are better better ways ”

better better ?

Consider:
This tutorial is intended for people who have mastered the basics of electronics and C/C++ programming. If you are a complete beginner and find the concepts presented here difficult, please review the basic examples in the Arduino IDE.


Suggest you discuss why this construct is good to use:

#define buttonPressed LOW


Maybe add a link to Nick Gammon’s discussion ?

http://www.gammon.com.au/forum/?id=11955


In discussion about connecting a switch to GND:

Switches configured between input and GND, to the same input, can function as a wired ‘OR’ circuit allowing for control from several locations.


" Intended audience
This tutorial is intended for people who have learned the basics of electronics and programming in C/C++ from other tutorials and are now realising there are better better ways "

better better ?

Well spotted! Corrected.

Protection diodes
Considered then left out deliberately as they would be something else that would need to be explained. I don’t think they add to the story I wanted to tell.

Suggest you discuss why this construct is good to use:
#define buttonPressed LOW

#define buttonPressed LOW                             // When the button is pressed the input will be low, this is to remove the confusion this might cause.

Is the comment not sufficient?
I don’t want to go into #define Vs using a constant, that’s too far away from what I intended to discuss.

Undecided on the examples you posted. Maybe belong at the end of the advanced part, not sure.

Thanks for your thoughts.

There are recurring posts about someone wanting to use interrupts to read switches. It may be instructive to put in a blurb on why this is not usually done.

Was thinking this could be added outside the sketch:

The following lines of code can be used to help document your sketch and prevents ambiguity.
These lines can also dispel confusion for those who are unfamiliar when thinking about things contrary to what they might expect.

//review #define vs const if you are not familiar with these terms.
#define buttonPressed LOW
#define buttonNotPressed !buttonPressed
OR
const byte buttonPressed = LOW;
const byte buttonNotPressed = ! buttonPressed;


Introduction
This tutorial follows on from Buttons and other electro-mechanical inputs (introduction) and should be read when you are comfortable with the concepts explained in that tutorial.

Maybe consider:

If you haven’t reviewed the thread “Buttons and electro-mechanical inputs (introduction)” please do so.

Okay, I won’t look at the structure any more. :-X


Having a section describing protection diodes would explain why you never place more than Vcc or negative voltages on input pins.

Also might want to explain the ‘Phantom Powering” problem.

"'Phantom Powering"
You mean back feeding through connected inputs that
have voltage on them WHILE arduino is powered OFF ?
(via protection diodes)

Yes.

dougp:
There are recurring posts about someone wanting to use interrupts to read switches. It may be instructive to put in a blurb on why this is not usually done.

I think that is particularly important. I have written some analyses on the matter, don't have them to hand just now but perhaps when I get out of hospital ...

I do like your tutorial so far. :sunglasses:

Thank you for the comments so far, here are my thoughts.

Protection diodes
Protection diodes are now covered here, people who are interested will find their way to this discussion and will read about them. I did consider including them in the schematic but the purpose of that schematic was to explain floating inputs, adding protection diodes doesn't do that but it does add something else that needs explanation. Floating inputs is directly relevant to the purpose of the tutorial, protection diodes are incidental.

Phantom powering
To me phantom powering is when you have a transformer at each end of a transmission line and use the centre taps to provide a DC path for power, as used in analogue telephony, stage microphones and power over Ethernet. However, the point is well made here. As with diodes it's neither central to nor a necessary incidental extra to the tutorial I wanted to write.

Interrupts
Paul__B please post your analysis here, then it will be somewhere the interested person can find it, and people can post links to it. My tutorial is about 'how to' not 'how not to'. If someone follows the tutorial and the further reading links then they will write code that doesn't need interrupts for their buttons. Newbies will use interrupts to break out of while and for loops they shouldn't have used in the first place, all part of learning. Send them to relevant tutorials when they do.

LarryD
I am still thinking about your proposed text, I was too tired to even read it properly last night :o . Keep the ideas coming.

“ Phantom powering
To me phantom powering is when you have a transformer at each end of a transmission line and use the centre taps to provide a DC path for power, as used in analogue telephony, stage microphones and power over Ethernet. However, the point is well made here. As with diodes it's neither central to nor a necessary incidental extra to the tutorial I wanted to write.”

Call it what you want, the image in post #8 is the concern. Phantom, back feeding . . .

Phantom powering
To me phantom powering is when you have a transformer at each end of a transmission line and use the centre taps to provide a DC path for power, as used in analogue telephony, stage microphones and power over Ethernet. However, the point is well made here. As with diodes it's neither central to nor a necessary incidental extra to the tutorial I wanted to write.

Ever touch touch the bell wires when an incoming call came in ?

raschemmel:
Ever touch touch the bell wires when an incoming call came in ?

I work in Telecoms....

I work in Telecoms....

Does that mean you've had your bell rung ?

raschemmel:
Does that mean you've had your bell rung ?

It means I know what ringing current feels like! Can we stay on the subject please?

Can we stay on the subject please?

I submit that a Telecom specialist's definition of "Phantom powering" is not relevant on an arduino forum where
people have been posting about the arduino backfeeding issue since the UNO was released. When I see the term
'backfeeding', or 'phantom powering' on this forum, there is only one thing I think of.

raschemmel:
I submit that a Telecom specialist's definition of "Phantom powering" is not relevant on an arduino forum where
people have been posting about the arduino backfeeding issue since the UNO was released. When I see the term
'backfeeding', or 'phantom powering' on this forum, there is only one thing I think of.

:slight_smile:

LarryD
I am still thinking about your proposed text, I was too tired to even read it properly last night :o . Keep the ideas coming.

You asked :o

Edits
Intended audience
This tutorial is intended for people who have learned the basics of electronics and programming in C/C++ from other tutorials and are now realising there are better ways than they have learnt so far to deal with inputs from mechanical push buttons and similar devices. If you are a complete beginner and find the concepts presented here difficult to understand then please go back to the more basic examples in the Arduino IDE and understand those. When you are comfortable with those then this tutorial is for you.

This tutorial is intended for people who have mastered the basics of electronics and C/C++ programming. If you are a beginner and find the concepts difficult, please review the basic examples in the Arduino IDE.
In this tutorial BUTTON will be a generic term for switch.

Introduction
A common requirement in many projects is to have push buttons, switches or other electro-mechanical devices connected as inputs to an Arduino. This tutorial shows you how to connect a button and read it reliably, and explains the reasons behind the dealing with inputs in the ways shown.

Introduction
A common requirement in many projects is to have push buttons, switches or other electro-mechanical devices connected as inputs to an Arduino. This tutorial shows you how to connect a button and respond to changes in the button’s state.

Subjects covered

Part 1

• How to correctly wire a simple push button as an input to an Arduino and reliably detect each individual press of the button and initiate some desired action
• Code examples for the simple situation of a detecting and reacting to a single button press.
• Example output on the serial monitor

Part 2

• The reason for debouncing the signal from any device with mechanical contacts
• Pull up resistors, what they are and why they are required
• Pull up instead of pull down
• State change detection
• Voltage, no voltage and 0v
Subjects covered

Part 1

• How to wire a push button switch to an input on the Arduino. Detect button operation and initiate actions.
• Code examples for above.
• Example code for output to the serial monitor.

Part 2

• Debouncing noisy signals from mechanical contacts.
• Purpose of pull-up resistors.
• Pull-up vs pull-down resistors.
• State change detection.
• Voltage, no voltage and 0v.

Part 1

Single button input
The schematic shows a single button connected to an input of an Arduino Nano. On many Arduinos digital inputs 0 and 1 are already in use for the serial monitor, for this reason digital input 2 is used in the example as it is the first free input.

Part 1

Single button input.
The schematic shows a single button connected to an input on an Arduino Nano. On many Arduinos digital inputs 0 and 1 are used for the serial monitor. Digital input 2 is the first free input and is used in this example.


Part 2
In part 1 I showed you how to read a single button, but did not explain why the circuit and the code are as they are. In this part I explain the reasons for the code and circuit in part 1.

Debouncing
You have probably heard of debouncing and are perhaps wondering what it is and why it is needed.

The oscilloscope trace below was taken from a single button wired as in part 1. If you have a look at the oscilloscope trace you will see lots of transitions between high and low lasting over 4ms before the signal settles at low. This is caused by the mechanical contacts of the button not closing cleanly or bouncing. These multiple transitions have to be removed in software to ensure they only count as one press of the button, not lots of quickly repeating successive presses. The millis based timer in the code in part 1 is to make sure the bouncing has stopped before registering the button as having been pressed.

Part 2
Part 1 shows how to read a single button. This part explains the code and circuit.

Debouncing
The oscilloscope trace below was taken from a single button wired as in part 1. The trace shows high and low transitions - some lasting over 4ms - before the signal settles at low. This is caused by mechanical bouncing of the button’s contacts. We can use software to remove these unwanted transitions. The millis() based timer code in part 1 makes sure the bouncing has stopped before registering the button press as valid.


The inputs to pretty much any micro-controller are something like the schematic above, with 2 MOSFETs. I am not saying that's the exact circuit, it probably isn't, but it gives a basic idea. The input pin is connected to the gates of a pair of MOSFETs. MOSFET gates are basically a conductive layer close to but insulated from the conductive channel that carries the current in the MOSFET between source and drain. The insulating layer has a very, very high resistance, so effectively the input is a small capacitor. Because of this, the input pin is essentially a well insulated open circuit, not connected to anything.

The equivalent 2 MOSFET circuit in the image above is typical for micro-controller inputs. I am not saying that is the exact circuit, it probably is not, but it gives a basic idea. The input pin is connected to the gates of a pair of MOSFETs. MOSFET gates are a conductive layer close to, but insulated from, the conductive channel that carries the current in the MOSFET flowing between source and drain. This insulating layer has an extremely high resistance, so effectively the input is a small capacitor. Because of this, the input pin is essentially a well-insulated open circuit, not connected to anything.


If the only thing connected to the pin is a switch (button, whatever) and the switch is open, then there is nothing on the pin to set it at any particular voltage. Being a small capacitor the pin will most likely remain at the last voltage that was applied to it, so, the switch is connected to 0V then when the switch is closed there is 0V on the pin. When the switch is open the charge on the gate stays at 0V as there is nothing to drain it away to anywhere.

When a button (switch) is the only thing connected to an input and the button is open, the input is said to be floating. Because of the high input resistance, whatever voltage was last applied to the input remains. If the button is connected to ground and closed, the input voltage goes to 0 volts and stays at 0 volts when the button opens.


The solution to this is to use a resistor to Vcc to pull the pin to Vcc when the switch is open. You can of course invert the logic by swapping the button and the resistor, which is then known as a pull down resistor. You might be thinking that there is no pull up resistor for the button in part 1 of this tutorual. The reason is that many micro-controllers have built in pull up (and in some cases pull down) resistors on their inputs, so external resistors are not needed. In the Arduino world you can enable these using

Many micro-controllers have software enabled pull-up and/or pull-down resistors.
Floating input voltages can be removed by using these. A resistor between the input and Vcc is a pull-up resistor. A resistor between ground and the input is called a pull-down resistor. In the example above, when the button opens, a pull-up resistor would make the input go to Vcc rather than sitting at a floating 0 Volt level.
On the other hand, if our switch were between Vcc and the input, and we connected a pull-down resistor between the input and ground, an open button would be read as 0 volts and a closed button would be read as Vcc volts.
You might think there is no pull-up resistor for the button in part 1. What the code below does is enable an internal pull-up resistor:


Why is it usual to pull up rather than down?
You might think it would make more sense to pull a pin down, with a resistor to 0V, that way when the input button was not pressed the input would be low, and when it was pressed it would be high, which you might think makes more sense. Having the pin high when the button is not presses is, you might think, back to front.

Pull-up resistors are often used instead of pull-downs. Why?
One might think it makes more sense to pull a pin down, with a resistor to 0V. The input would be at 0 Volts when the button is not pressed and be at Vcc (HIGH) when pressed.
A pull-up resistor connection is opposite to this. A pull-up input is HIGH when the button is released and LOW when the button is pressed.
Having the pin high when the button is not pressed is, you might think, back to front.

And a bit more:

To understand why it is common practice to have a pull up rather than a pull down resistor you have to look at the wider context of the equipment the micro-controller might be installed in. Typically some piece of equipment (from a microwave oven to a huge piece of industrial machinery) will have some control electronics buried inside somewhere with cables to a control panel. Maybe the control panel has buttons to press to activate various functions. The case or at least the chassis will probably be made of metal, and the metal connected to 0V or ground. If there is a cable then there is the possibility of the cable being damaged. If the cable comes into contact with the chassis or case then the wires might short to the metal. If the only thing the wires are connected to is 0V or inputs then the short won't do much harm. If, on the other hand they are connected to the supply then a short to the chassis will short out the supply. For this reason it is normal practice to connect buttons between 0V and their input and to pull the input up.

Understanding why it is common practice to have a pull-up rather than a pull-down resistor we have to look at the wider context of the equipment the micro-controller might be installed in. Typically, some piece of equipment (from a microwave oven to a huge piece of industrial machinery) will have some control electronics buried inside along with cables going to a control panel. Maybe the control panel has buttons to be pressed to activate various functions. The case or at least the chassis will probably be made of metal, and the metal connected to 0V or ground. If there is a cable, then there is the possibility of the cable being damaged. If the cable comes into contact with the chassis or case, then the wires might short to the metal. If the only thing the wires are connected to is 0V or inputs, then the short will not do much harm. If, on the other hand they are connected to Vcc then a short to the chassis will short out the power supply. For this reason, it is normal practice to connect buttons between 0V and their input and to pull the input up.

State change or detecting when a button becomes pressed
A button has 2 possible states: pressed or not pressed. However, for many applications it is not these states that need to be detected, it is the change of state either from not pressed to pressed, or from pressed to not pressed. Usually some action is required to happen when a button either becomes pressed or becomes not pressed. The example code in part 1 detects the button becoming pressed, so the output to the serial monitor happens once just after the button is pressed, and does not happen again until the button is pressed again.

State change or detecting when a button becomes pressed.
A button has 2 possible states: pressed or not pressed. However, in many applications it is not these states that need to be detected, it is the change of state either from not pressed to pressed, or vice versa that needs to be detected. The example code in part 1 detects the button becoming pressed, so the output to the serial monitor happens once just after the button is pressed and does not happen again until the button is first released and then pressed again.

In some applications neither debouncing nor state change is needed, for example if there are 2 buttons, one turns an LED on and the other turns the LED off then pressing the 'ON' button can only turn the LED on once as once the LED is on it doesn't matter how many times the button bounces the LED cannot be turned on again, similarly with the 'OFF' button turning the LED off.

In some applications neither debouncing nor state change is required. If a button turns on a LED when pressed, even if it bounces a thousand times, these bounces will do no harm because once a LED is on it stays on. If a second button turns the LED off, and it bounces a thousand times, once the LED is off, it stays off.

Voltage, no voltage and 0V
Something that commonly causes confusion is thinking that a pin that has nothing connected (open switch) has no voltage on it and that no voltage is the same as logic 0. All normal matter made from protons, electrons and neutrons (ie the stuff you, me, micro-controllers, the planet and stars are made from) always has a voltage, this is basis physics. A pin that is not connected has a voltage, but maybe not the voltage you want it to have or think it should have. Open circuit pins can pick up electrical noise from the environment, such as from the electrical field generated by the electrical system in the house, resulting in the voltage on the pin being unknown and probably changing all the time.

Voltage, no voltage and 0V
A pin that is not connected still has a voltage, but maybe not the voltage you want it to have or think it should have. Floating inputs can pick up electrical noise from the environment thus resulting in an unknown voltage on the input. Electrical noise can be from the electrical system in your house and other electric field sources.

A common cause of confusion is thinking that an input pin with nothing connected (open switch) has no voltage on it. And that no voltage is the same as logic 0. All normal matter made from protons, electrons and neutrons (ie the stuff you, me, micro-controllers, the planet and stars are made from) always has a voltage, this is basic physics.

No volts is a physical impossibility and is not 0V.

As for what counts as logic 0 and logic 1, this is typically a voltage close to either 0V or Vcc, the exact range that will be acceptable will be stated in the device data sheet.

Non blocking code
All the code in this tutorial is written to be non-blocking, which means it quickly does what it needs to do then returns to loop without any delays or getting stuck in while loops. In order to work properly the other code it is used with must be non-blocking as well. If there are any delays or anything that stops loop from looping freely then the code here will not work as expected.

Non-blocking code
All the code in this tutorial is written to be non-blocking. Non-blocking code means it quickly does what it needs to do then returns to loop() without any delays or getting stuck in “while” loops.
To work properly, other code must be non-blocking as well. If there are any delays or anything that stops loop() from looping freely then the code here will not work as expected.

=========================

Introduction
This tutorial follows on from Buttons and other electro-mechanical inputs (introduction) and should be read when you are comfortable with the concepts explained in that tutorial.

If you have not reviewed the thread "Buttons and electro-mechanical inputs (introduction)" please do so.

In this tutorial I present more examples with code of different things you can do with buttons as inputs to an Arduino. I have attempted to present the examples in order of increasing functionality and associated difficulty.

Examples presented
• Output on press and output again on release
• Output on press then repeat while button is held
• Output on short press or long press
• Multi button input
• 4 buttons with separate button press detection, resulting action and display

In this tutorial more examples are offered covering things you can do with buttons as inputs to an Arduino. Examples are in order of increasing functionality and associated difficulty.


Output on press then repeat while button is held

This code sends "Button has been pressed" to the serial monitor when the button becomes pressed then repeats while the button is held. In order to make it obvious what is happening I have included a counter that increments as long as the button is held down. You can vary the time before the repeating starts and you can vary the interval between each repeat. This version includes a state machine in the Buttons function.

This code sends "Button has been pressed" to the serial monitor when the button becomes pressed then repeats while the button is held. To make it obvious what is happening I have included a counter that increments if the button is held down. You can vary the time before the repeating starts and you can vary the interval between each repeat. This version includes a state machine in the Buttons function.

Further reading

Millis
I have used millis in every example for timing the debounce time out, you can find out more about
using millis for timing here.

Millis
I have used millis() in every example for timing the debounce time out, you can find out more about
using millis() for timing here.

Good stuff Perry !

Didn't look at the comments in the sketches themselves.