Micro Metal gear motor with shaft encoder

Hi ,

I am new here. I am working on micro metal gear with shaft encoder.I am trying to get exact 90 degree rotation in the wheel. But I couldn't get the exact turning , each time it slips the angle. please find my program below and give some solution.

  1. Micro Metal gear - Pololu - 298:1 Micro Metal Gearmotor HP 6V with Extended Motor Shaft

  2. Encoder - Pololu - Optical Encoder Pair Kit for Micro Metal Gearmotors, 5V

  3. Program:-


int motorRightPositive = 6; 
int motorLeftPositive = 9; 
int motorRightNegative = 5; 
int motorLeftNegative = 10; 

int encodervariable=0;
 int encoder0PinA = 3;
 int encoder0PinB = 4;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;


 int encoder0PinA1 = 7;
  int encoder0PinB1 = 8;
  int encoder0Pos1 =0 ;
 int encoder0PinALast1 = LOW;
 int n1 = LOW;
 
 
 void setup() { 
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   pinMode (encoder0PinA1,INPUT);
   pinMode (encoder0PinB1,INPUT);
   Serial.begin (9600);
   
   pinMode (motorRightPositive, OUTPUT);  
   pinMode (motorLeftPositive, OUTPUT);
   pinMode (motorRightNegative ,OUTPUT);
   pinMode(motorLeftNegative, OUTPUT);
  
    analogWrite (motorRightPositive, 100);
     analogWrite (motorRightNegative, 0); 
     analogWrite (motorLeftPositive, 0);
     analogWrite (motorLeftNegative, 100); 
   
 } 

 void loop() { 
   n = digitalRead(encoder0PinA);
   n1 = digitalRead(encoder0PinA1);
   
   
     if(encoder0Pos!=-453 )
   {
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
     encodervariable = encoder0Pos;
     Serial.print (encodervariable);
     Serial.print("Left");
     Serial.print ("//");
   } 
 }
   encoder0PinALast = n;
   
   
   
   
   if(encoder0Pos1!=-420 )
   {
 if ((encoder0PinALast1 == LOW) && (n1 == HIGH)  ) {
     if (digitalRead(encoder0PinB1) == LOW) {
       encoder0Pos1--;
     } else {
       encoder0Pos1++;
     }
    Serial.print (encoder0Pos1);
     Serial.print("Right");
     Serial.print ("/");
   } 
   }
   encoder0PinALast1 = n1;
   
   
  
    if(encoder0Pos1==420 || encoder0Pos1==-420) 
   {
     
        encoder1();
   }
   
   if(encodervariable==-453 )
   {
     
 encoder();
   }
   
  
 } 
 
 void encoder1()
 {
   analogWrite (motorRightPositive, 0);
     analogWrite (motorRightNegative, 0); 
 }
 
 void encoder()
 {
  analogWrite (motorLeftPositive, 0);
     analogWrite (motorLeftNegative, 0); 
 }

Serial.print @ 9600 baud will take a long long time compared to the spacing of
encoder pulses, so you will be losing pulses.

Typically people do their encoder processing in an interrupt routine to avoid
such issues, there are numerous examples in these forums so have a search?

As a stop-gap change the baud rate to 115200 ??

You didn't specify which type of encoder you got. (3.3V or 5V).
Also, where did you get the code ? Did you write this program yourself ? If so , is this your first attempt at writing code for rotary encoders ?

Also those gear ratios are not exact ratios, you need to know the exact
ratio (as a ratio) to do encoder pulse counting accurately. Counting the
teeth on the gears is one way to find this out :slight_smile:

MarkT:
Serial.print @ 9600 baud will take a long long time compared to the spacing of
encoder pulses, so you will be losing pulses.

Typically people do their encoder processing in an interrupt routine to avoid
such issues, there are numerous examples in these forums so have a search?

As a stop-gap change the baud rate to 115200 ??

Thank you , I set with 115200 baud,it didn't miss the signal.

