Let's Make Robots!

Servo+QRD1114 Wheel Encoder -- Fail!

I need wheel encoders on my current project. I believe that the gearing of the servo motors combined with the low weight of the robot won't allow the bot to roll by itself very much. Because of that I figure I don't really need full-tilt quadrature encoders. I also only have two of the QRD1114s, and I need two drive units, so each servo only gets one eye.

Here's a few photos showing how I added the eye to the insides of the servo housing. These servos had already been modified for continuous rotation, but this process kills all servo-ness that was left. Now they're just geared motors.

hole cut for the qrd1114

qrd1114 stuck in the hole

"encoder" drawn on a gear with Sharpie

eye attached to Arduino for testing

Finished. Two original wires to power the motor, three additional wires for 5V, GND, and signal for the qrd1114

Signal is pulled high, currently via the Arduino's built in pullup resistors. When the eye is looking at a black portion of the gear the signal is high (800+ at Arduino's analog input), Looking at a white spot it goes low (about 40 at the analog input). This difference _should_ be sufficient to drive a digital input low or high. The Arduino was just for testing, this whole thing will end up being in the XMOS powered bot. Hopefully it'll be enough to drive the XMOS's digital pins high or low too.

The schematic is similar to the one here, minus the 10k pullup resistor. I have not yet actually gotten around to finding out just how many counts per revolution this setup does, hopefully I'll get to that pretty soon ;) After I get that figured out, and have a proper code example working, and get the second one built, I'll likely re-post this as a proper Tip/Walkthrough.

Update 2009 Nov. 12:
Black reads high, white reads low. Seems backwards compared to how I thought I understood things. It's also not working on #2, black and white are both low on #2, anything in front of the sensor reads low, and nothing in front of the sensor reads high. Color be damned. Fun!


Re-update 2009 Nov. 12:
Got #2 working now. It was just a matter of sensor alignment to the gear. After it was all (finally) aligned properly I goobered more thermal prototyping gel into it. Naturally this melted the previous round of hot glue and I had to re-realign the bleeding thing. Double fun! Oh well, #2 is done and working now. I finally have both drive motors for NaMBot #1! Since the base is already built, the next update may actually be a genuine Robot Project page!!! (yay for exclamation marks!!!)


Update 2009 Nov. 14:
Okay, my excitement at having encoder-ed drive motors may have been a bit premature. Got back to the bench today to test just how many pulses are put out in a rotation. Motor #1 seems quite repeatable at 47 counts per revolution. Motor #2 on the other hand is giving me anywhere between 140 and 157 counts per revolution. Now that don't make much sense. They're built identically, I even measure-thingied the resistors before I put em in to make sure they were matched. Why in the hell would one return three times the counts as the other? *grumble*

Here's the Arduino code I'm using to test:

volatile unsigned int encoderPos = 0;

