Motor Encoder Problem

Hello,
I'm building a little robot with a differential drive. It has a hall effect encoder attached to each of its two motors. When calibrated on a given surface, it's capable of rotating to any value of theta with respectable accuracy; however, it will over shoot its stopping point on a smoother surface if it was calibrated on one more rough.
If I run it at different speeds on the same surface, it'll be fine; it will hit its stopping point every time. So, I don't think the arduino is having trouble reading the pulses. It's only when I change surfaces. I know that the motors draw more current when under a greater load, and the error between surfaces seems to be pretty well correlated with it. (I have tested it my multimeter.)
Thoughts? I would appreciate it!

How does the hall effect encoder detect the motor position?

...R

Robin2:
How does the hall effect encoder detect the motor position?

...R

I don't wanna speak for the OP, but I use hall encoders in my job and they usually have two signals (sin/cos) with a 90 degree offset providing you exact position in an analog fashion. Once the sensor has been calibrated at a reference point to be 0 degrees you will always know absolute position. And the nice thing is that as long as you don't move the sensor mounting you never have to calibrate again and your reference position never changes even after restarts or new software.

Back to the original question, can you give a little more info on the motors in your project? If you're doing a differential drive then I am assuming you're using some kind of brushless synchronous motors? How are you controlling them?

Also when you say the sensors are "Calibrated on a given surface", what does that mean exactly? Does that mean the axial offset between the magnet and the sensor? Or does that mean the rotational offset being aligned to a 0 degree reference?

m4778:
I don't wanna speak for the OP, but I use hall encoders in my job and they usually have two signals (sin/cos) with a 90 degree offset providing you exact position in an analog fashion. Once the sensor has been calibrated at a reference point to be 0 degrees you will always know absolute position. And the nice thing is that as long as you don't move the sensor mounting you never have to calibrate again and your reference position never changes even after restarts or new software.

I believe you are describing the signals that the hall encoders send to the Arduino.

My question was

How does the hall effect encoder detect the motor position?

...R

What you could do is have a sensor for the motor current, possibly integrate it and let it affect the setpoint presuming you are using a PID or similar to calculat ethe final position.

Robin2:
How does the hall effect encoder detect the motor position?

...R

The encoder puts out two square waves 90 degrees out of phase. I've just been counting the pulses with an Arduino via interrupts.

m4778:
I don't wanna speak for the OP, but I use hall encoders in my job and they usually have two signals (sin/cos) with a 90 degree offset providing you exact position in an analog fashion. Once the sensor has been calibrated at a reference point to be 0 degrees you will always know absolute position. And the nice thing is that as long as you don't move the sensor mounting you never have to calibrate again and your reference position never changes even after restarts or new software.

Back to the original question, can you give a little more info on the motors in your project? If you're doing a differential drive then I am assuming you're using some kind of brushless synchronous motors? How are you controlling them?

Also when you say the sensors are "Calibrated on a given surface", what does that mean exactly? Does that mean the axial offset between the magnet and the sensor? Or does that mean the rotational offset being aligned to a 0 degree reference?

I'm using a couple of Polulu's 25d gear motors (approx. 75rpm) with the included quadrature encoders and a basic H bridge from Sparkfun.

And, I've been synchronizing the motors via feedback from the encoders.

By calibrating, I mean that I measure how many pulses it takes for it to do a 360. This is where the problem is. Obviously, there should be a theoretical number of pulses that yield a 360 turn regardless of the surface (given that the motors are synchronized).

At the moment, I'm inclined to think that there's some kind of electrical noise or something that's causing the Arduino to miss pulses. I don't know.

I'll have access to an oscilloscope soon and plan to check the signal.

As i can imagine ther can be two reasons for the motors behavior:

  • The surface actually affects the distance traveled somehow. Either by traveling less due to skid on difficult surfaces or by overshoot om easy ones
  • Your regulation algorithm is not properly tuned

tylerstorm:

