Let's Make Robots!

rover 5 hall effect encoder testing

I'm a beginner to robotics control so everything I posted here may be wrong. I'd appreciate any comments.

Long story in short. It all begin when I bought a 4WD arduino robotics car from dx.com a month ago(http://dx.com/p/multi-function-4wd-arduino-robot-raider-car-kits-128715). It was a pretty good deal at that time. After learning arduino, I programmed robotics car to move without problem. However when I started to do basic line tracking, I found that there is no way to make the car perform in the expected way. For example, a simple command like move it in straigh line is not easy (nor even mention turn a speicific degree). Then I did my search on control theory and learned some odometry, PID and encoder.

I realized that I need a encoder first to do real feed back adjustment. So I looked up encoder solution. All are quite expensive... I found rover 5 which only cost less than $60 with 4 quadracture encoder.

When it arrived, I opened the motor inside immediately. I found that optical encoder was replaced by hall effect encoder. There is a manetic ring tied to the gear next to motor. There are four wires: red (5V), black(gnd), yellow (s1) and white (s2). I read the article about quadratic encoder from http://letsmakerobots.com/node/24031 . I wrote the following arduino to test if all 4 encoder works.

The test is to connect yellow and white to pin 2 and pin3 of arduino uno. Rotate wheel for 360 degree ( can't measure it exactly but it doesn't really matter to my concern).

static long s1_counter=0;

static long s2_counter=0;


void setup()




  attachInterrupt(0, write_s1, CHANGE); /* attach interrupt to pin 2*/

  attachInterrupt(1, write_s2, CHANGE); /* attach interrupt to pin 3*/

  Serial.println("Begin test");




void loop()




void write_s1()



  Serial.print("S1 change:");



void write_s2()



  Serial.print("S2 change:");




I roated almost 360 degree for each of them.

For L1 wheel, I got counter 85 times for S1 and 160 for S2. There' pattern of S1 and S2 change. S1,S2, S1,S2, S1, S2, S2, S1, S2, S2, S2, S2 (it repeats this pattern)

For L2 wheel, I got counter 165  times for S1 and 166 for S2. The pattern is S1, S2, S1, S2...

For R1 wheel, I got 165 times for S1 and 205 for S2. I can't find the pattern.

For R2 whell, I got counter 167 times for S1 and 168 for S2. The pattern is S1, S2,S1, S2..

I repated the test for couple times. The counter either equal to each other as L2 and R2 or quite bizzard as L1 and R1.

My question: Are L1 and R1 are defective items as counter doens't match to each other?

First of all, the test program is based on my instinct. I haven't read the enocder library to figure out what they are doing. But in genearl, counting the pulse in one round. But I'm not sure if counting makes more sense when applying XOR gate to yellow and white wire.

My tools are limited. So if you have any clues, I'd really appreciate it.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

The Rover 5 User Manual states that the encoder count is 1000 per 3 wheel rotations or 333.33 per single wheel rotation.  This is not correct.

I had to take the darn thing apart to see that there are three sets of step down gears between the motor and the drive wheel.  The first set is a 4.166:1 ratio from the motor to the encoder wheel. The encoder wheel has eight magnetic poles that generate 8 state changes per rotation.

Then two more gear sets (5:1 and 4.166:1) that total a 20.833:1 ratio from the encoder wheel to the final drive wheel.  20.83 * 8 = 166.66.  There are 166.66 encoder state changes (counts) per single drive wheel rotation.  Therefor 333.33 encoder counts represent TWO drive wheel rotations not ONE.

If you are ever into dead-reckoning navigation, this information may help to make sense of what is going on.

Also, the hall effect encoder output pulses are extremel dissimilar from each other.  When measured, the encoder timing pulses fall into groups of eight, as you might expect.  Each pair of magnetic poles generates the same pulse width duration each time the encoder wheel turns around; but the distance bewteen each pair is wildly different.  One cannot instantaneously measure speed from just one encoder pulse, or even two or four pulses.

I use an eight cell ring buffer to store eight pulse times.  From that I can get a good, consistent average that I use to calculate motor speed.

One tip:

Avoid Serial.print() function calls in an interrupt function. This will take too much time, you will loose encoder countings. Use Serial.print() only in the loop function

I measured the overhead of serial print function by computing differences using micros function. It is  100 us. 

It is said that encoder generate 1000 pusle per 3 rounds. Let's assume 1 second per round roated by hand. It is 0.003s (=3000us) per pulse. I believe that chances are very slim to miss counting.


Your measurement might be right, but the 100µs is only the time to copy the characters into the UART buffer. To send a single character over the UART line at 115200baud takes 87µs. Your UART buffer will be overrun very quickly. Reduce the amount of send characters in the interrupt routine to a minimum, like this example:

void loop()
  Serial.print(s1_counter, HEX);
  Serial.print(", ");
  Serial.println(s2_counter, HEX);


void write_s1()

void write_s2()
  if (s2_counter && s2_counter % 20 == 0)


Here only '1' or '2' is send in the interrupt routine. The counters will be send every 5seconds in the loop function.


The suggestion you proposed in loop is a good point indeed. But I remove all Serial.print in interrupt call back function.

Although 5 seconds interrupt is a race condition, as long as I don't roate wheel in every 5 seconds. It should be avoided.

The count of pulse per one rotation is pretty stable. It is  between 166 -170  times for two wheels which two encoders deliver close counts.

For the other two wheels, which doesn't deliver close count of pulse between two encoders, one of encoder deliver count around 166-170, while another enocder deliver either 80 or 200.

The results are almost the same as my previous test. I believe that each encoder in those two wheels are defective.

Ok, I agree with your diagnostics now. The encoders are defective. But I have no solution to fix this problem.

I sent email to robotshop.com. They are going to replace my defective chassis.  

Thanks for your help. Otherwise I will work in the dark...

I'm not sure if you used rover 5 chassis before. I'm going to order its dirver shield. I want to see how XOR gate improve the counting, although I'd believe that software can solve the XOR gate internally.

I will compare hardware approach and software approach later.


the way your code is written, I can't see anything would occur. Your void loop() {} is empty.

I attached two call back function to two interrupts pin. Those two pin connect to yellow and white wires from encoder sensor. As long as signal change, counter increase and output to serial.

Stupid me didn't notice the interrupts. /me bows his head in shame and shambles to the corner. :)