Go Down

Topic: Arduino board - Interrupt Pin rate? (Read 465 times) previous topic - next topic

J Young

Hi, I'm using Arduino UNO and trying to do position control of geared DC motor with encoder.
The following is code to check if the encoder counting is working. (well it's not..)

Code: [Select]
#define encA 2 // encoder channel A
#define encB 3 // encoder channel B

volatile int enc0 = 0; // initial encoder count #
int en1 = 5; // motor1 enable
int dir1 = 4; // motor1 direction
int pwm1 = 6; // motor1 pwm

void setup() {
  pinMode(en1, OUTPUT);
  pinMode(dir1, OUTPUT);
  pinMode(encA, INPUT);
  attachInterrupt(0, doEncoder_Expanded, CHANGE); // do counting if encA CHANGE
  pinMode(encB, INPUT);


  Serial.begin(9600);
  Serial.println("start");
 
}

void loop(){

  Serial.println(enc0);
  analogWrite(pwm1, 150);
  digitalWrite(en1, HIGH);
  digitalWrite(dir1, HIGH);
 
  if (enc0>100){
  analogWrite(pwm1, 0);
  delay(1000);
  enc0 = 0; 
}
}

void doEncoder_Expanded() {
  if (digitalRead(encA) == HIGH) {
    if (digitalRead(encB) == LOW) {
      enc0 = enc0 + 1;
    }
    else {enc0 = enc0 - 1;}
  }
  else {
    if (digitalRead(encB) == LOW) {
      enc0 = enc0 - 1;
    }
    else {enc0 = enc0 + 1;}
  }
}


encoder channel A and B are attached to interrupt pins and enc0 is supposed to increase/decrease as motor rotates. But the motor keeps rotating and en0(counting #) is printed as 0 all the time.
Maybe because the resolution of the encoder is 1024 and the geared ratio is 16:1, the Arduino interrupt pins cannot read the signal. (Because of so many countings..)
Is it really the problem of slow interrupt pin rate?
I'm not sure what is the critical problem.. THX

MarkT

Use direct port manipulation for reading the encoder pins, much faster than digitalRead(), and you should get
quite a speed-up.

You can check pin2 (on an Uno) like this
Code: [Select]

  if (PIND & 4)

and pin3
Code: [Select]

  if (PIND & 8)

So something like this will run faster:
Code: [Select]

void doEncoder_Expanded()
{
  byte b = PIND ;
  if (b & 4)
  {
    if (b & 8)
      enc0 -- ;
    else
      enc0 ++ ;
  }
  else
  {
    if (b & 8)
      enc0 ++ ;
    else
      enc0 -- ;
  }
}

Note the copying of PIND into b - this means that we read the state of pin2 and 3 simultaneously and just once - this
prevents any race conditions.
[ I won't respond to messages, use the forum please ]

J Young

Thx for your help.

How can I define PIND then? It seems like the state of encoder pin, but you meant both of the pins, A and B.

Grumpy_Mike


Thx for your help.

How can I define PIND then? It seems like the state of encoder pin, but you meant both of the pins, A and B.


You don't define it,it's already predefined just like HIGH and LOW

MarkT

google knows about direct port manipulation, thats why I mentioned the phrase.

  http://www.arduino.cc/en/Reference/PortManipulation
[ I won't respond to messages, use the forum please ]

J Young

THX both of you.
Now I can expect better accuracy. I'll try!

Go Up