Robin2:
How does the hall effect encoder detect the motor position?

...R

The encoder puts out two square waves 90 degrees out of phase. I've just been counting the pulses with an Arduino via interrupts.

Like the other person, you are looking at the wrong end of the encoder. What I am trying to find out is what is the encoder detecting so that it knows when to produce its pulses?

...R

Hi, can you see if the error is greater with the speed of the motors, most of the time just starting the motor and turning the wheel will cause slip, the encoder registers wheel turn, but there is no traction movement. Same when you come to a stop, try as slow a movement as possible and check.
The surface friction will be the problem here, what sort of tyre is on the wheels.
A glass surface will be different to a sandpaper surface.

Can you please post your code, I assume you are using interrupts to detect your encoder pulses?
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png or pdf

Tom... :slight_smile:

volatile int Lcount = 0;
volatile int Rcount = 0;

int STBY = 7;  //Standby
//Motor L
int PWMA = 6; //Speed control 
int AIN1 = A1; //Direction
int AIN2 = 8; //Direction
//Motor R
int PWMB = 5; //Speed control
int BIN1 = A0; //Direction
int BIN2 = 12; //Direction

//Parsed from serial
int dL=0;   //Direction of left motor
int dR=0;   //Direction of right motor
int deltaS=0;  //Number of encoder counts to be covered after zero turn.

int pwr=0;

void setup(){
  Serial3.begin(9600);
  attachInterrupt(0, count_1, RISING);  //Channel A
  attachInterrupt(1, count_2, RISING);  //Channel A                      
  //attachInterrupt(5,    ,    );          //Left Motor B
  //attachInterrupt(4,     ,    );        //Right Motor B
  pinMode(STBY, OUTPUT);
  pinMode(PWMA, OUTPUT);
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(PWMB, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);}

void loop(){
  if (Serial3.available()){
    char c = Serial3.read();
    if (c == 'M'){               
        dL = Serial3.parseInt();   //Direction of Left Motor 1 or 0
        dR = Serial3.parseInt();   //Direction of Right Motor 1 or 0
        deltaS = Serial3.parseInt();  //Number of encoder pulses to be covered
        Serial3.print(Rcount);         //This is just for diagnostics purposes to keep track of how many encoder pulses were logged before it's zeroed out
        Serial3.println();
        Serial3.print(Lcount);
        Serial3.println();
        Rcount=0;
        Lcount=0;
        
        while(true){
          
          if (deltaS-(Rcount+Lcount)/float(2) > 500){                        //This slows it dows before it stops to minimize the distance it coasts.
            pwr=200;}
          else{
            pwr=int((deltaS-(Rcount+Lcount)/float(2))*.3 + 50);}
            
          if(Lcount<deltaS){                                               //This synchronises the speed of each motor.
            if(Rcount-Lcount>0){
              move(1,pwr+5,dL);}
            else{
              move(1,pwr-5,dL);}}
              
          if(Rcount<deltaS){                                             //This kills the motor when deltas is reached, and it does not yet take coasting into account.
            move(0,pwr,dR);}                                             //The coasting doesn't account for the amount of error on different surfaces; it coasts, at most, a centimeter.
          else{
            stop();                                                      
            break;}}}

if (c == 'S'){
      stop();}
if (c == 'G'){
      digitalWrite(STBY, HIGH);}
}}

void count_1(){
  Lcount += 1;}

void count_2(){
  Rcount += 1;}

void move(int motor, int speed, int direction){
  digitalWrite(STBY, HIGH); //disable standby
  boolean inPin1 = LOW;
  boolean inPin2 = HIGH;
  if(direction == 1){
    inPin1 = HIGH;
    inPin2 = LOW;}
  if(motor == 1){
    digitalWrite(AIN1, inPin1);
    digitalWrite(AIN2, inPin2);
    analogWrite(PWMA, speed);}
  if(motor ==0){
    digitalWrite(BIN1, inPin1);
    digitalWrite(BIN2, inPin2);
    analogWrite(PWMB, speed);}}
    
