I am attempting to run 2 interrupts at the same time, one blinks an LED at 1Hz and another detects when an encoder is turned. On start up the LED blinks perfectly fine, but as soon as the encoder is turned, it falls into an infinite loop within the LED interrupt. Any help as to why this happens would be greatly appreciated.
int counter = 0;
int previous;
int current;
int DT;
bool led = 0;
void setup() {
pinMode(9, OUTPUT);
pinMode(2, INPUT);
pinMode(7, INPUT);
pinMode(5, OUTPUT);
Serial.begin(9600);
previous = digitalRead(2);
digitalWrite(11, HIGH);
digitalWrite(12, LOW);
//Timer Setup
attachInterrupt(digitalPinToInterrupt(2), KNOB, RISING);
//set timer1 interrupt at 2Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 31249;// = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler
TCCR1B |= (1 << CS12);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
}
ISR(TIMER1_COMPA_vect) {
TCNT1 = 0;
led ^= 1;
digitalWrite(5, led);
Serial.println("LED");
}
void KNOB() {
Serial.println("Knob");
current = digitalRead(2);
DT = digitalRead(7);
if (digitalRead(7) != current & counter != 0) {
counter += -10;
}
if (digitalRead(7) == current & counter != 250) {
counter += 10;
}
previous = current;
Serial.println(counter);
}
void loop() {
analogWrite(9, counter);
}
You should never use Serial.print within an ISR. Serial.print itself uses interrupts, an when used within an ISR it can block the whole system.
Be aware that ISR'S are NOT normal functions and need special attention.
analogWrite on pin 9 uses timer 1. This interferes with your usage of timer 1.
As soon as counter becomes greater than 0, it crashes.
And I told you already that ISR's are not normal functions. This is also important if you use variables inside AND outside the ISR. You have to deal with atomic reading and volatile variables.
Thank you this makes sense. Is there a way to obtain a 2Hz Frequency using Timer 0 and Timer 2 instead of Timer 1 for the interrupts? Or am I constrained to Timer 0 and Timer 2 (in other words higher frequencies) when analogWrite is necessary to be used?
To obtain a 2Hz frequency no timer is necessary in my opinion. This can be done with millis in loop().
Or you use the MoToTimebase class of my MobaTools lib, if you don't want to bother with millis directly.