Hey all, I'm trying to prototype a capacitive touch array and my clock-interrupt cycle seems to get a bit confused at higher speeds.
My code basically consists of a loop between a hardware GPIO interrupt and a TIMER1 interrupt, which trigger each other over and over again. The problem is that when I shorten the time between the hardware interrupt and the clock interrupt (by lowering the OCR1A value) below about 2200 clock cycles, the clock interrupt begins occurring after only about 100 cycles, more than ten times less than it should be. Any idea what's causing this?
Note: my code saves the TCNT1 clock register value at every clock interrupt and dumps them all once it has saved 100 of them. I did this to make viewing the waveforms on my oscilloscope a bit easier.
#define period 1000
volatile int index = 0;
volatile int bank[100] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void setup() {
cli();
Serial.begin(1000000);
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
TCCR1B |= (1<<CS10);
//TCCR1B |= (1<<CS11);
//TCCR1B |= (1<<CS12);
//TCCR1B |= (1<<WGM12); //ctc
TIMSK1 |= (1<<OCIE1A); //enables interupt
OCR1A = period;
DDRB |= (1<<0); //main touch IO pin OUTPUT
DDRB |= (1<<1); //debug OUTPUT
DDRB |= (1<<2); //debug OUTPUT
PCICR |= (1<<PCIE0); //enable IO 8-13 interrupt
PCMSK0 |= (1<<0); //enables interupt pin 8
PORTB |= (1<<0); //initial touch pin high
sei();
}
void dump() {
Serial.println("New shipment, boss");
Serial.println(OCR2A);
for (int i = 0; i<100; i++) {
Serial.println(bank[i]);
}
Serial.println("");
index = 0;
//PORTB |= (1<<1); //debug
}
ISR(TIMER1_COMPA_vect) {
cli();
if (index >= 100) {
PORTB |= (1<<1);
dump();
PORTB &= ~(1<<1);
}
else {
bank[index] = TCNT1;
index++;
}
PORTB |= (1<<2); //debug
DDRB &= ~(1<<0); //touch pin to input mode
TIMSK1 &= ~(1<<OCIE1A); //diables interupt
//TCCR1B &= ~(1<<WGM12); //ctc
//turn off touch pin and start timer
TCNT1 = 0;
PORTB &= ~(1<<0);
sei();
}
ISR(PCINT0_vect) {
if(!(PINB & (1<<0))) {
cli();
PORTB &= ~(1<<2); //debug
PORTB |= (1<<0); //touch pin off
DDRB |= (1<<0); //output mode touch pin
TIMSK1 |= (1<<OCIE1A); //enables clock interupt
TCNT1 = 0;
sei();
}
}
void loop() {}
Excerpt from console log, this output is the same for every data dump cycle:
New shipment, boss
0
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98
98