Down the Rabbit Hole

By Philip Kane

Parts List:

 Component Name Part Description Manufacturer Part No. R1-R4 R1-R4 51KΩ Resistor CF1/4W513JRC C1-C2 C1-C2 .0047µF Capacitor DC.0047 Q1-Q4 Q1-Q4 2N3904 Transistor 2N3904 — Arduino Uno R3 (optional) A000066

Resistive Touch Switch Basics

Place a finger across two electrodes separated by a small gap, with one electrode connected to a small DC voltage source and the other connected to ground. A tiny current will flow through the skin of your finger from one electrode to the other. This is the principle behind a resistance touch switch. Figure 1 shows one way to build a resistance touch switch.

Figure 1: Basic Resistance Touch Switch (click to enlarge)

When you place your finger across the touch contacts, the Darlington Circuit formed by Q1 and Q2 amplifies the current flowing through your finger to drive LED1. Resistor R1 is included to protect against a short circuit at the touch contacts. Capacitor C1 helps to eliminate switch bounce; I found that it was more important for eliminating induced AC noise. Without it, touching the transistor side contact alone caused the LED to light. The addition of C1 turns this into a voltage transient of short duration which can be be filtered out in software. The capacitor causes a turn on and turn off delay. You may need to experiment with different values to find one that produces an acceptable delay while still reducing induced noise.

The 4x2 resistance touch switch matrix circuit in Figure 2 works as follows. A high (VCC) is placed at each row input successively while keeping the other row inputs low. When a finger is placed across one pair of contacts in the row that is set to high, the output (Col1 or Col2) of the corresponding Darlington pair will go low (GND). So, to determine which contacts have been touched, you note the row input that is currently high and the resulting output that goes low.

Figure 2: Matrix Circuit Schematic (click to enlarge)

I was looking for a quick and cheap set of touch contacts. My wife graciously contributed a box of thumbtacks originally acquired for one of her art projects. As you can see in Figure 3, two thumbtacks were required to make each of the eight touch contacts in the 4x2 keypad matrix. Column 1 is at the bottom of the figure.

The table below shows the pattern for the circuit in Figure 3 Matrix Circuit:

 Switch Coordinates S1 Row1, Col2 S2 Row2, Col1 S3 Row2, Col2 S4 Row3, Col1 S5 Row3, Col2 S6 Row2, Col2 S7 Row4, Col1 S8 Row4, Col2

For the Arduino test circuit I built a test version of the matrix keypad on a solderless breadboard and used it as the input for an Arduino Uno single board computer. Figure 4 shows the test circuit with the with the Arduino Uno pin connections.

Figure 4: Arduino Test Circuit Schematic (click to enlarge)

The breadboard test circuit is shown in Figure 5.

Figure 5: Arduino Test Circuit

Arduino Test Software

The code in listing 1 is a simple test program that continually scans the keyboard matrix waiting for a "keypress." When a key is pressed it displays the value of the key. On startup the test program sets all row lines to Low. It then successively forces each row line high and, after a delay to account for switch bounce, checks each column output to determine if a contact has been touched.

If a contact has been touched, then the corresponding column output will be forced low. Upon detecting a low column output the test program uses the row and column values to index into a matrix that contains the the corresponding key value. It displays the key in the serial monitor. Then waits for the key to be released before it resumes scanning the keyboard.

```const byte ROWS = 4; //Four rows
const byte COLS = 2; //Two columns
char keys[ROWS][COLS] = {
{'1','2'},
{'3','4'},
{'5','6'},
{'7','8'}
};

byte rowPins[ROWS] = {12, 11, 10, 9}; //Connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 7};          //Connect to the column pinouts of the keypad

void setup(){

// Set row ports to output
for (int r = 0; r < ROWS; r++)
{
pinMode(rowPins[r], OUTPUT);
}
// set col ports to input
for (int c = 0; c < COLS; c++)
{
pinMode(colPins[c], INPUT);
}
// set row ports output levels to low
for(int r = 0; r < ROWS; r++)
{
digitalWrite(rowPins[r], LOW);
}
Serial.begin(9600);
}

char k;
boolean br;

void loop(){
k=NULL;
// scan the keyboard until a key is pressed
do
{
// Row scan - set the rows to high, one at a time
for (int r = 0; r < ROWS; r++)
{
digitalWrite(rowPins[r], HIGH);
delay(25); // Settling time

// Scan the columns for a low
for (int c = 0; c < COLS; c++)
{
if (digitalRead(colPins[c]) == LOW)delay(25); // Debounce
{
// Valid keypress. Get the key value and print it
k = keys[r] [c];
Serial.println(k);

// Wait until the key is released
br = false;
do {
{
delay(25);
}
}while (br==false);
// Exit
break;
}
}
digitalWrite(rowPins[r], LOW);
delay(25); // Settling time
if (k != NULL)break;
}
}while (k == NULL);
}

```

Phil Kane has been a technical writer in the software industry for more than 10 years. He has also occasionally authored articles for electronics enthusiast magazines.

If you have an electronics story or project you'd like to share, please email [email protected].