void stop(){   
  digitalWrite(STBY, LOW);}

TomGeorge:
Hi, can you see if the error is greater with the speed of the motors, most of the time just starting the motor and turning the wheel will cause slip, the encoder registers wheel turn, but there is no traction movement. Same when you come to a stop, try as slow a movement as possible and check.
The surface friction will be the problem here, what sort of tyre is on the wheels.
A glass surface will be different to a sandpaper surface.

Can you please post your code, I assume you are using interrupts to detect your encoder pulses?
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png or pdf

Tom... :slight_smile:

The error is too great to be due to slippage. (I have run tests at many speeds.) And, the motors don't put out enough torque for it to happen anyway. It will coast a little bit (up to maybe a half centimeter), but it clearly powers through the stopping point. Something must be causing the Arduino to miss pulses. They're read via interrupts by the way.

The encoders put out 12 cpr on each channel. Taking the gear ratio into account, it puts out 898 pulses per revolution of the output shaft. And, the error seems to be the same whether I use both channels or not.

Do you think the pwm to the motors could be causing interference with the interrupts maybe?

I'll get started on a schematic. I don't have one, currently. Do you have any specific questions about the circuit?

I've tested the voltage that the encoders receive. They're powered from a Polulu voltage regulator, and I'm using a 7.4v 2200mah Lipo battery, the voltage of which does not drop much even when the motors are nearly stalled.

TomGeorge:
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png or pdf

Dropbox link to a hand drawn circuit.

Thanks!

I have been trying (in a few posts) to get you to tell us how the hall-effect sensors detect the position of the motor.

I presume there is NOT an encoder disk because they are usually associated with optical encoders.

Perhaps there are several magnets arranged on a disk that are detected by the hall-effect sensor?

But what I am really concerned about is that the sensor may be detecting the current flowing in the motor coils and, if that is the case, the fact that more current flows when the surface is rough may upset the detection.

Regardless of how the detection works it may be useful to take one of the motors out of the robot and write a short sketch just to read the decoder while you put different loads on the motor shaft - perhaps with your finger (if it is a small motor).

...R

Robin2:
I have been trying (in a few posts) to get you to tell us how the hall-effect sensors detect the position of the motor.

I presume there is NOT an encoder disk because they are usually associated with optical encoders.

Perhaps there are several magnets arranged on a disk that are detected by the hall-effect sensor?

But what I am really concerned about is that the sensor may be detecting the current flowing in the motor coils and, if that is the case, the fact that more current flows when the surface is rough may upset the detection.

The encoders each use a magnetic disc with a stationary hall effect sensor as you correctly imagined. Here's a link to the gear motor with its attached encoder: CLick here.

I ordered a couple optical encoders; they should be here soon. Then I'll be able to test your hypothesis. I hope you're right.

Thanks for your help!

Tyler

I have been using several of those motors without any problem. So i doubt that the problem is in the encoder. The most likely reason is wheel slip, negative when accelerating or driving over difficult surfaces, positive when braking. Not much to do about except limiting acceleration/deacceleration. One solution would be having a idler wheel with an optical encoder that measures the traveled distance. Another method would be correcting the distance reported by the encoder with a value determined by the integetal of the motor current

tylerstorm:
The encoders each use a magnetic disc with a stationary hall effect sensor as you correctly imagined. Here's a link to the gear motor with its attached encoder: CLick here.

Thanks. In that case I don't imagine the encoders are causing the problem. I had not realized those motors use hall-effect encoders.

...R

Hi, you can post you pdf to the forum using the Attachment and other options.
What info do you have on the encoders, can you detect an output, a lot of encoders use open circuit collector outputs.
This means you need to attach say a 10K resistor from each of the encoder outputs to +5V to supply current to the output transistors.

Tom.... :slight_smile: