Non blocking Capacitive Sensing

A project log for Interactive Disco Dance Floor

A large interactive disco dance floor with hidden capacitive sensors

JeremyJeremy 06/19/2015 at 23:294 Comments

I think I've finally created a reliable non-blocking capacitive sensor library for the Atmega!

The Problem

Originally I was using Paul Stoffregen's Capacitive Sensor library, which works great, except that the main program has to wait while it takes enough samples (~30) for a stable proximity reading. It's usually pretty quick, but when you're trying to poll 144 nodes at 250Kbps, this delay can add up significantly.

I had to find a way to get the capacitive sensor running "in the background". There is a dedicated cap sense chip that we could use, but I prefer the challenge of making it all work on one little chip. After several failed iterations the latest appears to be working far.

How capacitive sensing works

The capacitive sensor is basically an RC circuit with the person being a variable capacitor. The circuit looks something like this:

The process to detect someone's proximity starts by setting the send pin to high and then tracks how long it takes for the receive pin to go high. The closer someone is to the foil, the longer this will take (ther person acts as a larger capacitor in the RC circuit).

Paul Stoffregen's method is to create a while loop which waits for the receive pin to register as HIGH and then waits another 10µs for everything to stabilize before taking the next reading.

The non-blocking solution!

The solution came down to juggling a few interrupts to handle this entire process without blocking the main program execution.

The program basically works by using the Atmega's input capture unit (ICU) to take a timestamp every time the receive pin goes HIGH. Then it uses a timer interrupt (triggered in ~4ms) to process the timestamp and give the pins time to discharge before starting the process all over again.


Trying to sense proximity (1+ inches / 25+ mm) with a capacitive sensor is inherently noisy since it can react to everything in its environment. I fought with this for a while -- playing with moving baselines, low pass filters, high pass filters, burning sage and chanting to the project Gods.

The solution came from implementing a simple 1-dimensional Kalman filter. The results were almost immediately a smooth and predictable line.

I also created a simple tool that will run the kamlan filter over a list of raw data, so I could play with various noise values offline.

See the code


allpublic wrote 03/13/2022 at 16:53 point

Dear Jeremy,

I found your description here but also failed to get the sketch that you made.

So I made your work again. So far I was able to create a sketch running on Arduino and Teensy.

  Are you sure? yes | no

gururaj.kashikar wrote 02/09/2019 at 13:52 point

Hi, Very nice project. Good enhancement to Paul's capacitive sensor. 

I would like to implement the same. Currently the code you have shared is not available anymore. Could you please provide us the new link to access your valuable source code.

Thanks again.


  Are you sure? yes | no

John Boyd wrote 06/29/2015 at 15:20 point

This is good work. Nice write up!

  Are you sure? yes | no

Eric Hertz wrote 06/21/2015 at 03:49 point

I'm sure burning sage helped a bit with the functionality, but I doubt it helped much with the write-up, nicely done.

  Are you sure? yes | no