I'm reading the book: AVR Programming: Learning to Write Software for Hardware by Elliot Williams. In the Interrupt section of the book, there's a small project to make a Capacitive touch sensor.
Schematics:
/*
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 */
}
Macros
#define CAP_SENSOR PC1
#define CAP_SENSOR_PORT PORTC
#define CAP_SENSOR_PIN PINC
#define CAP_SENSOR_DDR DDRC
This is the event loop description of the program:
The event loop then resets the charge cycle counter, initially charges up the capacitor, and then enables interrupts. As soon as the voltage on the capacitor drops back down, the ISR will be called, which will add one to the counter and then charge the capacitor back up. This cycle loops around until the delay is up and the code again disables interrupts. Now we can test how many cycles happened during the delay time and decide whether a press happened or not.
When reading this description, the first question that came to mind was this: By setting
CAP_SENSOR_DDR |= (1 << CAP_SENSOR);
The capacitor starts charging, but as long as this pin (PC1) is HIGH, the capacitor stays charged, right? So how come it discharges and trigger the pin change interrupt?