raschemmel:
You didn't specify which type of encoder you got. (3.3V or 5V).
Also, where did you get the code ? Did you write this program yourself ? If so , is this your first attempt at writing code for rotary encoders ?

I am using 5v encoder. yes, this is the first time using the encoder and I did write program by myself. pls help me . how to achieve the angle properly?

Hi everyone,

Now, I can get a proper rotation but dono is it right or wrong form? still I get the rotation and another problem facing here is wheel slips after some rotation. how to solve this?

Did you research quadrature encoder code ?

Yes , I tried it but nothing helps. But I came up with modified code but here I am facing problem that when one motor completes it rotation , it affects the other motor and couldn't get exact same position. Pls tell what wrong with my program.

Code:-

int motorRightPositive = 6; 
int motorLeftPositive = 9; 
int motorRightNegative = 5; 
int motorLeftNegative = 10; 
int motorRightEnable_pin =12;
int motorLeftEnable_pin=13;

int encodervariable=0;
 int encoder0PinA = 3;
 int encoder0PinB = 4;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;

int encodervariable1=0;
 int encoder0PinA1 = 7;
  int encoder0PinB1 = 8;
  int encoder0Pos1 =0 ;
 int encoder0PinALast1 = LOW;
 int n1 = LOW;
 
 
 void setup() { 
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   pinMode (encoder0PinA1,INPUT);
   pinMode (encoder0PinB1,INPUT);
   Serial.begin (115200);
   
   pinMode (motorRightPositive, OUTPUT);  
   pinMode (motorLeftPositive, OUTPUT);
   pinMode (motorRightNegative ,OUTPUT);
   pinMode(motorLeftNegative, OUTPUT);
   pinMode(motorLeftEnable_pin, OUTPUT);
   pinMode(motorRightEnable_pin, OUTPUT);
    

     
   
 } 

 void loop() { 
   digitalWrite(motorLeftEnable_pin, HIGH);
    digitalWrite(motorRightEnable_pin, HIGH);
   analogWrite (motorRightPositive, 50);
     analogWrite (motorRightNegative, 0); 
     analogWrite (motorLeftPositive, 50);
     analogWrite (motorLeftNegative, 0); 
   
   n = digitalRead(encoder0PinA);
   n1 = digitalRead(encoder0PinA1);
   
    
   
     if(encodervariable!=500 )
   {
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
     encodervariable = encoder0Pos;
     Serial.print (encodervariable);
   //  Serial.print("Left");
    // Serial.print ("//");
   } 
 }
   encoder0PinALast = n;
    
   if( encodervariable1!=-864 )
   {
 if ((encoder0PinALast1 == LOW) && (n1 == HIGH)  ) {
     if (digitalRead(encoder0PinB1) == LOW) {
       encoder0Pos1--;
     } else {
       encoder0Pos1++;
     }
          encodervariable1 =encoder0Pos1;
    
   Serial.print (encodervariable1);
    // Serial.print("Right");
    // Serial.print ("/");
   } 
   }
   encoder0PinALast1 = n1;
   
    if( encodervariable1==-864) 
   {
     
        encoder1();
        
   }
  
   if(encodervariable==500 )
   {
     
 encoder();
   }

 } 
 
 void encoder1()
 {
   digitalWrite(motorRightEnable_pin, LOW);
   analogWrite (motorRightPositive, 50);
   analogWrite (motorRightNegative, 50); 

   delay(1000);
   encodervariable1=0;
   encoder0Pos1 =0 ;
  
 }
 
 void encoder()
 {
   digitalWrite(motorLeftEnable_pin, LOW);
   analogWrite (motorLeftPositive, 50);
   analogWrite (motorLeftNegative, 50);
     
   delay(1000);
   encodervariable=0;
   encoder0Pos=0;
 }

First get rid of delay commands as they are not meant to be used on real working program. If i understand correctly they pause the whole program for 1 sec. when first motor is stopped ?

Kariky:
First get rid of delay commands as they are not meant to be used on real working program. If i understand correctly they pause the whole program for 1 sec. when first motor is stopped ?

But without using delay,How could I stop the motor for certain time?

