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.

Here's a screenshot of what it looks like on a semi-scope-ey-thingie.


This is me just rotating the gear around with my fingernail.

I couldn't quite get that other scope you linked to work. It compiled and ran, but never showed anything on the screen, or just sat with a "waiting for trigger" notification. Maybe I'm just too dense. I'll give it another go when I'm more focused. This is using the Liberino thingie.

But what exactly is going on here? Are the two spikes HIGH readings and the rest LOW readings? If so it corresponds with the numbers you named before. And I can definately conclude that something is VERY wrong with my sensors/setup :(

In your case it's not exactly a smooth square wave BUT the HIGHs and LOWs are quite easily distinguisable from one another. Perhaps it's not enough to consistantly trigger the digital inputs (though I don't see why not) but I would try to work with the analog readings as I mentioned before. Otherwise it should be a simple question of cleaning the signal using a Schmitt trigger, op amp or voltage comparator or whatnot. Perhaps even a simple transistor could do the trick?

About the other Linux scope...I think your supposed to upload a specific scetch to your Arduino which automatically sends of the values from the analog inputs (using interrupts somehow). But since I don't have Linux I didn't check it out further.

yeah, the spikes are the higher readings, specifically when the hole is over the sensor. that was on an analog input again for scope-ing purposes. it's hard to see in that pic, but there are some little steps as it transitions. those are happening at the edges of the hole. i imagine the digital input would see those as a rapid hi low combinations, not unlike pwm, causing multiple counts to happen. -- re scope prog, ya it came with a sketch too. had that on the duino but it didn't seem to notice any inputs. the tx light never even flickered while runing. wondering if the adc interrupt thing it talks about is only on the 328 chips, as i have an older diecimila. -- sorry for the run on paragraph. phone doesn't let me do line breaks. it doesn't do capitals or double letters well either.

Like I said I'm jealous of your readings :D I'm here experimenting with different resistor values, printouts, distances and weird workarounds to get something CLOSE to your readings.

About the little steps as it transistions. Yeah that could very well be your problem. However have you tried something as simple as putting a cap between the signal and the ground? That might smoothen out the transistions actually. I noticed that your schematic doesn't include the cap while the one I used does (otherwise they're identical):


PS: Sorry. Don't know what else to say about the Linux scope :/

Alright, I added a .1uF cap between signal and ground and fired up the fake-o-scope. The steps were still present when rotating with my fingernail. So I reassembled the servo, stuck the wheel on, and spun it like crazy ;) Naturally the fake-o-scope showed me spikes that were significantly shorter depending on how fast I spun the wheel (faster wheel == shorter spikes).

i decided I'd try a larger, polarized, electrolytic cap instead of the .1uF ceramic one. As I was scrolling through another diagram to check if/where there was a cap there, my bench computer decided to no longer accept input from its mouse or keyboard... Argh. That's all three computers in this house that are acting shitty now.

Tomorrow I hope to be able to order up the previously mentioned op-amps, schmitt triggers, comparators, etc... so I can try this a known way instead of trying to make up my own.

For now I think I'm going to have some rum and pretend I've never even heard of a computer or an Arduino ;)

Bad luck with the computers mate :/

Even with the op amp, Schmitt trigger, comparator and whatnot you're still gonna have to make up your own way...that is play around with the resistors, caps etc to make it work with your setup. But don't give up...I think you're closer to a solution than you may realize. Like I said your readings look very smooth to me.

BTW here is a guy who apparently had succes using a 10uF cap with a 47K pullup and a 470 Ohm LED resistor. Just shows that the setup may vary quite a bit depending on the application.

And I'd actually like to know which Schmitt trigger, comparator and op amp you end up buying?!

Anyway bottoms up :D


Heh. Of all the simple things, and possibly the most common, adding a cap never even crossed my mind. I'll put one on and see if that smooths things out. Thanks!

Yeah, I seem to have a problem with using terms that aren't globally well known. Winders would be the redneck pronunciation of windows ;)

I think they only appear to be consistent, due to the half second delay in my loop. Dropping the delay down to 5 seemed to show that it was all over the place, I just haven't properly measured to see exactly how bad it really is. I was only using the analog input for initial testing, I've since moved it to one of the interrupt pins so I don't have to poll.

Having a look at your link. Looking promising so far ;) Thanks!

Have you tried using a Schmitt trigger as Big Face suggested earlier? It seems like the way to go..