Introduction: Interactive Touchless Light

Hi everyone! I'd like to share the project I have been working on here. I got inspired to experiment with capacitive touch sensing through a project in my university. I found out about this technology through instructables and used the things I learned here and from other places on the internet to build my own touch-less controller, which I use to blend different RGB values to create interesting light colors.

For starters, when I started this project I knew next to nothing about either electronics nor capacitive touch sensing.

Some problems I ran in to early on were caused by misunderstanding what actually happens. So a short introduction from how I understand it:

A capacitive sensor uses multiple components, mainly:

A capacitor (in this project we use aluminium foil, but its also possible to use conductive fluids etc),

wires (ofcourse, its electronics)

and a resistor, anything under 10 MOhm is too small a resistance for more than direct touch.

the way it works is by measuring a difference in time between point A and point B. From the start pin it sends a signal to an endpin, the time it takes is measured with a timer. By decreasing the resistance value (by moving a capacitor (in this case your hand) closer to the capacitor of the sensor(the aluminium foil) this time shortens, the difference in time is what the sensor gives back as a value.

Due to the sensor being affected by capacitive surfaces the data can be wildly erratic due to interference. This can be solved for a large part by correctly insulating the capacitor and also by using a ground (I will show how later on) .

So now that is out of the way we can start inventorying all the stuff we need:

Step 1: What Do We Need?

Electronics:

1. 2 x 22M Ohm + resistors (the bigger the resistance value the further away your sensor reacts, I personally used 22M Ohm, the minimum to get usable data I experienced was 10M Ohm)

2. 3x 330 Ohm resistors

3.Wires

4. Breadboard

5. Circuit board (mine had continouos copper strips)

6. Multiple common Cathode RGB Leds (I used 8, but you can have more or less depends on how much light you want)

7.Aluminium foil

8. Cling wrap

9.Arduino Uno

10. Tape

The Case:

1. Wood I used 50 x 50 x 1.8 CM MDF(you can use anything really. It depends on the effect you want and the tools you have at your disposal)

2. Acrylic plexiglas I used 50 x 50 x 0.3 CM(or any other transparent/translucent material like rice paper)

3.Sandpaper (fine sandpaper)

4.Wood-glue

5.veneer (optional)

6.Acrylic glue

Tools:

Wire stripper

Soldering iron + tin

Stanley knife

drill

Saw (I used a table saw)


Step 2: Prototyping:

Now we have everything and we can start making a prototype to see how it works:

Prep work:

Cut out 4 rectangles from the aluminium foil (Mine are about 10 cm by 5 cm), wrap these in cling wrap to insulate them from direct touch and stick a wire to the aluminium foil. I just taped a stripped end to the foil (as long as they stay in contact).

To make sure the aluminium is safely insulated I wrapped in cling wrap and ironed it between papers (just for a few seconds so it doesn't completely melt).

Then set up the circuit as seen in the image.

Pin 4 is used as a send pin for both sensors, while the receive pins are pin 2 and 5. You could use multiple send pins but it causes trouble since they are not perfectly in sync.

use this setup for debugging purposes before soldering everything together, to make sure that everything truly works as intended.

Step 3: Code:

Now we have everything and we can start debugging the sensors.

To use my code you should download the capacitive sensing library from Arduino and install it according to the directions given by the reference page: Click me

The code: (I'm not great at coding, so if you know how to do it better please do)

#include <CapacativeSensor.h> //import the code library

CapacitiveSensor   cs_4_2 = CapacitiveSensor(4,2);        //Send pin = 4, receive are 2 and 5
CapacitiveSensor   cs_4_5 = CapacitiveSensor(4,5);        

const int redPin = 11;
const int greenPin = 10;
const int bluePin = 9;

const int numIndexR = 10;    // array size
const int numIndexG = 10;

int colorR = 0; 
int colorG = 0; 
float colorB = 0;

int indexR [numIndexR];
int posIndexR = 0;
long totalR = 0;              //it needs to be a long because the total of my array was to big for an integer.
int averageR = 0;

int indexG [numIndexG];
int posIndexG = 0;
long totalG = 0; 
int averageG = 0;

void setup()                    
{ 
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

   for (int thisIndexR = 0; thisIndexR < numIndexR; thisIndexR++) {   //sets the array to 0
    indexR [thisIndexR] = 0;
    }

   for (int thisIndexG = 0; thisIndexG < numIndexG; thisIndexG++) {
    indexG [thisIndexG] = 0;
    }

  colorR = 255; //turns on all leds colors 
  colorG = 255;
  colorB = 255;
  Serial.begin(9600);
}

void loop()                    
{
    long start = millis();
    long total1 =  cs_4_2.capacitiveSensor(10); //Save the raw sensor data to a variable
    long total2 =  cs_4_5.capacitiveSensor(10);
    
    if (total1 >= 4500){        //cap the sensor values to a usable maximum, this is not the same for every resistor value and also might differ a bit from environment to environment you might need to tweak this to your own needs.
      total1 = 4500;
      }

    if (total2 >= 4500){
      total2 = 4500;
      }

    totalR = totalR - indexR[posIndexR]; //this here creates an array that continuously adds a sensor output and produces the average. 
    indexR[posIndexR] = total1;
    totalR = totalR + indexR[posIndexR];
    posIndexR = posIndexR + 1;


    if (posIndexR >= numIndexR){
      posIndexR = 0; 
      }

    averageR = totalR / numIndexR; //we use the average instead of the raw data to smooth out the output, it slows the process down slightly but it also creates a really nice smooth flow.

    totalG = totalG - indexG[posIndexG]; 
    indexG[posIndexG] = total2;
    totalG = totalG + indexG[posIndexG];
    posIndexG = posIndexG + 1;

    if (posIndexG >= numIndexG){
      posIndexG = 0; 
      }

    averageG = totalG / numIndexG;

  if (averageR >= 2000 ){     // we don't want the leds to constantly changes value unless there is input from your hand, so this makes sure all lower environmental readings are not taken into account.                    
      colorR = map(averageR, 1000, 4500, 255, 0);
      
          analogWrite (redPin, colorR);   
    }
  else if (averageR <= 2000){
          colorR = 255;  
          analogWrite (redPin, colorR);
         
      }
  if (averageG >= 1000 ){ 
      colorG = map(averageG, 1000, 4500, 255, 0);
      
          analogWrite (greenPin, colorG);   
    }
  else if (averageG <= 1000){

           colorG = 255;
           analogWrite (greenPin, colorG);   
    }

  if (colorR <= 125 && colorG <= 125){            //B works a bit different because I only used 2 sensors so I mapped B on both sensors
     colorB = map(colorR, 255, 125, 0, 127.5) + map(colorG, 255, 125, 0, 127.5);
     analogWrite (bluePin, colorB);     
  }

  else{
   colorB = map(colorR, 255, 125, 127.5, 0) + map(colorG, 255, 125, 127.5, 0);
   if (colorB >= 255){
      colorB = 255;
      }

   if (colorB <= 0){
      colorB = 0;
      }
    analogWrite (bluePin, colorB);
    }
    
    Serial.print(millis() - start);        //this is for debugging purposes
    Serial.print("\t");                    

    Serial.print(colorR);       
    Serial.print("\t");
    Serial.print(colorG);       
    Serial.print("\t");
    Serial.println(colorB);                 

    delay(1);                             
}

What this code does is extracting the raw data from the sensor (this data will always be slightly erratic due to all the different factors that affect the sensor) and it puts the raw data continuously in an array, when the array reaches is max value (in my case 10) it purges the last value and adds a new one. Each time a value is added it calculates the average value and puts it in a new variable. This average variable is used to map a value to a value from 0 to 255, this is the value that we write to the RGB pins to increase the brightness of each channel (the channels being R G and B).

Now if you upload your code to the arduino and you open the serial monitor you should be seeing the RGB values lower when you hover your hand over each sensor also the light color of the led should change.

Step 4: Now for the Case:

The case: I made the case using tools available through my university, so this workflow is not applicable for everyone. However there is nothing too special about it, it needs a hole on one side for the USB port to fit through but other than that its just an open topped box.

The dimensions are as follows:

15 x 15 CM for the transparent top

and

15 x 8 CM for the wooden base (the thickness of the wood was 1.8 CM for me).

I used a table saw to cut a plate of MDF into the correct dimensions I needed (which is 4 panels 15 x 8 CM and 1 15 x 15 CM ground panel), after which I cut the corners into a 45 degree angle. All the parts I stuck together using wood glue and clamps(let it dry at least 30 minutes), I used the same procedure for the Plexiglas but with a special saw blade.

1 of the wooden sides should have a hole in the center at the height of the arduino USB plug to allow the arduino to be plugged in.

I finished the base of with veneer. I cut it into pieces slightly bigger than the surface of each side.

This I glued on it, then clamped it 30 minutes for each side (better to do it individually so you make sure it doesn't slide and after it dried I cut off whatever stuck out.

The cap I glued together using a glue specific for Acryl called Acryfix.

Be aware that if you use acrylic Plexiglas, the glue dissolves the Plexiglas a bit, so be as precise and fast as possible (it dries within a couple of minutes, but exposed to air within seconds).

To finish off the cap I frosted the cube with a sandblaster but you can also use fine sandpaper it just takes much more time to make it look even. Pay mind though if you use sandpaper it needs to be fine grained and also glue the parts together after the frosting procedure (So you don't break it accidentally by applying to much pressure)

To make sure the cap doesn't slide to much I glued a couple of small wooden bars on the edges of the wooden cube.

Step 5: The End Result Should Look Something Like This:

Step 6: Soldering!

If you have a circuit board you can start soldering all the parts together using the same setup your breadboard has.

My circuit board has continuous copper strips for ease of use.

For each sensor I cut off a small square to solder the resistors and wires to.

The send wires (the wires that go from pin 4 to each sensor) are soldered in sequence to a separate square, with 1 wire that goes into pin 4.

I kept a long rectangle to make an improvised led strip(measure it so it fits inside of the cap but on the edges of the base). You can just solder the leds in sequence after each other(keep in mind in the image I accidentally soldered the leds and resistors on the wrong side of the circuit board, the copper strips should always be on the underside) .

When you are done soldering the individual parts together, fit them into the case. I didn't solder my individual wires together so I can change them out easily if needed.

Time to fit everything into the base:
This is pretty much the easiest step, the arduino needs to be places first with the USB port through the hole at the backside of the case. Now add the sensors, make sure the sensor foil fits against the wood on both sides, with the ground foil straight against it. When it all fits in well, plug the RGB leds into the right pins (9, 10, 11) and let it lean on the edges of the base.

Step 7: We're Done!

If you have followed through with all off this, you should now have a working light with capacitive touch color blending. Have fun!