View previous topic :: View next topic |
Author |
Message |
crystal_lattice
Joined: 13 Jun 2006 Posts: 164
|
Capacitance Measurement through integration |
Posted: Sat Apr 12, 2008 2:27 pm |
|
|
Hi there, has anyone used a normal IO pin to measure capacitance before??
I recently stumbled upon a guy's web site which has a circuit to "measure" capacitance and use this switch LED's on. I would like to implement a similar idea on a PIC to enable me to make a capacitance keypad for harsh environments.
Unfortunately i am not familiar with the AVR micro and was wondering if someone could maybe shed some light on how to implement it on a PIC. I have included the AVR code as the original website seems to be down at the moment. (http://www.elm-chan.org/works/capsens/report_e.html)
Kind Regards
Code: |
/*------------------------------------------------*/
/* Touch sensor test program R0.1a (C)ChaN, 2007 */
/* ATtiny2313 Internal osc 8MHz */
/*------------------------------------------------*/
#include <avr/io.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include "suart.h"
#include "xitoa.h"
#include "cs.h"
#define SYSCLK 8000000UL
/*------------------------------------------------*/
/* Global variables */
char line[16]; /* Console input buffer */
/*------------------------------------------------*/
static
void get_line (char *buff, int len)
{
char c;
int idx = 0;
for (;;) {
c = rcvr();
if (c == '\r') break;
if ((c == '\b') && idx) {
idx--; xputc(c);
}
if (((unsigned char)c >= ' ') && (idx < len - 1)) {
buff[idx++] = c; xputc(c);
}
}
buff[idx] = 0;
xputc(c);
xputc('\n');
}
void get_sens (int *res, int chs)
{
int ch, loop;
/* Clear count accumlator */
for (ch = 0; ch < chs; ch++) res[ch] = 0;
/* Capture and accumlate integration time for 1/60 second */
OCR0A = 8000000UL / 1024 / 60;
TCNT0 = 0;
TIFR = _BV(OCF0A);
TCCR0B = 0b101;
loop = 0;
do {
for (ch = 0; ch < chs; ch++) res[ch] += touch(ch);
loop++;
} while ((TIFR & _BV(OCF0A)) == 0);
TCCR0B = 0;
/* Mean calculation */
for (ch = 0; ch < chs; ch++) res[ch] /= loop;
}
/*------------------------------------------------*/
/* Online Monitor */
int main (void)
{
char *cp;
int n, c, ref[8], val[8];
PORTB = 0b10111111; /* Initialize I/O port */
DDRB = 0b01000000;
PORTD = 0b1000000;
DDRD = 0b0111111;
PORTA = 0b100;
DDRA = 0b011;
get_sens(ref, 8); /* Get reference count for each channel */
if (1) { /* Standalone mode */
/* Re-initialize I/O port as sens outputs */
PORTB = 0b00000000;
DDRB = 0b11111111;
for (;;) {
get_sens(val, 8);
for (c = 0; c < 8; c++) {
n = val[c] - ref[c];
if (n < 3) PORTB &= ~(1 << (7 - c));
if (n > 5) PORTB |= (1 << (7 - c));
}
}
}
/* Interactive mode */
xfunc_out = (void(*)(char))xmit;
xputs(PSTR("\nTouch sensor test program\n"));
for(;;) {
xputc('>'); /* Prompt */
get_line(line, sizeof(line));
cp = line;
switch (*cp++) { /* Pick a header char (command) */
case '\0' : /* Blank line */
break;
case 's' : /* Read sensor */
xputs(PSTR(" ch0 ch1 ch2 ch3 ch4 ch5 ch6 ch7\n"));
do {
get_sens(val,8);
for (c = 0; c < 8; c++) xitoa(val[c] - ref[c], -10, 4);
xputc('\r');
} while (bit_is_clear(PINB, 5)); /* repeart until a break detected */
xputc('\n');
break;
default : /* Unknown command */
xputs(PSTR("\n???"));
}
}
}
|
|
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Sat Apr 12, 2008 6:30 pm |
|
|
Look at Microchip.com application note 512. It shows how to use an RC circuit to measure resistance with minimal hardware. But the RC circuit can just as easily measure capacitance as resistance. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
crystal_lattice
Joined: 13 Jun 2006 Posts: 164
|
Capacitive Button |
Posted: Sun Apr 13, 2008 1:03 am |
|
|
Hi SherpaDoug, i realize now that my topic heading is a bit missleading. I don't want to make capacitive readings as such, i just want to implement capacitve based switches.
I will read the app note you suggested, but was wondering if anyone has done this type of button implementation with good success?? And maybe willing to share some code...
Kind Regards |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
crystal_lattice
Joined: 13 Jun 2006 Posts: 164
|
Capacitive Button |
Posted: Sun Apr 13, 2008 3:34 am |
|
|
Thanx PCM, but i would like to refrain from using AD ports. I have drawn up some code which i wanna test a bit later on, i was just wondering if anyone has some input regarding any better methods of doing it.
The circuit comprises of a large value pull-up on a pin. The junction of which is attached to a "pad".
Kind Regards
Code: |
int8 first_capture, second_capture,x,max_time,Button_presses;
while(true)
{
output_b(0x0); //Set output low to discharge "cap"
first_capture = input_b(); //capture the state of the pins just after they have been made low, if no
// capacitance present it will imediately be high.
for(x=0;x<max_time;x++) // delay for a fixed amount of time to give the cap time to charge
{
}
second_capture = input_b(); // Check the status of the inputs again, after the "cap" had time to "charge"
//via the pull up resistor.
Button_presses = Second_capture - first_Capture; // the delata change indicates which buttons were pressed
output_c(button_presses); // put the result on a output port for display.
} |
|
|
|
crystal_lattice
Joined: 13 Jun 2006 Posts: 164
|
Capacitive buttons/touch sensor |
Posted: Sun Apr 13, 2008 1:48 pm |
|
|
Hi all, i thought i had found the solution to my problem when i found some app notes and a few data sheets microchip's.
They have a pic, the 16F72X series, with built-in capacitance switch inputs. After studying the datasheets and app notes i was convinced to change my original idea to this newly found info.
Unfortunately it is only a future product... only found that out when trying to order samples...
I did find this link quite useful though:
http://www.bytecraft.com/Touch_Sensitive_Switch
My current code is working but needs a bit of tweaking to avoid false triggers and adjust sensitivity. any input is welcome (no pun intended...)
Kind Regards
Code: |
while(true)
{
output_d(0x00); //Set output low to discharge "cap"
delay_ms(1);
set_tris_d(0b11111111);
delay_us(5);
output_c(input_d()^0xff); //invert to light LED when "button" pressed
delay_ms(50);
} |
|
|
|
yerpa
Joined: 19 Feb 2004 Posts: 58 Location: Wisconsin
|
|
Posted: Mon Apr 14, 2008 2:32 pm |
|
|
I did several touch switch applications about thirteen years ago, using 16C55 chips. The user interface consisted of stainless steel bolts. There were eight touch bolt inputs per 16C55, plus a single reference input driven directly from a 555 timer chip. The 555 also drove each touch bolt through a series resistor with a diode (1n4004) across the resistor. Another series resistor buffered each 16C55 input pin, except for the reference.
The way it worked was as follow: The PIC would look at the reference pin in a tight loop. When it went low, the PIC would then read an input pin in a loop and count how many cycles it took to also go low. If a person touched a bolt, the additional capacitance would cause the input to drop more slowly than the reference pin, indicating a touch. The program was adaptive - it would look at all of the inputs, and determine a median loop timing with the assumption that most of the inputs are off at any given time.
There were four PICs and one 555 per board for a total of 32 inputs. The boards worked very well as long as the wire lengths to the touchbolts were kept below about three feet. I think they are still in service. |
|
|
crystal_lattice
Joined: 13 Jun 2006 Posts: 164
|
Capacitive touch buttons |
Posted: Tue Apr 15, 2008 12:34 am |
|
|
Thanx Yerpa, i'm planning on doing something similar with measuring the cycles that the pin went low. Think this is better as this will give a reference value without a touch and then one can also determine the "exact" capacitance when a touch is present.
Am currently trying to figure out how to make an array of inputs to work...
I found this post: http://www.ccsinfo.com/forum/viewtopic.php?t=32989
but have not tried it yet, still not sure why the values have to be 16Bit??
Kind Regards
PS. these "buttons" will be PCB based so the trace to the PIC from the pad will be minimal. |
|
|
|