I am using an encoder motor for one of my projects and i was reading encoder values manually through Arduino. It was working fine when i turned it slowly, but whenever i would rotate it at some higher speed, data input to the arduino would stop. I am using the encoder at 4 x.
Can somebody help me with some code to read the data from encoder faster.
int pulses, A_SIG=0, B_SIG=1;
void setup(){
attachInterrupt(0, A_RISE, RISING);
attachInterrupt(1, B_RISE, RISING);
Serial.begin(115200);
}//setup
void loop(){
}
void A_RISE(){
detachInterrupt(0);
A_SIG=1;
if(B_SIG==0)
pulses++;//moving forward
if(B_SIG==1)
pulses--;//moving reverse
Serial.println(pulses);
attachInterrupt(0, A_FALL, FALLING);
}
void A_FALL(){
detachInterrupt(0);
A_SIG=0;
if(B_SIG==1)
pulses++;//moving forward
if(B_SIG==0)
pulses--;//moving reverse
Serial.println(pulses);
attachInterrupt(0, A_RISE, RISING);
}
void B_RISE(){
detachInterrupt(1);
B_SIG=1;
if(A_SIG==1)
pulses++;//moving forward
if(A_SIG==0)
pulses--;//moving reverse
Serial.println(pulses);
attachInterrupt(1, B_FALL, FALLING);
}
void B_FALL(){
detachInterrupt(1);
B_SIG=0;
if(A_SIG==0)
pulses++;//moving forward
if(A_SIG==1)
pulses--;//moving reverse
Serial.println(pulses);
attachInterrupt(1, B_RISE, RISING);
}
2 Answers 2
volatile long rawTacho[2]; // interrupt 0 & 1 tachometers
ISR(MotorISR1)
{
int b = digitalReadFast(8);
if (digitalReadFast(2))
b ? rawTacho[0]-- : rawTacho[0]++;
else
b ? rawTacho[0]++ : rawTacho[0]--;
}
ISR(MotorISR2)
{
int b = digitalReadFast(9);
if (digitalReadFast(3))
b ? rawTacho[1]-- : rawTacho[1]++;
else
b ? rawTacho[1]++ : rawTacho[1]--;
}
void setup()
{
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
attachInterrupt(PCINT0, MotorISR1, CHANGE); // pin 2
attachInterrupt(PCINT1, MotorISR2, CHANGE); // pin 3
}
something similar to that - it was extracted from bigger code so you will have read it and understand it as opposed to copy paste.
Update note: This is not complete in a pure form - the cpu doesnt tell you what pin had an interrupt - thus some underlying Arduino code figures that out for me, but it is fairly efficient, and I used it as is. Also if it is not obvious, this is reading encoders from 2 motors. 1 interrupt is assigned to each motor, the second phase of each is on a non-interrupt pin. Never lost a reading to my knowledge.
The problem with your code is probably the print in the interrupt as pointed out in a comment.
-
Very helpful, thanks! Didn't know about digitalReadFast.neuhaus– neuhaus2015年08月12日 12:21:07 +00:00Commented Aug 12, 2015 at 12:21
I built a measuring bench using a glass slide (intended for DRO) with quadrature output. I found the Arduino was easily overwhelmed and would miss beats. I also tried implementing a D flip flop to halve the resolution of the slide. Ultimately, I put a LS7166 IC in the prototyping area of the freeduino eleven I was using and then performed a PORT read on D0-D7.
Serial.print()
from inside an interrupt service routine. Instead, haveloop()
printpulses
periodically. Also, there is no need todetachInterrupt()
if you are attaching a new interrupt.