void setup(){
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
  pinMode(13, OUTPUT);
  attachInterrupt(0, doEnc, FALLING);

void loop(){
  if (Serial.available() > 0)
    int incoming = Serial.read();
    if ((char)incoming == '1')
      digitalWrite(13, HIGH);
      encoderPos = 0;
      Serial.println("Counter reset");
      digitalWrite(13, LOW);

void doEnc(){
  Serial.println(encoderPos, DEC);

Wow, I really need to get a code block thingie put in here.


Update 14 Nov. 2009:
Took em both apart to see if I could find anything and got this:

The one on the left is the one that was repeatably returning 47 counts. Interesting that it'd be repeatable with the sharpie wearing off. The right one is the non-repeatable 140+ count one. Gotta figure out how to lower the sensor in the one, and I think I'll try marking the gear half-n-half instead of in quarters.


Update 15 Nov. 2009:
Got em apart and am fiddling with different pullup resistor values. So far nothing I've tried gives reliable results when "seeing" marker ink. With a 3600 Ohm resistor in place it can easily not see actual black plastic, but it still sees markered black plastic.

Before drilling holes in the gears I also tried assembling the servo without the would-be-drilled gear. It would seem that the next gear in the line of sight is close enough to be seen as something there. In other words, no-go on the drilling idea either.

I guess this means it's time to try other methods of marking the gear. Indeed clearance is a problem. A 0.010" (0.254 mm) shim on the gear shaft is enough to bind the gears enough to sieze the servo. And the thickness of the ink is enough to be scraped off in certain areas. So I'm back to having to remelt the glue to move the sensor assembly farther back, and possibly grind some clearance on the housing thing too.

At least it counts toward bot time :D


Update 16 Nov. 2009:
So last night I gave up on the marker thing and drilled a hole in the gear.
Put it on and bigger than shit it doesn't line up to the IR sensor. The edge of the gear that was intact goes directly across the both parts of the sensor.
So I pulled out the wife's heat gun (oddly enough, it's a scrapbooking tool) and melted the hot glue out of the servo, again. Of course the heat gun blows warm enough to put a wobble in the servo casing, but nothing too critical. For testing purposes (again) I rotated the sensor 90 degrees so the LED shines through the hole and stuck the gear on again (leaving the sensor loose, not going to glue it yet). Well, the light shines through the hole just fine. Gear over sensor reads low, hole over sensor reads high (no more analog in, just using a digital).
So I start stacking the other gears on top. Of course the light shines right through the hole, and bounces all over the place and the sensor still sees an object, hole or otherwise... Dammit, says I.

It's like the light is too bright.

If only there were some magical way of making an LED dimmer.

*several hours pass, I do a bit more PHP study, I play with my wowwee bots*

Then this little voice says "HEY STUPID!"

Now I've replaced the 220 Ohm resistor to the LED with a 1k resistor. Can you guess what happened? Yeah! The LED is dimmer, and doesn't reflect all over the freakin place inside the servo! (damn, I'm back to using exclamation points again)

Re-re-re-re(-re?)-assembly will commence shortly. One step at a time. Circuit diagram will follow, providing this idea continues to work.


Update 17 Nov. 2009:
Getting back to this project today finds the first one (the reliable, 47 count one) no longer reliable, returning between 90 and 200 counts per revolution. And the second one even less reliable, it just counts even when sitting still. Fun how sitting a day did... something. Maybe they only work when they're still warm from the hot glue? I dunno, but I grow rather weary of chasing this experiment. I think the theory is sound, it's just the implementation that's eluding me. For the time being I believe I'll see if I can find some other method of putting encoders on this bot so I can get on with the rest of it. I'll likely return to this idea sometime when I've got more attitude and a few less projects to be working on. Unless I don't find some other solution either, in which case I'll likely just bang my head on the desk ;)


Update 28 Nov. 2009:
Played with this off and on the last few days. Added the 7414 schmitt trigger chip, and get reasonably consistent highs and lows now. The first one still gives a reliable 47 counts per rotation, but with a clean and consistent high of 4.45+ volts. It's a little bouncy at the top when held high, but I believe the suggestion of tying the unused analog inputs high or low, and tying the unused 7414 pins will help that.

Motor number two is still giving me fits though, it just won't give an accurate count. I finally yanked the 1k resistor off the LED side, thinking maybe it needed slightly more juice to work well. Using a 10k pot in its place, I twiddled the knob until the sensor could see the white gear just fine. Put the measure thingy on the pot and found ~530 Ohm. A 550 Ohm was the closest I had so I yanked the pot and stuck that in the breadboard. Poke, prod, test, repeat, the sensor sees the white gear, and doesn't see the hole, just like it's supposed to do. Since things are looking swell I soldered the 550 to the sensor module, hold it all in place, and the damned thing doesn't see the white gear again. WTF, over? Poke, prod, curse, repeat, and finally start to wonder if that sensor is bad (too many re-solderings maybe?).

Then, as I'm writing this update to the "how not to add IR encoders to your servos" saga I realize there's an extra resistor still on the breadboard. It seems I failed to remove the 10k pullup from the breadboard after I'd soldered the sensor blob back together, so the signal line's being pulled up twice by two separate 10k resistors. Yank that from the breadboard and bigger than shit it sees the gear just bloody fine. Argh.

*several minutes later*

With the gear train assembled, the housing held together, and the sensor blog held in place by fingers that barely fit, I spun the wheel and got (*drumroll*) 47 counts per revolution(!!!OMG!eleven). I got 47 counts per wheel rotation 6 times, 46 once, and 48 once. Think I'll glue this little bastard in place. Tomorrow. After I see it count 47 a few more times.

Comment viewing options

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

Grats on the latest update Rudolph - finally there is a light at the end of the tunnel eh?

nice job, dont throw the servo internals away though, add a mosfet and you can make an ESC for btushed motors!

Got my parts the other day (and was shorted half the 10k resistors... argh) but just finally got to play with it again today. I've now added a schmitt trigger chip (SN74LS14) which produces the following on the pseudoscope.


Time to put in the interrupt-counting sketch and see if this helps.

Those readings don't look too good. When I connected the Schmitt trigger I got a pretty neat square wave actually. Only I still haven't managed to make it stop counting some transitions more than once. Especially when the wheel is turning slowly.

TeleFox adviced me to connect all of the unused inputs on the Schmitt trigger to the ground for a cleaner output. You may wanna look into that too.


Anyway good luck ;)

Just thought I'd let you know that I finally get some proper readings from my setup:


And I'm pretty sure that I can improve some more on that.

Anyway I noticed that the light in my room makes a HUGE difference. Just by turning on/off my desktop lamp I got the readings jumping more than 1V. So I thought maybe that is your problem. You're testing it in a lit up room and when you close the servo up it all changes. You may wanna make sure that you test/calibrate it under the same conditions as it will be used.

Just a thought :D


Just thought I'd keep you updated on my progress since we're basically doing the same thing.

I connected it to a Schmitt trigger which wasn't quite the wonder chip I had hoped for. It does create a square wave from the analog output and it inverts the high/low pulses (aha so that's why it's called a hex INVERTER :). But when I move it slowly across my encoder discs it tends to count a transition several times. That's no good. More experimention is needed :/

Aniss ... Over and out

You (Rudolph) said:

"When the eye is looking at a black portion of the gear the signal is high (800+ at Arduino's analog input), Looking at a white spot it goes low (about 40 at the analog input)."

Do you mean to say that you respectively get a clean and consistent ~800 and ~40 from the analog inputs?

If so then I'm jealous. I'm using a QRB1134 which should be pretty much identical (= an IR led + a phototransistor) and my readings are jumping up and down like this:


Perhaps I'm doing something very wrong or perhaps I just got the wrong sensor :/

I don't have a scope to actually see things yet. I'd give yours a shot but I don't have a winders machine to use.

Originally I was getting between 37 and 43 as low, and 770 to like 880 for high (if memory serves). Those numbers ended up varying depending on temperature, caffeine intake, and possibly planet alignment ;) They also were highly dependent on the angle of the sensor, although that's not surprising.

