0
$\begingroup$

I am making an Arduino-controlled differential drive robot, and I am having the following problems:

  • the encoders built into the motors are being used for measuring the rotary displacement, and while running they will randomly start counting the opposite direction of their rotation for a second then start counting the right direction again

  • What can I do in terms of differential and integral control that will lead to a consistent turn every time?

MY CODE:

'#'include <DueTimer.h>

'#'define MOT1 5 //right motor speed pin (PWM)

'#'define MOT2 6 //left motor speed pin (PWM)

'#'define DIR1 4 //right motor direction pin

'#'define DIR2 7 //left motor direction pin

'#'define EN1A 10 //right motor encoder phase A pin

'#'define EN1B 11 //right motor encoder phase B pin

'#'define EN2A 8 //left motor encoder phase A pin

'#'define EN2B 9 //left motor encoder phase B pin

volatile long right_enc = 0;

volatile long left_enc = 0;

volatile long left_enc1 = 0;

volatile long left_enc_diff = 0;

void setup() {

  // put your setup code here, to run once:
 //set pin mode, attach external interrupts to encoders with ISR vector, set initial direction and speed of motors.

  pinMode(MOT1, OUTPUT); // Set ENC1 as output

  pinMode(DIR1, OUTPUT); // Set DIR1 as output

  pinMode(MOT2, OUTPUT); // Set ENC2 as output

  pinMode(DIR2, OUTPUT); // Set DIR2 as output

  attachInterrupt(digitalPinToInterrupt(EN1A), countRight, CHANGE);

  attachInterrupt(digitalPinToInterrupt(EN2A), countLeft, CHANGE);

  digitalWrite(DIR1, HIGH);

  digitalWrite(DIR2, LOW);

  Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:

left_enc = 0;

//left_enc1 = left_enc;

while (-left_enc < 1023){

analogWrite(MOT2, 100);

analogWrite(MOT1, 50);

Serial.println("left_enc: ");

Serial.print(-right_enc);

Serial.println(" ");

Serial.print(" ");

}

analogWrite(MOT2, 0);

analogWrite(MOT1, 0);

for (;;) {
   // statement block
}

}

void countRight(){

  if (digitalRead(EN1A)){

    if (digitalRead(EN1B)){right_enc++;}

    else if (!digitalRead(EN1B)) {right_enc--;}

  }
}

void countLeft(){

  if (digitalRead(EN2A)){

    if (digitalRead(EN2B)){left_enc++;}

    else if (!digitalRead(EN2B)) {left_enc--;}

  }
}

=======

$\endgroup$

2 Answers 2

1
$\begingroup$

What kind of motors are you using? Because the behaviour you describe makes me think of a brushless motor, due to the fact that you have a rotating magnetic field having the rotor spin. But in the beginning it will not necessary start on the right direction (during a very very little lapse of time).

Your program's frequency can also be related to this behaviour. So, have you tried with only one encoder (for this you need to comment all the code calling the interrupts you are not using)? If it occurs only when you have 2 encoders then your micro-controller may not be fast enough (or your motor is to fast).

Have you tried this library ? Usually this code is giving good results!

$\endgroup$
3
0
$\begingroup$

This is just a guess, but I think that your measuring cycle is too slow (not enough measurements per time, therefore the phases get mixed up). Does this occur, when the motors turn slower?

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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