Hands-On Embedded Programming with C++17
上QQ阅读APP看书,第一时间看更新

Debounce

The debounce board has the debouncing of switch signals as a requirement, as well as providing the Raspberry Pi board with power. The theory and reason behind the debouncing of mechanical switches is that the signal provided by those switches is not clean, meaning that they don't immediately switch from open to closed. They will briefly close (make contact) before the springiness of the metal contacts causes them to open again and rapidly move between these two states, before finally settling into its final position, as we can see in the following diagram from an oscilloscope connected to a simple switch:

The result of this property is that the signal that arrives at the SBC's GPIO pins will rapidly change for a number of milliseconds (or worse). Performing any kind of action based upon these switch input changes would therefore lead to immense problems, as one cannot easily distinguish between a desired switch change and the rapid bouncing of the switch contacts during this change.

It is possible to debounce a switch either in hardware or software. The latter solution involves the starting of a timer when the state of the switch first changes. The assumption behind this is that after a certain time (in milliseconds) has expired, the switch is in a stable state and can be safely read out. This approach has disadvantages in that it puts an extra burden on the system by taking up one or more timers, or pausing the program's execution. Also, using interrupts on the input for the switch requires one to disable interrupts while the timer is running, adding further complexity to the code.

Debouncing in hardware can be done using discrete components, or using an SR latch (consisting of two NAND gates). For this application, we will use the following circuit, which works well with the most commonly used SPST (single-pole, single-throw) type of switch:

The concept behind this circuit is that when the switch is open, the capacitor is charged via R1 (and D1), causing the input on the inverting Schmitt trigger circuit (U1) to go high, resulting in the GPIO pin of the SBC connected to the output of U1 to read low. When the switch closes, the capacitor is discharged to the ground over R2.

Both the charging and discharging will take a certain amount of time, which adds latency before a change is registered on the input of U1. The charging and discharging rates are determined by the values of R1 and R2, the formulas for which are as follows:

  • Charging: 
  • Discharging: 

Here, V(t) is the voltage at time t (in seconds). VS is the source voltage and t is the time in seconds after the source voltage has been applied. R is the circuit resistance in Ohm and C the capacitance in farads. Finally, e is a mathematical constant with the value of 2.71828 (approximately), also known as Euler's number.

For the charging and discharging of capacitors, the RC time constant, tau (τ), is used, which is defined as follows:

This defines the time it takes for the capacitor to be charged up to 63.2% (1τ), then 86% (2τ). The discharging of a capacitor for 1τ from fully charged will reduce its charge to 37%, and 13.5% after 2τ. One of the things one notices here is that a capacitor is never fully charged or discharged; the process of charging or discharging just slows down to the point where it becomes almost imperceptible.

With the values that we used for our debounce circuit, we get the following charge time constant for charging:

 

The discharge time is as follows:

This corresponds to 51 and 22 microseconds, respectively.

Like any Schmitt trigger, it has so-called hysteresis, meaning that it has dual thresholds. This effectively adds a dead zone in the output response above and below, which the output will not change:

The hysteresis from a Schmitt trigger is usually used to remove noise from an incoming signal by setting explicit trigger levels. Even though the RC circuit we are already using should filter out practically all noises, adding a Schmitt trigger adds that little bit more insurance without any negative repercussions.

When available, it is also possible to use the hysteresis functionality of an SBC's GPIO pins. For this project and the chosen debounce circuit, we also want the inverting property of the chip so that we get the expected high/low response for the connected switch instead of having to invert the meaning in software.