Introduction: Touchless Keypad: DIY Capacitive Proximity Sensors With Aluminium Foil & Capacitive Sensing Library
Touch interfaces such as elevators buttons can potentially aid in the transmission of pathogens. Inspired by the COVID-19 pandemic, I decided to build a prototype of touchless keypad. By implementing Arduino Capsense Library, capacitive proximity sensors are made with aluminium foil and high value resistors. As this setup normally functions as a touch sensing device, several modifications are implemented to increase the sensor's sensitivity for proximity sensing, which will be highlighted in this article.
Step 1: How Does It Work?
A finger, which has high dielectric properties, is able to increase the capacitance. If the capacitance of a RC circuit is higher, the time taken to charge or discharge is longer, which can be detected by Arduino. It is recommended that you read this article (https://playground.arduino.cc/Main/CapacitiveSensor/) which explains the mechanism and library methods in details.
Step 2: Tools & Materials
(1) Arduino UNO
(2) Breadboard
(3) 10M Ohm Resistors × 11
(4) Male-to-male/Male-to-female connector x 11
(5) Male-to-male connectors × 13
(6) Aluminium foil
(7) OLED display
(8) Standing calendar
(9) Scissor and cellophane tape
(10) Stripping pliers (optional)
Step 3: Attaching Aluminium Foil
Sketch the outline on the calendar. Use a small screw (or something sharp) to make a small hole. After stripping the insulator off the wire, attach the exposed wire to the aluminium foil.
Note: As Arduino UNO has a limited number of input pins, only 11 out of the 12 foil pieces can be used as capacitive sensors. You will be able to cover every digit from 0 to 9, and an extra input to clear/delete.
Step 4: Wiring & Attaching OLED Display
Further details and explanation on how to use an OLED module can be found in https://randomnerdtutorials.com/guide-for-oled-display-with-arduino/
Step 5: Code
#include <CapacitiveSensor.h> const byte howManySensors = 11; // total number of capacitive sensor input int sensorsVal[howManySensors]; // declare an array to store all input const byte threshold = 200; // Setting a threshold based on your observation // 10 megohm resistor between pins 13 & 12, pin 12 is the receiver pin, add wire, foil // multiple sensors can share the same sender pin 13 CapacitiveSensor cs_13_12 = CapacitiveSensor(13,12); CapacitiveSensor cs_13_11 = CapacitiveSensor(13,11); CapacitiveSensor cs_13_10 = CapacitiveSensor(13,10); CapacitiveSensor cs_13_9 = CapacitiveSensor(13,9); CapacitiveSensor cs_13_8 = CapacitiveSensor(13,8); CapacitiveSensor cs_13_7 = CapacitiveSensor(13,7); CapacitiveSensor cs_13_6 = CapacitiveSensor(13,6); CapacitiveSensor cs_13_5 = CapacitiveSensor(13,5); CapacitiveSensor cs_13_4 = CapacitiveSensor(13,4); CapacitiveSensor cs_13_3 = CapacitiveSensor(13,3); CapacitiveSensor cs_13_2 = CapacitiveSensor(13,2); /** Setting Up OLED Display **/ #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); void setup(){ // set autocalibration cs_13_12.set_CS_AutocaL_Millis(5000); cs_13_11.set_CS_AutocaL_Millis(5000); cs_13_10.set_CS_AutocaL_Millis(5000); cs_13_9.set_CS_AutocaL_Millis(5000); cs_13_8.set_CS_AutocaL_Millis(5000); cs_13_7.set_CS_AutocaL_Millis(5000); cs_13_6.set_CS_AutocaL_Millis(5000); cs_13_5.set_CS_AutocaL_Millis(5000); cs_13_4.set_CS_AutocaL_Millis(5000); cs_13_3.set_CS_AutocaL_Millis(5000); cs_13_2.set_CS_AutocaL_Millis(5000); Serial.begin(9600); if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64 Serial.println(F("SSD1306 allocation failed")); for(;;); } delay(2000); display.clearDisplay(); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(0, 10); // Display static text display.println(F("Initialising...")); display.display(); } void loop(){ // The intended number should correspond to the index number // Match the correct physical pin "cs_xx_xx.capacitiveSensor()" to the correct index // Index 0 --> number 0, Index 1 --> number 1, and so on // Index 10 --> an extra button sensorsVal[0] = cs_13_11.capacitiveSensor(130); sensorsVal[1] = cs_13_2.capacitiveSensor(130); sensorsVal[2] = cs_13_3.capacitiveSensor(130); sensorsVal[3] = cs_13_4.capacitiveSensor(130); sensorsVal[4] = cs_13_5.capacitiveSensor(130); sensorsVal[5] = cs_13_6.capacitiveSensor(130); sensorsVal[6] = cs_13_7.capacitiveSensor(130); sensorsVal[7] = cs_13_8.capacitiveSensor(130); sensorsVal[8] = cs_13_9.capacitiveSensor(130); sensorsVal[9] = cs_13_10.capacitiveSensor(130); sensorsVal[10] = cs_13_12.capacitiveSensor(130); // return error when it takes too long int maxVal = 0; // To find the max value of sensorsVal[] array byte maxValIndex = 0; // To find the index of the max value of sensorsVal[] array for(byte i = 0; i < howManySensors; i++){ /** // UNCOMMENT THIS TO DEBUG // use serial plotter to choose a threshold value Serial.print(sensorsVal[i]); Serial.print("\t"); **/ // To find the max value of the array if(sensorsVal[i] == -2){ maxVal = sensorsVal[i]; //locate timeout condition break; } else if(sensorsVal[i] > maxVal){ maxVal = sensorsVal[i]; maxValIndex = i; } } Serial.print("\n"); if(maxVal > threshold){ Serial.println(maxValIndex); oledDisplay(maxValIndex); delay(500); // to prevent multiple entries } else if(maxVal == -2){ // CapacitiveSensor returns -2 when there is timeout due to bad connection oledDisplay(255); delay(500); } delay(10); // arbitrary delay to limit data to serial port } void oledDisplay(byte val){ display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(25, 5); // Display static text display.println(F("The number is:")); if(val == 10){ // clear number display.display(); } else if (val == 255){ // sending error message display.setCursor(0, 20); display.println(F("Connection error")); display.display(); } else{ // display the number display.setTextSize(5); display.setCursor(53, 20); display.println(val); display.display(); } }<br>
You'll need to install the Capacitive Sensor Library by Paul Badger. You may also wish to download the relevant library for the OLED display.
Step 6: Final Product
The following methods are used to improve the sensitivity & accuracy
(1) set_CS_AutocaL_Millis(5000)
Re-calibration is set at a 5-second interval
(2) capacitiveSensor(130)
By experimenting, the optimum sampling rate is found to be 130. You may wish to try different values.
(3) Ground plate
To improve grounding, a large piece of aluminium foil is mounted on the sides of calendar, which is connected to the ground pin of Arduino. Refer to the note on the second diagram.