Wednesday, August 4, 2010

Encoders make the world go around

For the CNC project, I'm planning to use stepper motors as they're much much much much much cheaper than their servo brethren. But the down side to this is that they're they dumbest of the two.
Basically in a servo the control says to the servo "go to 180 degrees" and the servo goes to 180, and stays there, it actually has a built in rotary encoder to see if it starts to stray to 179.999 or 180.001. If it does, it corrects itself and maintains 180 until the control tells it to go somewhere else.
The Stepper is aptly named because when the control says to the stepper "go to 180 degrees", the stepper will step a certain number of increments until it thinks it's at 180 degrees - for example a common step angle is 1.8 degrees per step.
180/1.8 = 100 steps - so the motor will blindly make 100 steps and hold itself there.
In a perfect world, this isn't a problem. But in the real world anything can happen. If the stepper makes it's 100 steps, the control will assume it's at 180 degrees. Now, if the motor gets bumped, it's possible that it could have shifted a step(or two). Now in the real world the motor is at 181.8 degrees, but the control still thinks it's at 180. This is a huge problem if you're concerned with accurate positioning... such as in a CNC machine.
So, I was hoping to take some inexpensive digital calipers and hack them into a linear encoder. The machine would then be as accurate as the calipers that I hacked. But I tore apart some cheap $8 calipers from Harbor Freight, only to find pretty much nothing inside. I was stumped. They were nothing like my dial calipers - no mini-rack and pinion or anything that a mechanical minded person could comprehend. It was pretty much the sliding portion, the portion it slides on, a tiny circuit board and a battery - there wasn't even any visible means of connection between the two (as in - how did it make measurements from it's relative movement?). I later found out, after tons of digging that the stationary portion (long part) has specifically spaced magnets (or magnetized bits) in it, while the sliding part (short part with the readout) has a hall-effect sensor type thingy in it to read the spacings and know where it is based on that.
Short of it is, I couldn't use it because I couldn't find anything to hack and read a signal from.
So after putting that on the back burner for a while, I stumbled upon a (relatively) inexpensive rotary encoder, with surprising resolution.

I even got the cute coupling to go with it.













Below you can see my quick setup (the beer is actually incredibly important).

I wanted to play with it, so I hooked it up to my Arduino for a clean 5V power, and used my DMM to read each wire as I fiddled with the shaft (giggidy).
So far, from playing and the operation manual (barely that... more like operation page), I found that basically there are 6 signal wires. A/A- ; B/B- and Z/Z-. A and B are signals, Z is the 'reference'. Z is supposed to switch (go from 0 to about 3.4V or vice-versa) with 1 revolution. I got a 1000 resolution encoder, so A and B both pulse 1000 times for each revolution (that's 0.36 degrees of resolution, for those counting. not too shabby for $86). I found that reading voltage across A and A- gives readings bouncing back and forth from -3.4 and 3.4 (nothing in between), while reading between A and GND bounces between 3.4 and 0. B/B- and Z/Z- act similarly. I'll have to dink more, but the plan is to use the Arduino and it's interrupt routines to decode the encoder. Pair that with my stepper, and I might actually have something here...

UPDATE =D

I've been tinkering with the encoder, and still can't figure a good use for the A-, B- and Z- (I guess I'm not using it right). I've been told by an Electrical dude that in the real world Z is only used for homing (or Zeroing).
I deduced a beautiful way to make A+ and B+ work for me. It seems I can figure direction just from those two signal pulses.
Short of it is, I got it working!
Had a few problems initally. The first and most newbish being 'unsigned' int - I couldn't figure why when I decremented, my number shot from 0 to 65535, instead of -1 like I was expecting (I knew it 'cycled back around' I just didn't know why the negative numbers where omitted). Took me a good 30 minutes to figure I needed to take off 'unsigned'.
I originally had "Serial.println(position)" after every pulse, and that pretty much limited me to oh, maybe 3 rpm or I'd start noticing skipped pulses (or worse, it'd skip just right to where it'd read what it thought was a decrement signal when it was incrementing). Spent quite a while before I realized just how slow the Serial.println was slowing the entire thing down. I changed up my program to delay for one second then print. Without an accurate rotary table to measure it, I can't say for sure, but it seemed like that fixed it. My set up should (in theory) be accurate to roughly 0.25 degrees. I'd be willing to bet that's not too far off just from crude testing.
Fun stuff.

No comments:

Post a Comment