Study the BlinkWithoutDelay example... Rather than stopping and waiting
you regularly check.

Edit your post and use the CODE TAGS toolbutton "#"

Can you post a photo of a hand-drawn schematic ?
What are you using for a driver ?

MarkT:
Study the BlinkWithoutDelay example... Rather than stopping and waiting
you regularly check.

Thanks Mark ,I will look that .

raschemmel:
Edit your post and use the CODE TAGS toolbutton "#"

Can you post a photo of a hand-drawn schematic ?
What are you using for a driver ?

Here with the code tags

/* Right motor and left motor terminals and enable pin */

int motorRightPositive = 6; 
int motorLeftPositive = 9; 
int motorRightNegative = 5; 
int motorLeftNegative = 10; 
int motorRightEnable_pin =12;
int motorLeftEnable_pin=2;

/* Left encoder connect with pin 3 and 4 */

 int encoder0PinA = 3;
 int encoder0PinB = 4;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;

/*Right encoder connect with pin 7 and 8 */

 int encoder0PinA1 = 7;
  int encoder0PinB1 = 8;
  int encoder0Pos1 =0 ;
 int encoder0PinALast1 = LOW;
 int n1 = LOW;
 
 
 
 void setup() { 
   
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   pinMode (encoder0PinA1,INPUT);
   pinMode (encoder0PinB1,INPUT);
   Serial.begin (115200);
   
   pinMode (motorRightPositive, OUTPUT);  
   pinMode (motorLeftPositive, OUTPUT);
   pinMode (motorRightNegative ,OUTPUT);
   pinMode(motorLeftNegative, OUTPUT);
   pinMode(motorLeftEnable_pin, OUTPUT);
   pinMode(motorRightEnable_pin, OUTPUT);
    

     
   
 } 

 void loop() { 
   
   n = digitalRead(encoder0PinA);
   n1 = digitalRead(encoder0PinA1);
 
 

     if(encoder0Pos!=850 )
   {
   if ((encoder0PinALast == LOW) && (n == HIGH))
   {
     if (digitalRead(encoder0PinB) == LOW) 
     {
       encoder0Pos--;
     } else 
     {
       encoder0Pos++;
     }
     
     Serial.println (encoder0Pos);
     Serial.print("Left");
   
   } 
   motorleftrun();
 }
 
  if(encoder0Pos==850 )
   {
       encoder();
   }

   encoder0PinALast = n;
    
   if( encoder0Pos1!=850 )
   {
 if ((encoder0PinALast1 == LOW) && (n1 == HIGH)  ) {
     if (digitalRead(encoder0PinB1) == LOW) {
       encoder0Pos1--;
     } else {
       encoder0Pos1++;
     }
       
    
   Serial.println (encoder0Pos1);
     Serial.print("Right");
    
   } 
   motorrightrun();
   }
   encoder0PinALast1 = n1;
   
    if( encoder0Pos1==850) 
   {
        encoder1();
   }
 
 }

 
 void encoder1()
 {
   /* I am trying to make "When right motor statisfies the above condition ,function calls
   here and stop motor for 1 second and reset the encoder value" but I couldn't get the result*/
   digitalWrite(motorRightEnable_pin, LOW);
   analogWrite (motorRightPositive, 50);
   analogWrite (motorRightNegative, 50); 
    delay(1000);
   encoder0Pos1 =0 ;  
 }
 
 
 void encoder()
 {
   /* the same above scenerio here*/
   digitalWrite(motorLeftEnable_pin, LOW);
   analogWrite (motorLeftPositive, 50);
   analogWrite (motorLeftNegative, 50);
     delay(1000);
    encoder0Pos=0;
 }
 
 
 void  motorleftrun()
 {
   digitalWrite(motorLeftEnable_pin, HIGH);
     analogWrite (motorLeftPositive, 50);
     analogWrite (motorLeftNegative, 0);
 }
 
void motorrightrun()
 {
   digitalWrite(motorRightEnable_pin, HIGH);
   analogWrite (motorRightPositive, 0);
     analogWrite (motorRightNegative, 50);  
 }

