Capacitive sliders and the capsense library- repeatability

Follows on from this post if anyone wants to read it;

cap sense post

I’m trying to build a very long capacitive slider...two triangular contacts made of copper mesh. The readings between the two plates do not seem very reliable. I had hoped that a simple formula of

(Reading from plate one)/(sum of readings from both plates)

would be a reliable indicator of the position that contact was made...it doesn’t seem to be.

Does anyone have experience of getting the best out of this type of device? I’ve been quite successful at smoothing the output with a moving average array, but there’s still too much variation.

In the original thread above, TonyWilks used a separate pin to send a pulse which improved reliability but as yet I’ve been unable to replicate this...but I may well be (in fact, probably am) doing something wrong, plus I don’t know how to send the PWM signal to the pin that was grumpymike’s idea.

Mike, you may say “I told you so” at this point if you wish, but I ain’t giving up yet.

The real goal is quite simply a distance sensor, approx 800mm long, that reports back the position it has been touched...the more accurate the better, ideally to +/-10mm, but if unachievable, I could live with up to +/- 100mm...more than that and it won’t work for the intended purpose.

It also needs to be as unobtrusive as possible (invisible would be ideal, which is why the copper mesh was so tempting) and not use too many pins as it needs to run on a small format Arduino device.

plus I don't know how to send the PWM signal to the pin

analogWrite(pin,128); // use a PWM capable pin one of the ones marked with a ~

GreyArea:
TonyWilks used a separate pin to send a pulse which improved reliability but as yet I’ve been unable to replicate this...

Can you post some pictures of your sensor ?

My 800mm test sensor is still stood in the corner, I didn't go any further with it.

I'll hook it up again and have another play with the code (there were several suggestions which I never investigated).

Yours,
TonyWilk

Thank you Mike, I should be able to give that a try almost immediately.

Tony…pictures on their way (I have to take them on my ipad then email them to myself to get them to my PC…working with this forum from the iOs is painful).

I’m still unfortunately using the same 1MOhm resistors rather than your suggested 10MOhms. I have bought some 10MOhms and put them in a safe place. A very safe place. When I find where that safe place IS, I will try them out.

By the way, since what I’m workign with is a line of WS2812B LEDS that sit under the sensor, the ideal “resolution” I’d like to get from the scale would be 60 divisions per metre or 1.667 cm per division…the same as the pitch on the LED strips.

Right now I’m wondering if my “count up the pole” version of this might be better (or at least easier) but there are enough advantages in a “continus contact” solution like this one that I’d like to bottom it out completely before I give up and look at the “discrete” contact method again.

