Go Down

#### rajanjamu

##### Oct 25, 2011, 11:31 am
Hey,

I have been trying to calculate the velocity for two motors, using encoder interrupts, which later would be used to apply PID control. Velocity Calculation code gives out correct velocity till a certain rpm (goes up as input voltage goes up), but then starts giving negative velocity (goes down as voltage goes up). Following is the code:

Code: [Select]
`#define DirectionPin 3    // direction pinint encoder0Pos = 0,oldPos = 0;  // encoder positionint dir = 0;unsigned long oldTime, newTime, dt;float vel;void setup() {  Serial.begin(9600);            // set up Serial library at 9600 bps  pinMode(DirectionPin, INPUT); // encoder pin on interrupt 0 (pin 2)  attachInterrupt(5, doEncoder, RISING);  oldTime = millis(); }void loop() {  newTime = millis();              // read the current time stamp  dt = newTime - oldTime;           // compute delta time  oldTime = newTime;    vel = (float) ((encoder0Pos - oldPos) * 4.25) / (dt);  // velocity estimate in ms    int temp = encoder0Pos - oldPos;  oldPos = encoder0Pos;    Serial.println(vel);}// Interrupt routinevoid doEncoder(){  dir = digitalRead(DirectionPin);     // read the direction of motor  if (dir == HIGH) {encoder0Pos = encoder0Pos - 1;}  else {encoder0Pos = encoder0Pos + 1;}  }`

I need to connect three of these motors later in near future, but this code seems to have lot of interrupt overhead. Interrupt frequency is around 8000 ticks per second per motor.

#### AWOL

#1
##### Oct 25, 2011, 12:18 pm
You could get rid of the digitalRead in the ISR, and use the fast version instead.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

#### rajanjamu

#2
##### Oct 25, 2011, 12:30 pm
I did the same. Following is the code.

Code: [Select]
`#define DirectionPin 3    // direction pinint encoder0Pos = 0,oldPos = 0;  // encoder positionint dir = 0;unsigned long oldTime, newTime, dt;float vel;void setup() {  Serial.begin(9600);            // set up Serial library at 9600 bps  pinMode(DirectionPin, INPUT); // encoder pin on interrupt 0 (pin 2)  attachInterrupt(5, doEncoder, RISING);  oldTime = millis(); }void loop() {  newTime = millis();              // read the current time stamp  dt = newTime - oldTime;           // compute delta time  oldTime = newTime;    vel = (float) ((encoder0Pos - oldPos) * 4.25) / (dt);  // velocity estimate in ms    int temp = encoder0Pos - oldPos;  oldPos = encoder0Pos;    Serial.println(vel);}// Interrupt routinevoid doEncoder(){  dir = (PINE & 0b00100000) >> 5;  if (dir == HIGH) {encoder0Pos = encoder0Pos - 1;}  else {encoder0Pos = encoder0Pos + 1;}}`

I could notice some improvement but, I finally need to implement this with three motors in parallel. Connecting two of them, I faced the same problem again. Any solutions?

#### AWOL

#3
##### Oct 25, 2011, 12:37 pm
That wasn't quite what I meant.
I see no reason here that "dir" should be global.
Either:
Code: [Select]
`  if (digitalReadFast(DirectionPin) {encoder0Pos = encoder0Pos - 1;}  else {encoder0Pos = encoder0Pos + 1;}` or
Code: [Select]
`  if ((PINE & 0b00100000) >> 5) {encoder0Pos = encoder0Pos - 1;}  else {encoder0Pos = encoder0Pos + 1;}`
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

#### rajanjamu

#4
##### Oct 25, 2011, 03:03 pm

I will try that soon and post my results here !

#### AWOL

#5
##### Oct 25, 2011, 03:31 pm
I forgot: encoder0Pos should be declared "volatile"
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

#### rajanjamu

#6
##### Oct 26, 2011, 09:38 am
Hey,

May I know the reason for declaring it 'volatile'?

By the way, forgot to mention, Interrupt frequency is around 12646 counts per sec per motor.
(1024 Counts per Rotation and 741 Rotations per Minute (RPM))

I tested my motor with your suggestions incorporated. It (two motors together) still gives erroneous velocity values.

Would you suggest me to consider following options?

• Analog PID Controller (using resistors, Op-Amp and Capacitors)

• Use of Motion Control Chip (PID Controller - LM629)

#### AWOL

#7
##### Oct 26, 2011, 10:05 am
Quote
May I know the reason for declaring it 'volatile'?

Sometimes, the reference material is a little deficient.
Not in this case, however:
http://arduino.cc/en/Reference/Volatile
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

#### Jack Christensen

#8
##### Oct 26, 2011, 02:05 pm

I forgot: encoder0Pos should be declared "volatile"

And should be accessed atomically in loop() ?

#### AWOL

#9
##### Oct 26, 2011, 02:10 pm
Good point.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Go Up

Please enter a valid email to subscribe