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);
}
  • 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! – jfpoilpret May 22 '15 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. – Edgar Bonet May 22 '15 at 12:29
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.

  • Very helpful, thanks! Didn't know about digitalReadFast. – neuhaus Aug 12 '15 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.