Pics of two poles, one with external driver strip (copper tape on red tape( I havent tried this on yet but I did introudce a copper stip into the other and got no real difference in output…

The copper mesh that makes the plates is set into rpoxy resin. THeres a slight difference in tube one is pole/vinyl/resin/copper whereas pole one is just tube/resin+copper,vinyl I plan a finaly coat opf resin, but don’t wants to waste it if possibble.

Pics attached, if you need anythiing lese just yell…

Just a quick check…I “upgraded” my arrangement of resistors to a proper soldered board unit. Photo and diagram attached. Have I done it right, because ever since I started using it, my arduino has been resetting and I’m worried something is shorting…

as someone said…the problem is the last thing you did…

Currently this is my serial plotter output when I’m running my “calibration” process…don’t worry about the plateaus, that’s because I output each result 5 times so it spreads out more

It kind of neatly illustrates the problems I’m having…ideally I should have a neat cross…but my “X” is off centre to the right (I think I know why that is though) and the results are a bit all over the place…this is what I’m trying to make better…but if it cvan’t be done…back to my “stepping” method…which was a lot closer…

Quick note: hooked up my sensor, ran the old code... was dragged out for a beer, ended up being several. Will continue later :slight_smile:

Yours,
TonyWilk

Beer is good.

Well, that took a bit longer than I thought (mind you, with She Who Must Be Obeyed back from Portugal, there were a number of other jobs and shopping trips that took priority :slight_smile: )

GreyArea:
Pics of two poles... snip

Picture1, Picture2... 2 poles, I see, one tape, the other mesh in resin.
Picture3 - that's some tape on top of red tape on the mesh pole. Probably not good - the tape will make a big capacitor and mess up the sensor I think.
Picture4 - detail of the mesh and the thin end of one of the strips - ok.
Picture5 - the other end of the mesh pole? - ok
Picture6 - I'm not sure what that is showing. see my diagram again below

I'm still unfortunately using the same 1MOhm resistors rather than your suggested 10MOhms

They should be 1 MOhm, not 10 MOhms, see diagram: (it will not work without these resistors)

Progress...
Referring to some earlier comments/suggestions:
"pre-selecting the analog channel and driving the pin" like this:
digitalWrite( DRIVE_PIN, LOW );
digitalWrite( DRIVE_PIN, HIGH );
analogRead( STRIP_PIN1 );
digitalWrite( DRIVE_PIN, LOW );
digitalWrite( DRIVE_PIN, HIGH );
a0+= analogRead( STRIP_PIN1 );
...makes no difference at all.

Using fast PWM is useless... the analogRead is not synchronised to the PWM output and, as you can see from the 'scope trace below, the analog line is pulled LOW by the drive signal

Note the 'scope trace... it is essential to start an analogRead immediately after switching the drive line HIGH
you cannot read both sense strips at the same time (the input will have decayed by the time the second ADC starts)
'Scope picture (20uS/div, top trace 1V/div = analog input, bottom trace 2V/div = drive signal)
CapSensorWaveform.png

New Code
Messed with the code quite a bit and added some more calibration (now stored in EEPROM).
As well as removing the 'ambient' levels read on the analog inputs, the ratio of the signals from the strips does not go from 0% up to 100% so there's a couple more calibration steps so we can work out the low and high percentage and then scale (using map() ) the actual reading into a nice 0 to 100 range.

To use it you'll have to wire your sensor as per the above diagram (note that A0 should be connected to the "low end" wide strip) and add a button on digital pin 2.

With Serial Monitor running, press the button and it will start the calibration sequence (the onboard LED will blink showing the stage of calibration in case you have to do it without the monitor).
Keep your hand off the sensor and press the button again.
Put your hand on the low end, press the button
Put your hand on the high end and press the button.
It should then be running and calibrated. (the values are stored in EEPROM, so it will start with these values next time).

Exactly how you hold the sensor is quite important
I found the most accurate to be having you palm on the back of the pole and your 4 fingers wrapping over both sense strips. (the least accurate is putting your palm on the strips - because you tend to cover more of one strip than the other).

Code was too big to include inline... attached.

Yours,
TonyWilk

CapSensorWaveform.png

CapStrip2.ino (9.52 KB)

Just a quick note.
While you can scale up the size of your electronics, you can not scale up the size of your thumb.

Grumpy_Mike:
Just a quick note.
While you can scale up the size of your electronics, you can not scale up the size of your thumb.

Made me howl. Thanks Mike.

Tony; thanks again for efforts.

As to the pics are you saying my layout is flawed, that the third “driver” strip won’t work if it is on top of insulation? I’ll admit I don’t understand that bit (quite a lot of other stuff I don’t understand too, but this in particular). I don’t know why sensor/tape/driving pin is any different to sensor/air/driving pin...isn’t air a pretty good insulator?

I’ll look at you recommendations and the code though...I thought a robust calibration was the key too, but my method still wasn’t delivering sufficient reliability, so I’ll be interested to see what you do differently, and if it helps.

Not sure where I got the 10MOhm idea from...oh well at least I’ve been inadvertently using the right thing!

Ok re-read post...cant read sketch yet so apologies if it’s in there, but are you saying;

Drive pin
Read sensor A
Read sensor B

would be better as

drive pin
Read sensor A
Drive pin again
Read sensor B

?

Thanks! I’ll leave more questions until I’ve had chance to play, but maybe a couple of weeks...other pressures!

GreyArea:
As to the pics are you saying my layout is flawed, that the third “driver” strip won’t work if it is on top of insulation?

In Picture3.jpg it looks like you have the copper mesh cut diagonally and then there is some red tape with a strip of copper tape on top.
What it looks like is that the red tape and copper tape is on top of the copper mesh - which would not be good.
Diagram:

...are you saying;

Drive pin
Read sensor A
Read sensor B

would be better as

drive pin
Read sensor A
Drive pin again
Read sensor B

Yes, the first of those will hardly work at all. Look at the 'scope trace in my post above: the bottom 'driving signal' pulses LOW, when it rises it couples into the top 'sense strip' and pulls it up. Since the level is only held on the small capacitance of the strip, it decays to almost nothing in 6 divisions on the 'scope - that's only 120uS. The code only did one analogRead() in that time, if it then tried to analogRead() the other sense strip there will not be any signal left on it - so you have to drive before every read.

Yours,
TonyWilk

TonyWilk:
In Picture3.jpg it looks like you have the copper mesh cut diagonally and then there is some red tape with a strip of copper tape on top.
What it looks like is that the red tape and copper tape is on top of the copper mesh - which would not be good.

Yes, that’s exactly how it is. Bugger. Does explain why it’s not working!

Still; I think I can fix it with the Dremel, but I have a questino for future versions; you have two driving plates on the outside. Is this necessary? I ask because since my contacts wrap around a pole, they meet at the back. I could arrange it so there’s a single driving strip down the middle (pic attached may explain better…I’ve colour coded the contacts so you can see what they’d look like if looking along the axis opf the pole in the direction of the blue arrow) - but would that cause any problems? It means both contacts would be coupled by an identical signal, which to me sounds like it should be better, but as wel’ve all seen, I get a lot of stuff wrong!

The timing of the drive signal is a no brainer and I’ll implement that as soon as I get chance.

Thanks again!

Few more (probably dumb) questions...

You specify "at low end". Just want to clarify what that means...low as in signal (ie narrow point) or low as in height?

Due to the simple advantages of "more copper available"...I've got both triangles connected to the pins from their wide ends...but that means one wire is much longer than the other. How much of a problem would that cause?

If I should be keeping the wires the same length, then is it better to connect at the top of the stick (shorter wires) or at the bottom (nearer to ground - I could in theory add a ground strip that actually ran to ground...but would this help or hinder the reliability?

Also with wires...how diligent have I got to be in ensruing that they do not cross or touch? Is it enough to just "keep them from touching", or should I actually separate them by as much distance as possible?

Thanks again Tony, I really, really appreciate you doing this. If you're UK based I'll buy you a beer one day! A few beers, even!

This is my code prior to your suggested changes.

I also had a “grip” calibration routine, but I thought the movement of the hand might need to be factored in, so this is my “sweep” calibration.

I have used the lights within the pole to indicate the calibration procedure. I appreciate thius means it may not be much use to you, especially as I use both the Adafruit and CapSense libraries, but…at least you can see how poorly structured my code is (it IS a question of “how”, not “if” I am sure - and memory waste in variables is probably huge.

The sketch also contains my “shimmer” routine, which works very nicely as standalone code (each pixel has it’s own independent sinusoidal variation in brightness, plus random “flashes” thrown in - on an array of 12x12 pixels it’s a very pleasing effect indeed) but currently in combination with the capstrips only works on the first LED in the strip.

NOT expecting you to buy a load of neopixels just to try it out - just proffering my version of the code for completeness.

DragonCapsweepcal.ino (10.9 KB)

GreyArea:
... my contacts wrap around a pole, they meet at the back. I could arrange it so there's a single driving strip down the middle...

My prototype is sort of the opposite, the driving strip wraps around the pole and the sense strips are relatively thin.
The thing is your hand will pick up some 'driving signal' which needs to be coupled into both sense strips, you hand must cover the full width of both sense strips so that the ratio of the two signals is controlled by their width at that point - not by the amount your hand covers them by.

Since the calculated result relies on the relative strength of the two sense strip signals, it is not so important how much 'driving strip' your hand covers
e.g.
If your hand covers a point where Strip1 is 20mm wide and Strip2 is 5mm wide then Strip1 should get 4 times the signal of Strip2. The actual signal will be larger or smaller depending on how much 'driving strip' you hand is covering at the same time.

I've video'd my setup and put it on my server here: Arduino Stuff

You specify "at low end". Just want to clarify what that means...low as in signal (ie narrow point) or low as in height?

I meant 'low end' as in 'bottom end of the pole'

Wires... I don't think it's too critical, but keep the drive signal separate.
You may be able to see in the video, I used some ribbon cable and made all the connections at the bottom of the pole. I also separated the two signal wires from the driving wire with a wire connected to GND.

Wires:
1= Signal 1
2= Signal 2
3= GND (not connected at the pole end)
4= Drive output

This was to prevent the drive signal from coupling straight into a sense signal right next to it.

Yours,
TonyWilk

Cheers Tony, videos very infomrative. Ill be next week or week after before I can put any of it to work...thanks once again!