the wondrous tales of a software guy in hardwareland

Sense My Capacity

A little digression doesn’t hurt. Plus, it’s funny and it even has videos! :-)

I wanted to give the CapSense library a try, with the intent of creating something like a poor man’s Theremin (well, maybe too poor for a Theremin, let’s say a poor man’s D-Beam).

The beauty of this experiment is that it is absolutely simple to set up. Exactly how and why it works, instead, it’s totally over my head. So I won’t bother inanely trying to explain the theory behind, just how to make it work.

You need 2 things only: some resistors, the highest value you have, and a common tin foil. Yes, you can shape it in form of a hat if you like. My “best” resistors are 100k, so I connected 4 of them in sequence to get to 400k ohm. A couple of megaohm, if you have them, work even better.

Then you just connect the resistor(s) between 2 Arduino digital pins (I used 2 and 4), and on one end – the “sensor” end, pin 2 in my case – you wire up the tin foil. Download the CapSense library from the link above, and you’re ready to rock.

I connected a small speaker (pin 6) to generate sound, and fiddled with the values until I got something meaningful. Well, what I call meaningful: your mileage may vary :-)

This is the sketch I ended up with:

#include <CapSense.h>

CapSense cs = CapSense(4, 2);
int lastTone = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  long reading1 = cs.capSense(30);
  delay(1);
  long reading2 = cs.capSense(30);
  delay(1);
  long reading3 = cs.capSense(30);
  float reading = ((float)reading1+(float)reading2+(float)reading3)/3.0;
    
  if(reading > 25.0 && reading < 200.0) {
    int t = map((long)reading, 25, 200, 32, 3520);
    float d = (float)abs(t - lastTone) / 10.0;
    if(t > lastTone) lastTone += (int) d;
    else lastTone -= (int) d;
    if(lastTone > 3520) lastTone = 3520;
    if(lastTone < 32) lastTone = 32;
    Serial.print(reading);
    Serial.print("\t");
    Serial.println(lastTone);
    tone(6, lastTone);
  } else {
    if(reading >= 200.0) {
      tone(6, 3520);
      lastTone = 3520;
    } else {
      noTone(6);
      lastTone = 32;
    }
  }
  delay(1);
}

There are 3 main parameters you can play with:

  1. number of samples: that’s the parameter passed to the capSense() call (30 in my code), and it basically smooths the reading. I tried higher values, but it doesn’t really help a lot.
  2. delay between readings: I use 1 millisecond here to generate smoother sound.
  3. minimum and maximum reading (25..200 range in my code): here you have to study the raw readings on the Serial output and see what works best for you.

I threw in 2 tricks, so to say, to make the audio output a little bit more pleasant:

  1. I do 3 delayed readings and average them
  2. I always raise or lower the pitch by 1/10th of the delta between readings

Again, that’s basically what I came up with purely empirically. I’m pretty sure the code can be improved and fine-tuned to make the “sensor” work more reliably and realistically.

With this, you get a super annoying siren-like sound that goes up and down in pitch when your hands get near the tin foil. My setup works from about a 3cm distance, but you can increase the range throwing more megaohms between the CapSense pins.

What’s perhaps most interesting, I discovered that putting a small magnet on the tin foil helps a lot in “smoothing” the readings. In particular, you can touch the magnet and the readings stay quite in range. Furthermore, if you push the magnet, it will really sense the pressure! Without the magnet, touching the tin foil just gives maximum reading, no matter how light you touch it.

This is a short video of my hand playing the “instrument” (I will repeat it again, it makes annoying sounds. You’ve been warned):

And wait, there’s even more! I also discovered that if you put different magnets on the tin foil, they will sound different! Better said, the maximum capacitive reading seems to be related to the strength of the magnet. This video demonstrate the effect with 2 slightly different magnets:

I have absolutely no idea why the magnets do this thing. From what I’ve read on the CapSense page, it looks like they act as sort of capacitors, smoothing and capping the sensor readings somehow. I’m sure there is a very complex scientific explanation for this, involving differential equations and more greek letters than Unicode has. But I prefer to believe it’s a kind of magic :-)

No, seriously, if you can explain in plain english what effect the magnets have on capacitive sensing, I’d be very curious to know.

And this was my mad scientist achievement for today. I’m pretty sure I will play with this CapSense thing again in the future, it’s real fun!

cheers,
Aldo

UPDATE 2012-06-10: Oh silly me :-( I realized with some more reading that the magnets are totally irrelevant. Being standard fridge/pinboard magnets, they are simply non-conductive. The effect I observed, in fact, is the same you get with every non-conductive object between the tin foil and your finger. And the two different magnets probably just have slightly differing thickness, accounting for the different reading (and thus, different pitch).

So, much ado (and two videos) about nothing. But hey, I’m a slow learner :-)

cheers,
Aldo

,

Comments are currently closed.