MachineKit Encoder
Motivation
I want an encoder! Encoders1 read position, generally by counting 'ticks' on some reference. For example, an Optical Encoder uses a reference with openings that allow light to pass, and count whenever a photodiode goes high or low to indicate that some motion has occurred.
Then, you add the ticks together to get your position. In order to detect direction, a technique called 'quadrature' is used:
Super simple, very neat. Here's picture of a fancy encoder:
You'll notice this encoder has two other reference markings - those are super interesting as well, and encode absolute position into the ring - there is only one uniqe combination of holes-or-not-holes on those rings for every single indicated position. This is good news because then your joint / axis does not have to touchoff on a known reference point - aka a 'home' or 'limit' switch - before it starts counting. If this looks expensive, it's because it is. An encoder like this might run ~ $300, and they're super sensitive to dust, misalignment etc. That's no bueno.
So my goal here is develop an encoder that I can put on whatever-I-want without spending too much money, and without fussing too much about setup. Critically, I also want to un-constrain myself from particular sizes - whenever I have to source a particular size ring or strip (for reference) I end up boxed-in in terms of the *~ design spaces ~* I can get into. I don't like that.
Solution?
So I'm going to try rolling2 a magnetic encoder3 with a custom array of magnets. This way I can roll a ring or line of magnets into whatever structure I want, and hover one of these encoders above it to read position.
The chip I'm going to use is an AS5304 - a product offered by AMS that does all of the hard work on the hall-array end for me. I can read quadrature output from this ('ABI' interface - 'I' being an Index Pulse)
So, in summary, I am basically just building a big ring magnet, and trying to read that with the AS5304.
Problems
I am using an AS5304 (4mm poles) or an AS5406 (2.4mm poles). Each has 160 positions per magnetic period. This translates to a resolution of 25um and 15um steps, respectively. If I wrap this around some diameter D I have that
angular resolution = 360 / (((PI x D)/pole_length) x 160)
Of course, I have to set the circumference equal to an integer value of magnets. I wrote a quick spreadsheet for this, and get that w/ a Diameter ~ 100mm (where the gearbox currently stands) I can get 0.017 deg/step with a 2.4mm pole pair, and ~ 0.03 deg/step with a 4mm pole spacing. Nice.
Now, this is not so straightforward. The important thing to remember is that Resolution != Accuracy - while I have ~ 0.03 deg / step, those steps are not exactly mapped perfectly in a circle. I will actually be referencing magnets that are glued in place - so my glueing and magnet placement would have to be perfect4 for Resolution to = Accuracy. In addition, not all magnetic fields will be identical, etc.
In addition to these mappings between poles, I will have some deviation, I'm sure, within the poles. As in, the magnets will likely have small gaps (finding a magnet which is perfectly 2mm across... not likely) and so I expect readings to deviate in a kind of sine-wave around actual position... one period of the wave corresponding to one period of the poles.
This can be overcome in implementation by mapping in memory a lookup table, with respect to some 'home' position, of how measured ticks of the encoder match up with reference positions. For example, I would rotate the encoder to known positions (with some other, higher precision system) and map readings -> known values.
This is not ideal! And it requires a deal of labor, some good routines and memory-storage games, and a reference point.
In this exercise (which I am trying to keep bounded)5 I will try only to measure this deviation-from-perfection. Or, at least, deviation from some other, better positioning system.
At best, I hope to cancel periodic deviation (i.e. map the sine-wave between individual poles into a more linear interpolation. my encoders have an Index pulse (on every top-of-pole) that I can use as a reference point for this.
Design
Without further ado, here's a sketch of how I plan to build the encoder:
And then, a system to put that encoder in set positions, while measuring...
- while pole pairs are 4.0mm apart, poles are 2mm long - magnets are 2mm across.
In some moment of foresight, I want to find an encoder with a bigger pole spacing - I think that 2mm is tooo small and seems likely to drive me to madness in assembly. Time to DigiKey it up! None are available, boo. The other option is to truly roll my own encoder, using Hall Effect Sensors with variable output, look at the sine waves, and do encoding from there. This is becoming a challenging project.
OK, nevermind. I'm going back to on-chip quadrature de-quadraturing (or, mag field -> quadrature).
I made a home for the board
And started laying out a schematic. Had to build the footprint in Eagle.
If you're wondering why I have SPI pins labelled, it's because I'm actually connecting this to a plug on my Networking Switch - these are the pinouts. Instead of SPI I will just configure those pins to do GPIO.
THIS is a big what-if for me. As in, what if I get my switch boards back from the fab and it turns out I can't get GPIO to work on these particular pins? I have trapped myself. !
I also have voltage dividers set up here - the AS5304 drives 5v, and I don't want to pump that into my puny 3v3 logic lines on the ATSAMS70.
I also have a jumper / pin header footprint setup on the Analog Out pin - this will let me read the strength of the magnetic fields, making sure I am aligned, and that the field strength does not deviate too wildly between poles.
Ideally, I would tie this voltage out to an ADC on the ATSAM, but I haven't broken any of those out on the BLDC encoder board... this is a long chain of interconnects. I am rethinking my overall switch -> peripheral strategies now. A good learning / systems design moment. OR I could tie it to some kind of comparator, and have an LED turn on only when that voltage was in a particular range. shrugguy. This is helping me design the modular switch, so that's good news.
OK, Routed
Exporting to mods from Eagle is a bit of a pain. In the fullness of time I would write a MOD to do GERBERS -> Milling, however.
In Eagle, I do this
Options -> Settings -> Misc -> don't display pad names or signals on traces
Layers -> none Layers -> Top, Pads export image monochrome
Layers -> none Layers -> Bottom, pads export image monochrome
... ok
Back to my layout, and working back into my sheet, I'm going to add magnets here:
And then to test this against some reference, I'm going to use a stepper motor. With the current diameter I'll have 0.05 deg resolution (or, I would ideally) - this means I would need 1/32 microstepping to match up on a stepper motor - I want my reference to have a bit more resolution than what I'm measuring, so I'll try to find a stepper motor with 400 steps / rev, and do 1/32 microstepping on that. Then I have 0.028 deg / step. I'll also bring the diameter down on my encoder to 58 poles, so I'll have 0.077 deg / step there. This means I have about 3x the resolution on my reference than I do on my measured-thing, and intuitively that feels like a good spec. Thumbs up.
ALSO - I knew I should check this, and I'm glad I did - here's a #2 and a #0 screw - the #2 contacts the encoder ring. Noice.6
Final touches, I'm going to make a mount for a NEMA17 Motor on the back, and a little teeny desktop stand.
OK, check it oot
Fab: the board
So I milled this board on the Roland SRM-20. I'm plugging this into my other ongoing work... here's my brushless motor controller that rides below my even-more-unresolved networking chip. Those ports you see on the left of the bldc-driver are for other GPIO, including this encoder.
Ramble ramble, here it is:
And you can see the AS5304 here
Also, a moment of appreciation for the new Leica microscope that showed up at the CBA soldering station. Has variable zoom, and generally is very lovely.
Fab: the kit
I printed the hardware on the Eden. The Eden's washing-up station is currently broken, and I spent the better part of an afternoon trying to cobble together a fittings-and-adapters solution to unbreak it, to no avail. I await McMaster parts.
Update: I borrow Biomechatronics' eden waterjet blaster. I have parts now.
First order is getting these magnets in. They're small!
I accidentally put a few poles side-by-side (rather than alternating) - a bit of a bummer. But this is good enough for my test... Here's the ring
Ok I got this mostly together - made one mistake, where the motor floats a bit behind the mount. I kind of knew this might be an issue - also, generally, I am overconstrained w/ the motor bearings fighting my ring bearing. In hindsight I didn't even need this ring bearing, but it's something I also wanted to prototype for later development, so here we are. Belt and Suspenders.
Testing
Before I get into the meat of programming interrupts etc for this, I'm going to first get some voltage on this board alone and scope the lines to see that I am getting (1) the voltage I want out of the magnetic-field sensing pin, and (2) the ticks I want on the ABI lines.
Programming, Measurements & Corrections
I want to be like Sam. Sam measures everything and he does it really beautifully. This is some of the functionality I really want to be able to bring into mods - the ability to quickly pull test data out of systems, do computation with it, and learn.
With that motivation, I want to take this chance to run a test cast of that. The Goal here:
- First, do ATSAM Router -> MODS pipeline
- Read Encoder with GPIO Interrupts or QED7 and report periodically to MODS
- Bones of step & dir control on the ATSAMS70
- Stateless Stepper Motor Drive on MODS -> ATSAMS70
- Graphs & Charts & Realtime Data Capture in MODS
- Push a line to the stepper, read encoder, watch linear != linear
- Think long & hard about how to cancel observed differences?
That's a lot! I'm not going to get into it this week, but maybe this is a good project for next week.
Footnotes
- In the sense I am familiar with - that is, machine design and motion control.
- ~ pun alert ~
- Also cool, footnoted to reduce rambling nature of this document, magnetic encoders use an array of hall sensors to sense and a changing magnetic field as a reference. Were I to go even finer grain with this, I would build my own array of hall sensors, but I am a mere mortal and that's the kind of project that belongs in Sam's domain, or until I significantly up my signal processing game.
- And remember, in the words of Morty: "everything is crooked, the world is a lie!"
- But I am also planning on actually using this encoder in my implementation of an arm, and later in linear applications, so having an idea of how to really pull this off is - I am hoping - something that will come to me. But I make no plans as such. Seems hard.
- Ideally I would solder small threaded-things on to the back of the PCB, then I could mount it from the rear and really pinch the rest of it against the plate. Also this would allow me to adjust the encoder position with the ring already in place.
- Quadrature Encoder Decoder - a timer implementation available on the ATSAMS70 that is meant for this.