Capacitive Sensor:
The basic principle behind capacitive touch sensors is the same: timing how long it takes for a capacitor to charge or discharge. When nobody is nearby, the sensor plate itself will have some roughly fixed capacitance of its own, and it will take a given amount of time to charge and discharge at a given voltage. When you come along, your body capacitance couples with the circuit. The resulting capacitor— made up of you and the sensor—has more capacitance than the sensor’s capacitor alone, and so takes longer to charge and discharge. Measuring the change in charge time, allowing for environmental variation and more, lets you determine when the “button” is pressed.
Timing the capacitor’s discharge time directly involves detecting the difference between times that are on the order of two or more microseconds different from each other, and that’s a little bit unreliable and hard to do with great sensitivity. Instead if you fire off a pin-change interrupt service routine that recharges the capacitor and adds one to a count variable, and then time how many of these cycles you get in 50 milliseconds.
CODE:
/*
Capacitive touch sensor demo
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include "pinDefines.h"
#include "USART.h"
#define SENSE_TIME 50
#define THRESHOLD 12000
// ------- Global Variables ---------- //
volatile uint16_t chargeCycleCount;
// ------- Functions -------- //
void initPinChangeInterrupt(void) {
PCICR |= (1 << PCIE1); /* enable Pin-change interrupts 1 (bank C) */
PCMSK1 |= (1 << PC1); /* enable specific interrupt for our pin PC1 */
}
ISR(PCINT1_vect) {
chargeCycleCount++; /* count this change */
CAP_SENSOR_DDR |= (1 << CAP_SENSOR); /* output mode */
_delay_us(1); /* charging delay */
CAP_SENSOR_DDR &= ~(1 << CAP_SENSOR); /* set as input */
PCIFR |= (1 << PCIF1); /* clear the pin-change interrupt */
}
int main(void) {
// -------- Inits --------- //
clock_prescale_set(clock_div_1); /* full speed */
initUSART();
printString("==[ Cap Sensor ]==\r\n\r\n");
LED_DDR = 0xff;
MCUCR |= (1 << PUD); /* disable all pullups */
CAP_SENSOR_PORT |= (1 << CAP_SENSOR); /* we can leave output high */
initPinChangeInterrupt();
// ------ Event loop ------ //
while (1) {
chargeCycleCount = 0; /* reset counter */
CAP_SENSOR_DDR |= (1 << CAP_SENSOR); /* start with cap charged */
sei(); /* start up interrupts, counting */
_delay_ms(SENSE_TIME);
cli(); /* done */
if (chargeCycleCount < THRESHOLD) {
LED_PORT = 0xff;
}
else {
LED_PORT = 0;
}
printWord(chargeCycleCount); /* for fine tuning */
printString("\r\n");
} /* End event loop */
return (0); /* This line is never reached */
}
The basic principle behind capacitive touch sensors is the same: timing how long it takes for a capacitor to charge or discharge. When nobody is nearby, the sensor plate itself will have some roughly fixed capacitance of its own, and it will take a given amount of time to charge and discharge at a given voltage. When you come along, your body capacitance couples with the circuit. The resulting capacitor— made up of you and the sensor—has more capacitance than the sensor’s capacitor alone, and so takes longer to charge and discharge. Measuring the change in charge time, allowing for environmental variation and more, lets you determine when the “button” is pressed.
Timing the capacitor’s discharge time directly involves detecting the difference between times that are on the order of two or more microseconds different from each other, and that’s a little bit unreliable and hard to do with great sensitivity. Instead if you fire off a pin-change interrupt service routine that recharges the capacitor and adds one to a count variable, and then time how many of these cycles you get in 50 milliseconds.
CODE:
/*
Capacitive touch sensor demo
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include "pinDefines.h"
#include "USART.h"
#define SENSE_TIME 50
#define THRESHOLD 12000
// ------- Global Variables ---------- //
volatile uint16_t chargeCycleCount;
// ------- Functions -------- //
void initPinChangeInterrupt(void) {
PCICR |= (1 << PCIE1); /* enable Pin-change interrupts 1 (bank C) */
PCMSK1 |= (1 << PC1); /* enable specific interrupt for our pin PC1 */
}
ISR(PCINT1_vect) {
chargeCycleCount++; /* count this change */
CAP_SENSOR_DDR |= (1 << CAP_SENSOR); /* output mode */
_delay_us(1); /* charging delay */
CAP_SENSOR_DDR &= ~(1 << CAP_SENSOR); /* set as input */
PCIFR |= (1 << PCIF1); /* clear the pin-change interrupt */
}
int main(void) {
// -------- Inits --------- //
clock_prescale_set(clock_div_1); /* full speed */
initUSART();
printString("==[ Cap Sensor ]==\r\n\r\n");
LED_DDR = 0xff;
MCUCR |= (1 << PUD); /* disable all pullups */
CAP_SENSOR_PORT |= (1 << CAP_SENSOR); /* we can leave output high */
initPinChangeInterrupt();
// ------ Event loop ------ //
while (1) {
chargeCycleCount = 0; /* reset counter */
CAP_SENSOR_DDR |= (1 << CAP_SENSOR); /* start with cap charged */
sei(); /* start up interrupts, counting */
_delay_ms(SENSE_TIME);
cli(); /* done */
if (chargeCycleCount < THRESHOLD) {
LED_PORT = 0xff;
}
else {
LED_PORT = 0;
}
printWord(chargeCycleCount); /* for fine tuning */
printString("\r\n");
} /* End event loop */
return (0); /* This line is never reached */
}
No comments:
Post a Comment