I'm writing code that needs to detect rising edges on two digital signals. I've chosen to do this using interrupts. The way I have it set up right now the interrupt constantly occurs, saving the value of the timer into two variables AInt and BInt. The resolution of how often these interrupts are occurring is giving me bad values for each variable. If I could have a way to detect both the B signal edge and A signal edge exactly only once in a loop and save each timer value to compare, it would be perfect. So not just the ISR, but the whole interrupt. I thought about using input capture, but there is not enough available hardware on the board I am using, the Spark fun Qwik Pro Micro (Atmega32U4).
Here is my code:
int Asignal = 2;
int Bsignal = 3;
unsigned int AInt;
unsigned int BInt;
void setup() {
Serial.begin(9600);
pinMode(Asignal, INPUT_PULLUP);
pinMode(Bsignal, INPUT_PULLUP);
//attachInterrupt(digitalPinToInterrupt(Asignal),intRT1,RISING);
//attachInterrupt(digitalPinToInterrupt(Bsignal),intRT2,RISING);
}
void loop() {
attachInterrupt(digitalPinToInterrupt(Asignal),intRT1,RISING);
attachInterrupt(digitalPinToInterrupt(Bsignal),intRT2,RISING);
if (AInt > BInt) {
Serial.println("Scrolling A direction");
}
if (BInt > AInt) {
Serial.println("Scrolling B direction");
}
Serial.println(AInt);
Serial.println(BInt);
delay(1000);
}
void intRT1() {
//Serial.println("A interrupt");
AInt=TCNT1;
}
void intRT2() {
//Serial.println("B interrupt");
BInt=TCNT1;
}
Once again, the solution to my problem would be a way for the whole interrupt to only iterate once per loop.
Your Aint and Bint variables should be volatile; you will also need to disable interrupts before you read them in loop() and enable the interrupts again after that.
Post the timing diagrams of the two external interrupting signals. Are you trying to measure the time difference between the two rising edges? There should be codes to intialize the TC1 (Timer/Counter 1) (mode of operation, frequency of the driving clock).
Depending on which way I spin my encoder, the leading signal will tell me which direction Im rotating the encoder. I need to know which time value is less than the other so I can detect my direction. if the yellow signa is leading, im spinning "forward" for example.
my current solution is to make two flags that are set if I have a value for AInt or BInt. If these are 1, then I dont save a new value for every interrupt. It sort of locks the value for the compare.
The encoder I am using is that of one that would be in a computer mouse:
If I Can correctly get the time stamps of these interrupts I should be able to detect what I am looking for.
There is three pins, A, B and GND. Like I said before depending on direction one signal is leading the other.
You don't need to know which signal changes first. Trying to measure that makes everything far more difficult. You just need to check if A is HIGH or LOW when B changes and vice-versa. This is how pretty much all encoder libraries work.
I tried this approach, and I'm still getting an incorrect result. The code just looks to read one of the signals after it detects a rising edge, and then prints the direction based on an evaluation. Not sure what else could be wrong here other than resolution of how many times the interrupt samples the data.
int Asignal = 2;
int Bsignal = 3;
volatile unsigned int AInt;
volatile unsigned int BInt;
volatile unsigned int Dir;
void setup() {
Serial.begin(9600);
pinMode(Asignal, INPUT);
pinMode(Bsignal, INPUT);
}
void loop() {
attachInterrupt(digitalPinToInterrupt(Asignal),IntRT1,RISING);
//delay(100);
if (Dir == 1) {
Serial.println("Scrolling in B direction");
}
if (Dir == 0) {
Serial.println("Scrolling in A Direction");
}
delay(1000);
}
void IntRT1 () {
volatile unsigned int BStatus = digitalRead(Bsignal);
if (BStatus == 1) {
Dir = 1;
}
if (BStatus == 0) {
Dir = 0;
}
}
Like I said this still isn't giving the right input its like its getting random values to compare. Im wondering if maybe its a hardware problem with the micro.
Why are you calling attachInterrupt() on every pass through loop?
The algorithm I linked in Post #10 automatically handles contact bounce with no extra hardware required. Here's an Interrupt-Driven Library that I wrote based on that algorithm.