1
$\begingroup$

am 2 weeks old to arduino projects..i had been using timing all this while to control my rover...now, i wanted to shift to using encoders..am facing quite some problems..am using arduino uno and a two amp motor shield..this is code i am trying to use..am using a 8V Li-po battery

http://www.myduino.com/index.php?route=product/product&product_id=170&search=rover+5 (link to rover)

http://www.myduino.com/index.php?route=product/product&product_id=131&search=motor+shield (link to motoshield)

my question is there are four pins coming out of encoders from each side...what i did was connected the red and black to 5V and GND respectively and the white and yellow of the first encoder to pin 2 and the white and yellow of second encoder to pin 3...is what am doing correct??

and sometimes when i use this code, in the motorshield both the green and red light starts thereby stalling the motor..why does that happen?

can anyone of you suggest a link to a simple encoder code to make the motors move forward in a straight using feedback..

thanks

    // interupt 0 -> pin 2
    // interupt 1 -> pin 3

    volatile unsigned long positionL = 0;  //vehicle position count from left encoder
    volatile unsigned long positionR = 0;  //vehicle position count from right encoder

    int motorLa = 5;
    int dirLa = 4;
    int motorRa = 7;
    int dirRa = 6;

    void setup(){
      pinMode (motorLa, OUTPUT);
      pinMode (dirLa, OUTPUT);
      pinMode (motorRa, OUTPUT);
      pinMode (dirRa, OUTPUT);
      Serial.begin(9600);
    }

    void loop(){
      moveFWD(5300);
      delay(2000);
      moveREV(3000);
      delay(2000);
      while(1);
    }

    void encoder1(){
      positionR++;
    }

    void encoder2(){
      positionL++;
    }


void moveFWD(unsigned int x){
      positionL=0;
      positionR=0;
      attachInterrupt(0, encoder1, CHANGE);   
      attachInterrupt(1, encoder2, CHANGE);
      digitalWrite(dirLa, LOW); // Left a Forward 
      digitalWrite(dirRa, HIGH); //Right a Forward          
      while((positionL <= x) || (positionR <= x)){

        if (positionL > positionR){
          analogWrite(motorLa, 220);
          analogWrite(motorRa, 255);
          }  

        else if (positionR > positionL){
          analogWrite(motorRa, 220);
          analogWrite(motorLa, 255); // Sets the motor speed at a value of 180            }

        else {
          analogWrite(motorRa, 255);
          analogWrite(motorLa, 255); // Sets the motor speed at a value of 180            }        

        Serial.print(positionL); // This prints the current value of positionL in the serial monitor on the computer.
        Serial.print("\t"); // This creates a tab on the monitor 
        Serial.print(positionR);
        Serial.println(); // This creates a new line to print on         
      }        

      // Stop all motors
      analogWrite(motorLa, 0);
      analogWrite(motorRa, 0);

      // Disables the encoders interrupt
      detachInterrupt(0);
      detachInterrupt(1);
    }

void moveREV(unsigned int x){
      positionL=0;
      positionR=0;
      attachInterrupt(0, encoder1, CHANGE);   
      attachInterrupt(1, encoder2, CHANGE);
      digitalWrite(dirLa, HIGH); // Left a Forward 
      digitalWrite(dirRa, LOW); //Right a Forward    
     while((positionL <= x) || (positionR <= x))
      {

       if (positionL > positionR){
          analogWrite(motorLa, 20);
          analogWrite(motorRa, 200);
        }  

      else if (positionR > positionL){
          analogWrite(motorRa, 20);
          analogWrite(motorLa, 200); // Sets the motor speed at a value of 180           }  
        else{
          analogWrite(motorLa, 200); // Sets the motor speed at a value of 180           analogWrite(motorRa, 200);
          }
       Serial.print(positionL); // This prints the current value of positionL in the serial monitor on the computer.
        Serial.print("\t"); // This creates a tab on the monitor 
        Serial.print(positionR);
        Serial.println(); // This creates a new line to print on  
        } 
      // Stop all motors
      analogWrite(motorLa, 0);
      analogWrite(motorRa, 0);

      // Disables the encoders interrupt
      detachInterrupt(0);
      detachInterrupt(1);
    }
$\endgroup$
1
$\begingroup$

I believe your encoders provide incremental quadrature. Yes, red and black are probably power and ground, (but please consult your data sheet!) and the other two wires provide a pattern of square waves that indicate the direction of motion as well as an incremental count of distance traveled.

Typically, microcontrollers provide a quadrature decoder in hardware so you can just read off the distance traveled as a number. But it isn't too hard to write yourself. However, you will need 4 interrupts and i believe the Arduino Uno only provides 2. You could probably poll the I/O lines, as long as the quadrature pulses aren't too short or your code is too slow to keep up.

If you don't care about the direction. For example if your gear-train is non-backdrivable. You can simply use a single quadrature wire under the assumption that the motor is always spinning in the direction you commanded. You should set up the ISR to trigger on a change. then increment (or decrement) a variable for distance traveled. You should probably also record the time so you can turn it into a speed. Note that this is not a very good way of doing things because of debouncing. Think about if the encoder is right on the edge between two states, it will bounce back and forth between high and low. Your code will assume each transition is some distance traveled, when in reality no motion occurred.

After you iron out all the encoder business, you need to implement speed control. Basically, you want both motors to travel at the same measured speed. I will only describe proportional control, but you may want to add the other terms. Here is the gist of it:

  float error = target_speed - measured_speed;
  int control_value = (P * error) + last_control;
  last_control = control_value

Note that control_value is the PWM value to give to the motor. So you should cap it appropriately. target_speed and measured_speed are in the units of some speed, whatever makes sense for your system. And P is the gain.

$\endgroup$

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.