More recently I think I've figured out where I was going wrong (well, one place among many); my first sketch was taking a reading and delay(500)-ing. That 500 delay was screwing with everything by showing neither the "stutter" at edges, nor the inconsistent opacity of the gear. Dropping that delay significantly shows me that thin spots of the gear register as holes (apparently), edges cause the output to rapidly flutter, and some spots cause flutter for no apparent reason. Rik's comment on what the sensor sees was dead on, marker ink or otherwise.

The way I understand these Schmitt Trigger thingies to work, they should reduce/eliminate that flutter at edges, and possibly the random, no-apparent-reason flutter in the middle of the gear as well.

Based off the link from Ro-Bot-X I'm going to order up some 7414 chips come payday (and some other parts too, cause I'm not paying 7 bucks to ship 1.30 worth of parts)

Not sure why you mention that in this context? :/

However the scope I made is extremely easy to use. Here is the Arduino test code I'm using now:

#define ADC 0

int val;

void setup() {

void loop() {
  val = analogRead(ADC);
  val = map(val, 0, 1023, 0, 255);
  Serial.print(val, BYTE);

Anyway you don't really need a scope to get an idea about the readings. It's just easier to look at a lot of readings this way.

The waveform above is (supposed to be) a pure high signal (!!!). It fluctuates between 0V and ~4.8V. A corresponding low signal fluctuates between 0V and ~1V and looks something like this:


So if your readings flutuate between ~37 and ~43 as low and ~770 to ~880 they're a LOT better than mine.

Besides I also get the feeling that the readings act differently every time I test. Possible the earths alignment has something to do with it :D It's as good a guess as any...

Sorry, "winders machine" == Windows, which your serial scope software runs on. My workbench and duty computers both run Linux. The wife's laptop has XP, but I can't stand to use that POS ;)

In addition to the 7414 thing with the schmitt trigger, I'll also be ordering some of the LM311 comparator and LM358 op-amp since they seem to be common in these other diagrams and projects, and they're cheap. The Lynxmotion thing posted in your thread (I think by Robologist) looks slick, I think I'll try replicating that to start.

So you meant WINDOWS and not an actual winder machine. Makes more sense.

Anyway a guy on the Arduino forum posted a software scope specifically for Linux which you may wanna check out. It seems somewhat fancier than mine.

Besides if your analog readings are really as consistent as you say have you considered working with these readings and using code to determine whether it's a high or low state? Something like this:

if(analogRead(IRPIN) > 500) state = HIGH;
else state = LOW;

Just an idea ;)