***** I will update schematic soon and by the way I am using L298N motor driver *****

Pls reply and help me

click the MODIFY button in the upper right of the post window.
Highlight all you code.
click the "#" CODE TAGS button on the toolbar above just to the left of the QUOTE button.
click SAVE (at the bottom).
When you post code on the forum, please make a habit of using the code tags "#" button.

If you followed the above instructions correctly the result would look like the following :

 /* Right motor and left motor terminals and enable pin */

int motorRightPositive = 6; 
int motorLeftPositive = 9; 
int motorRightNegative = 5; 
int motorLeftNegative = 10; 
int motorRightEnable_pin =12;
int motorLeftEnable_pin=2;

/* Left encoder connect with pin 3 and 4 */

 int encoder0PinA = 3;
 int encoder0PinB = 4;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;

/*Right encoder connect with pin 7 and 8 */

 int encoder0PinA1 = 7;
  int encoder0PinB1 = 8;
  int encoder0Pos1 =0 ;
 int encoder0PinALast1 = LOW;
 int n1 = LOW;
 
 
 
 void setup() { 
   
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   pinMode (encoder0PinA1,INPUT);
   pinMode (encoder0PinB1,INPUT);
   Serial.begin (115200);
   
   pinMode (motorRightPositive, OUTPUT);  
   pinMode (motorLeftPositive, OUTPUT);
   pinMode (motorRightNegative ,OUTPUT);
   pinMode(motorLeftNegative, OUTPUT);
   pinMode(motorLeftEnable_pin, OUTPUT);
   pinMode(motorRightEnable_pin, OUTPUT);
    

     
   
 } 

 void loop() { 
   
   n = digitalRead(encoder0PinA);
   n1 = digitalRead(encoder0PinA1);
 
 

     if(encoder0Pos!=850 )
   {
   if ((encoder0PinALast == LOW) && (n == HIGH))
   {
     if (digitalRead(encoder0PinB) == LOW) 
     {
       encoder0Pos--;
     } else 
     {
       encoder0Pos++;
     }
     
     Serial.println (encoder0Pos);
     Serial.print("Left");
   
   } 
   motorleftrun();
 }
 
  if(encoder0Pos==850 )
   {
       encoder();
   }

   encoder0PinALast = n;
    
   if( encoder0Pos1!=850 )
   {
 if ((encoder0PinALast1 == LOW) && (n1 == HIGH)  ) {
     if (digitalRead(encoder0PinB1) == LOW) {
       encoder0Pos1--;
     } else {
       encoder0Pos1++;
     }
       
    
   Serial.println (encoder0Pos1);
     Serial.print("Right");
    
   } 
   motorrightrun();
   }
   encoder0PinALast1 = n1;
   
    if( encoder0Pos1==850) 
   {
        encoder1();
   }
 
 }

 
 void encoder1()
 {
   /* I am trying to make "When right motor statisfies the above condition ,function calls
   here and stop motor for 1 second and reset the encoder value" but I couldn't get the result*/
   digitalWrite(motorRightEnable_pin, LOW);
   analogWrite (motorRightPositive, 50);
   analogWrite (motorRightNegative, 50); 
    delay(1000);
   encoder0Pos1 =0 ;  
 }
 
 
 void encoder()
 {
   /* the same above scenerio here*/
   digitalWrite(motorLeftEnable_pin, LOW);
   analogWrite (motorLeftPositive, 50);
   analogWrite (motorLeftNegative, 50);
     delay(1000);
    encoder0Pos=0;
 }
 
 
 void  motorleftrun()
 {
   digitalWrite(motorLeftEnable_pin, HIGH);
     analogWrite (motorLeftPositive, 50);
     analogWrite (motorLeftNegative, 0);
 }
 
void motorrightrun()
 {
   digitalWrite(motorRightEnable_pin, HIGH);
   analogWrite (motorRightPositive, 0);
     analogWrite (motorRightNegative, 50);  
 }