Touchless Keypad: DIY Capacitive Proximity Sensors With Aluminium Foil & Capacitive Sensing Library

by Ernest Nga in Circuits > Arduino

3109 Views, 9 Favorites, 0 Comments

Touchless Keypad: DIY Capacitive Proximity Sensors With Aluminium Foil & Capacitive Sensing Library

ezgif.com-gif-maker.gif
photo6265013059340839628.jpg

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.

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.

Tools & Materials

photo6265013059340839630.jpg

(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)

Attaching Aluminium Foil

photo6265013059340839635.jpg
photo6265013059340839636.jpg
photo6265013059340839637.jpg
photo6265013059340839640.jpg

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.

Wiring & Attaching OLED Display

Wiring.PNG
photo6265013059340839631.jpg
photo6265013059340839633.jpg
photo6265013059340839632.jpg
photo6265013059340839634.jpg
photo6265013059340839639.jpg

Further details and explanation on how to use an OLED module can be found in https://randomnerdtutorials.com/guide-for-oled-display-with-arduino/

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.

Final Product

photo6265013059340839627 (1).jpg
photo6265013059340839629.jpg

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.