1

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);
}
asked May 22, 2015 at 3:09
2
  • Show the code that currently works (when motor turns slowly) so that we can infer on WHY it does not work when motor turns faster, and HOW to make it run better. Arduino.SE is not a site to have ALL the code done for you! Commented May 22, 2015 at 4:22
  • 3
    Never Serial.print() from inside an interrupt service routine. Instead, have loop() print pulses periodically. Also, there is no need to detachInterrupt() if you are attaching a new interrupt. Commented May 22, 2015 at 12:29

2 Answers 2

1
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.

answered May 22, 2015 at 5:12
1
  • Very helpful, thanks! Didn't know about digitalReadFast. Commented Aug 12, 2015 at 12:21
0

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.

answered May 29, 2015 at 0:30

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.