Commit 376494c1 authored by Jake Read's avatar Jake Read
Browse files

split mag and cap

parent 33d33be1
......@@ -18,191 +18,10 @@ You'll notice this encoder has two other reference markings - those are super in
**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?
## Solution: Capacitive Encoder
So I'm going to try rolling<sup>2</sup> a magnetic encoder<sup>3</sup> 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.
[Go Here](https://gitlab.cba.mit.edu/jakeread/mkencoder/tree/master/capacitive.md) for Capacitive Writeup and Doc
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)
## Solution: Magnetic Encoder
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.
![rough spreadsheet](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/spreadsheet-resolution-approx.png)
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 *perfect<sup>4</sup>* 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)<sup>5</sup> 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:
![layout test](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/layout-encoder-test.jpg)
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
![board-in-fusion-begin](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-in-fusion-begin.jpg)
And started laying out a schematic. Had to build the footprint in Eagle.
![board schematic](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-schematic.jpg)
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](https://github.com/jakeread/tinynets/tree/master/circuit) - 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
![board routed](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-routed.jpg)
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:
![cad magnet circle](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/cad-magnet-circle.jpg)
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.<sup>6</sup>
![cad screw clearance](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/cad-screw-clearance.jpg)
Final touches, I'm going to make a mount for a NEMA17 Motor on the back, and a little teeny desktop stand.
![cad stand](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/cad-stand.jpg)
OK, check it oot
![cad check](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/cad-check.jpg)
## 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](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver) 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:
![board assembled](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-assembled.jpg)
And you can see the AS5304 here
![board as5304](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-as5304.jpg)
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.
![microscope appreciation](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/microscope-appreciation.jpg)
## 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
![magnets-in-place](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/magnets-in-place.jpg)
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.
![motor-and-encoder](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/motor-and-encoder.jpg)
## 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.
So, pretty upsetting. I am getting the bad magnetic field warning from the AS5304. The Index is High while A and B are low (the warning) and the output from the CAO (analog magnetic field indicator) is low, around 1.1 volts, meaning that I have a magnetic field that is way too strong.
![datasheet-cao](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/datasheet-cao.jpg)
And my scope trace:
![scope-sad-cao](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/scope-sad-cao.jpg)
And setup:
![scope-to-check-cao](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/scope-to-check-cao.jpg)
In some sense, I should have anticipated this, and in hindsight I really should have read the datasheet in more detail, where I'm sure it outlines the required magnetic field strength...
Yep, there it is
![datasheet-magfield](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/datasheet-magfield.jpg)
So lesson learned - I really should have gotten into this beforehand, but it looks like I have *way* too much magnetic field - 13500 Gauss at the magnet pole and the AS5304 wants only to see 10 to 60 mT (milliTesla) - I have 1350 mT. Whoop!
## NEXT TIME
I think the best way forward, with all things considered, is to go bones deep <i class="em em-swimmer"></i> and get two Hall Effect Sensors, read those, and do the signal processing. It's a much more interesting project this way, etc.
I may make a last-ditch attempt at the easy route, with skinnier magnets and a bigger spacing between the encoder and the ring.
All I want is more time.
## 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 QED<sup>7</sup> 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
1. In the sense I am familiar with - that is, machine design and motion control.
2. ~ pun alert ~
3. 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.
4. And remember, in the words of Morty: "everything is crooked, the world is a lie!"
5. 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.
6. 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.
7. Quadrature Encoder Decoder - a timer implementation available on the ATSAMS70 that is meant for this.
\ No newline at end of file
[Go Here](https://gitlab.cba.mit.edu/jakeread/mkencoder/tree/master/magnetic.md) for Magnetic Writeup and Doc
\ No newline at end of file
# Solution: Capacitive Encoder
Here, I'll try PCB-fabbing a reference circle with triangular teeth, and two pads to read through.
As the ring moves, capacitance should vary between the pads - I can read this as a value on an ADC pin and track that to figure position.
## Commercial Sensors
I'm dubious about Neils TX / RX settle time - 100us (yikes!). I'm looking into using some other IC's - drivers that are made for this - to do the conversion.
TI has two - the FDC1004 and the FDC2112 - both are I2C devices. The FDC2112, rather than doing rise / delay, watches deviation in resonant frequency at the sensor location. Oddly, none that I can find use Neils TX / RX Scheme for environmental cancelling, all use TX / GND.
In short, these solutions seem cool, but complicated, and I need to take some more time with the bare-bones of this problem to determine if I can make something work. Like,
- does rise-time drop with smaller pads? less charge to distribute...
- how many up/down sets do I need for a reasonable measurement?
- adc resolution -> bar width / spacing
- grounding, stack setup, tx pads, rx pad(s)?
Some quick thoughts
- do static tx / rx pads. reference is metallic thing that moves between them, changing the permeability of space between them
- bc capacitance is C = \frac{k * e * A}{d} where E is constant, A is area, and K is relative permeability (k ~= 1 for air)
- 'metallic thing' can be double-sided pcb w/ sawtooth or sine pattern to read
- can do spreadsheet maths for tx / rx areas, see what total capacitance range will be (1pf -> 15pf?)
- can figure apparent rise-time calculator, probably?
http://hyperphysics.phy-astr.gsu.edu/hbase/electric/pplate.html
http://www.ti.com/lit/an/snoa927/snoa927.pdf
To quickly lay this out, I'll take the linear case... and a triangular wave to read.
- notebook pic
- or whiteboard, do pitch, do 1/4 -> 1/2 -> 3/4
So I can build a quick spreadsheet for this. Using basic areas and http://hyperphysics.phy-astr.gsu.edu/hbase/electric/pplate.html
C = k*e_0*A/d
What changes as the imaged plate moves is the permittivity of the space between the tx and rx pads. Copper has a technically infinite permittivity, so in some sense what we're doing is decreasing the space between the pads, when the copper passes through. *shrugman*
\ No newline at end of file
# Solution: Magnetic Encoder
So I'm going to try rolling<sup>2</sup> a magnetic encoder<sup>3</sup> 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.
![rough spreadsheet](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/spreadsheet-resolution-approx.png)
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 *perfect<sup>4</sup>* 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)<sup>5</sup> 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:
![layout test](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/layout-encoder-test.jpg)
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
![board-in-fusion-begin](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-in-fusion-begin.jpg)
And started laying out a schematic. Had to build the footprint in Eagle.
![board schematic](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-schematic.jpg)
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](https://github.com/jakeread/tinynets/tree/master/circuit) - 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
![board routed](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-routed.jpg)
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:
![cad magnet circle](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/cad-magnet-circle.jpg)
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.<sup>6</sup>
![cad screw clearance](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/cad-screw-clearance.jpg)
Final touches, I'm going to make a mount for a NEMA17 Motor on the back, and a little teeny desktop stand.
![cad stand](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/cad-stand.jpg)
OK, check it oot
![cad check](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/cad-check.jpg)
## 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](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver) 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:
![board assembled](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-assembled.jpg)
And you can see the AS5304 here
![board as5304](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/board-as5304.jpg)
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.
![microscope appreciation](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/microscope-appreciation.jpg)
## 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
![magnets-in-place](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/magnets-in-place.jpg)
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.
![motor-and-encoder](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/motor-and-encoder.jpg)
## 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.
So, pretty upsetting. I am getting the bad magnetic field warning from the AS5304. The Index is High while A and B are low (the warning) and the output from the CAO (analog magnetic field indicator) is low, around 1.1 volts, meaning that I have a magnetic field that is way too strong.
![datasheet-cao](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/datasheet-cao.jpg)
And my scope trace:
![scope-sad-cao](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/scope-sad-cao.jpg)
And setup:
![scope-to-check-cao](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/scope-to-check-cao.jpg)
In some sense, I should have anticipated this, and in hindsight I really should have read the datasheet in more detail, where I'm sure it outlines the required magnetic field strength...
Yep, there it is
![datasheet-magfield](https://gitlab.cba.mit.edu/jakeread/mkencoder/raw/master/images/datasheet-magfield.jpg)
So lesson learned - I really should have gotten into this beforehand, but it looks like I have *way* too much magnetic field - 13500 Gauss at the magnet pole and the AS5304 wants only to see 10 to 60 mT (milliTesla) - I have 1350 mT. Whoop!
## NEXT TIME
I think the best way forward, with all things considered, is to go bones deep <i class="em em-swimmer"></i> and get two Hall Effect Sensors, read those, and do the signal processing. It's a much more interesting project this way, etc.
I may make a last-ditch attempt at the easy route, with skinnier magnets and a bigger spacing between the encoder and the ring.
All I want is more time.
## Capacitive Encoders
OK, on Neil's suggestion I am now thinking that I'll try for a Capacitive Encoder. Also, [here's](http://www.cui.com/product-spotlight/capacitive-absolute-encoders-amt20-series) an *advertisement* but good writeup on encoders, generally, concluding with a note on capacitive encoding.
I like this a lot because it means I can use a machine to make the reference - no magnets and tweezers. It also scales really well, as I can have PCB's fabbed elsewhere. This actually might be the answer to my closed-loop cnc machines problem. So, certainly, I'm excited to try it out... and I'm going to push this *old* work into a sub-dir and start a new capacitive line.
This is appealing
## 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 QED<sup>7</sup> 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
1. In the sense I am familiar with - that is, machine design and motion control.
2. ~ pun alert ~
3. 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.
4. And remember, in the words of Morty: "everything is crooked, the world is a lie!"
5. 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.
6. 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.
7. Quadrature Encoder Decoder - a timer implementation available on the ATSAMS70 that is meant for this.
\ No newline at end of file
[Eagle]
Version="08 03 02"
Platform="Windows"
Globals="Globals"
Desktop="Desktop"
[Globals]
AutoSaveProject=1
UsedLibraryUrn="urn:adsk.eagle:library:79"
UsedLibraryUrn="urn:adsk.eagle:library:88"
UsedLibraryUrn="urn:adsk.eagle:library:178"
UsedLibraryUrn="urn:adsk.eagle:library:179"
UsedLibraryUrn="urn:adsk.eagle:library:180"
UsedLibraryUrn="urn:adsk.eagle:library:181"
UsedLibraryUrn="urn:adsk.eagle:library:182"
UsedLibraryUrn="urn:adsk.eagle:library:183"
UsedLibraryUrn="urn:adsk.eagle:library:184"
UsedLibraryUrn="urn:adsk.eagle:library:185"
UsedLibraryUrn="urn:adsk.eagle:library:186"
UsedLibraryUrn="urn:adsk.eagle:library:187"
UsedLibraryUrn="urn:adsk.eagle:library:89"
UsedLibraryUrn="urn:adsk.eagle:library:188"
UsedLibraryUrn="urn:adsk.eagle:library:189"
UsedLibraryUrn="urn:adsk.eagle:library:190"
UsedLibraryUrn="urn:adsk.eagle:library:191"
UsedLibraryUrn="urn:adsk.eagle:library:192"
UsedLibraryUrn="urn:adsk.eagle:library:193"
UsedLibraryUrn="urn:adsk.eagle:library:194"
UsedLibraryUrn="urn:adsk.eagle:library:195"
UsedLibraryUrn="urn:adsk.eagle:library:196"
UsedLibraryUrn="urn:adsk.eagle:library:197"
UsedLibraryUrn="urn:adsk.eagle:library:90"
UsedLibraryUrn="urn:adsk.eagle:library:198"
UsedLibraryUrn="urn:adsk.eagle:library:199"
UsedLibraryUrn="urn:adsk.eagle:library:200"
UsedLibraryUrn="urn:adsk.eagle:library:201"
UsedLibraryUrn="urn:adsk.eagle:library:202"
UsedLibraryUrn="urn:adsk.eagle:library:203"
UsedLibraryUrn="urn:adsk.eagle:library:204"
UsedLibraryUrn="urn:adsk.eagle:library:205"
UsedLibraryUrn="urn:adsk.eagle:library:206"
UsedLibraryUrn="urn:adsk.eagle:library:207"
UsedLibraryUrn="urn:adsk.eagle:library:91"
UsedLibraryUrn="urn:adsk.eagle:library:208"
UsedLibraryUrn="urn:adsk.eagle:library:209"
UsedLibraryUrn="urn:adsk.eagle:library:210"
UsedLibraryUrn="urn:adsk.eagle:library:211"
UsedLibraryUrn="urn:adsk.eagle:library:212"
UsedLibraryUrn="urn:adsk.eagle:library:213"
UsedLibraryUrn="urn:adsk.eagle:library:214"
UsedLibraryUrn="urn:adsk.eagle:library:215"
UsedLibraryUrn="urn:adsk.eagle:library:216"
UsedLibraryUrn="urn:adsk.eagle:library:217"
UsedLibraryUrn="urn:adsk.eagle:library:92"
UsedLibraryUrn="urn:adsk.eagle:library:218"
UsedLibraryUrn="urn:adsk.eagle:library:219"
UsedLibraryUrn="urn:adsk.eagle:library:220"
UsedLibraryUrn="urn:adsk.eagle:library:221"
UsedLibraryUrn="urn:adsk.eagle:library:222"
UsedLibraryUrn="urn:adsk.eagle:library:223"
UsedLibraryUrn="urn:adsk.eagle:library:224"
UsedLibraryUrn="urn:adsk.eagle:library:225"
UsedLibraryUrn="urn:adsk.eagle:library:226"
UsedLibraryUrn="urn:adsk.eagle:library:227"
UsedLibraryUrn="urn:adsk.eagle:library:93"
UsedLibraryUrn="urn:adsk.eagle:library:228"
UsedLibraryUrn="urn:adsk.eagle:library:229"
UsedLibraryUrn="urn:adsk.eagle:library:230"
UsedLibraryUrn="urn:adsk.eagle:library:231"
UsedLibraryUrn="urn:adsk.eagle:library:232"
UsedLibraryUrn="urn:adsk.eagle:library:233"
UsedLibraryUrn="urn:adsk.eagle:library:234"
UsedLibraryUrn="urn:adsk.eagle:library:235"
UsedLibraryUrn="urn:adsk.eagle:library:236"
UsedLibraryUrn="urn:adsk.eagle:library:237"
UsedLibraryUrn="urn:adsk.eagle:library:94"
UsedLibraryUrn="urn:adsk.eagle:library:238"
UsedLibraryUrn="urn:adsk.eagle:library:239"
UsedLibraryUrn="urn:adsk.eagle:library:240"
UsedLibraryUrn="urn:adsk.eagle:library:241"
UsedLibraryUrn="urn:adsk.eagle:library:242"
UsedLibraryUrn="urn:adsk.eagle:library:243"
UsedLibraryUrn="urn:adsk.eagle:library:244"
UsedLibraryUrn="urn:adsk.eagle:library:245"
UsedLibraryUrn="urn:adsk.eagle:library:246"
UsedLibraryUrn="urn:adsk.eagle:library:247"
UsedLibraryUrn="urn:adsk.eagle:library:95"
UsedLibraryUrn="urn:adsk.eagle:library:248"
UsedLibraryUrn="urn:adsk.eagle:library:249"
UsedLibraryUrn="urn:adsk.eagle:library:250"
UsedLibraryUrn="urn:adsk.eagle:library:251"
UsedLibraryUrn="urn:adsk.eagle:library:252"
UsedLibraryUrn="urn:adsk.eagle:library:253"
UsedLibraryUrn="urn:adsk.eagle:library:254"
UsedLibraryUrn="urn:adsk.eagle:library:255"
UsedLibraryUrn="urn:adsk.eagle:library:256"
UsedLibraryUrn="urn:adsk.eagle:library:257"
UsedLibraryUrn="urn:adsk.eagle:library:96"
UsedLibraryUrn="urn:adsk.eagle:library:258"
UsedLibraryUrn="urn:adsk.eagle:library:259"
UsedLibraryUrn="urn:adsk.eagle:library:260"
UsedLibraryUrn="urn:adsk.eagle:library:261"
UsedLibraryUrn="urn:adsk.eagle:library:262"
UsedLibraryUrn="urn:adsk.eagle:library:263"
UsedLibraryUrn="urn:adsk.eagle:library:264"
UsedLibraryUrn="urn:adsk.eagle:library:265"
UsedLibraryUrn="urn:adsk.eagle:library:266"
UsedLibraryUrn="urn:adsk.eagle:library:267"
UsedLibraryUrn="urn:adsk.eagle:library:97"
UsedLibraryUrn="urn:adsk.eagle:library:268"
UsedLibraryUrn="urn:adsk.eagle:library:269"
UsedLibraryUrn="urn:adsk.eagle:library:270"
UsedLibraryUrn="urn:adsk.eagle:library:271"
UsedLibraryUrn="urn:adsk.eagle:library:272"
UsedLibraryUrn="urn:adsk.eagle:library:273"
UsedLibraryUrn="urn:adsk.eagle:library:274"
UsedLibraryUrn="urn:adsk.eagle:library:275"
UsedLibraryUrn="urn:adsk.eagle:library:276"
UsedLibraryUrn="urn:adsk.eagle:library:277"
UsedLibraryUrn="urn:adsk.eagle:library:80"
UsedLibraryUrn="urn:adsk.eagle:library:98"
UsedLibraryUrn="urn:adsk.eagle:library:278"
UsedLibraryUrn="urn:adsk.eagle:library:279"
UsedLibraryUrn="urn:adsk.eagle:library:280"
UsedLibraryUrn="urn:adsk.eagle:library:281"
UsedLibraryUrn="urn:adsk.eagle:library:282"
UsedLibraryUrn="urn:adsk.eagle:library:283"
UsedLibraryUrn="urn:adsk.eagle:library:284"
UsedLibraryUrn="urn:adsk.eagle:library:285"
UsedLibraryUrn="urn:adsk.eagle:library:286"
UsedLibraryUrn="urn:adsk.eagle:library:287"
UsedLibraryUrn="urn:adsk.eagle:library:99"
UsedLibraryUrn="urn:adsk.eagle:library:288"
UsedLibraryUrn="urn:adsk.eagle:library:289"
UsedLibraryUrn="urn:adsk.eagle:library:290"
UsedLibraryUrn="urn:adsk.eagle:library:291"
UsedLibraryUrn="urn:adsk.eagle:library:292"
UsedLibraryUrn="urn:adsk.eagle:library:293"
UsedLibraryUrn="urn:adsk.eagle:library:294"
UsedLibraryUrn="urn:adsk.eagle:library:295"
UsedLibraryUrn="urn:adsk.eagle:library:296"
UsedLibraryUrn="urn:adsk.eagle:library:297"
UsedLibraryUrn="urn:adsk.eagle:library:100"
UsedLibraryUrn="urn:adsk.eagle:library:298"
UsedLibraryUrn="urn:adsk.eagle:library:299"
UsedLibraryUrn="urn:adsk.eagle:library:300"
UsedLibraryUrn="urn:adsk.eagle:library:301"
UsedLibraryUrn="urn:adsk.eagle:library:302"
UsedLibraryUrn="urn:adsk.eagle:library:303"
UsedLibraryUrn="urn:adsk.eagle:library:304"
UsedLibraryUrn="urn:adsk.eagle:library:305"
UsedLibraryUrn="urn:adsk.eagle:library:306"
UsedLibraryUrn="urn:adsk.eagle:library:307"
UsedLibraryUrn="urn:adsk.eagle:library:101"
UsedLibraryUrn="urn:adsk.eagle:library:308"
UsedLibraryUrn="urn:adsk.eagle:library:309"
UsedLibraryUrn="urn:adsk.eagle:library:310"
UsedLibraryUrn="urn:adsk.eagle:library:311"
UsedLibraryUrn="urn:adsk.eagle:library:312"
UsedLibraryUrn="urn:adsk.eagle:library:313"
UsedLibraryUrn="urn:adsk.eagle:library:314"
UsedLibraryUrn="urn:adsk.eagle:library:315"
UsedLibraryUrn="urn:adsk.eagle:library:316"
UsedLibraryUrn="urn:adsk.eagle:library:317"
UsedLibraryUrn="urn:adsk.eagle:library:102"
UsedLibraryUrn="urn:adsk.eagle:library:318"
UsedLibraryUrn="urn:adsk.eagle:library:319"
UsedLibraryUrn="urn:adsk.eagle:library:320"
UsedLibraryUrn="urn:adsk.eagle:library:321"
UsedLibraryUrn="urn:adsk.eagle:library:322"
UsedLibraryUrn="urn:adsk.eagle:library:323"
UsedLibraryUrn="urn:adsk.eagle:library:324"
UsedLibraryUrn="urn:adsk.eagle:library:325"
UsedLibraryUrn="urn:adsk.eagle:library:326"
UsedLibraryUrn="urn:adsk.eagle:library:327"
UsedLibraryUrn="urn:adsk.eagle:library:103"
UsedLibraryUrn="urn:adsk.eagle:library:328"
UsedLibraryUrn="urn:adsk.eagle:library:329"
UsedLibraryUrn="urn:adsk.eagle:library:330"
UsedLibraryUrn="urn:adsk.eagle:library:331"
UsedLibraryUrn="urn:adsk.eagle:library:332"
UsedLibraryUrn="urn:adsk.eagle:library:333"
UsedLibraryUrn="urn:adsk.eagle:library:334"
UsedLibraryUrn="urn:adsk.eagle:library:335"
UsedLibraryUrn="urn:adsk.eagle:library:336"
UsedLibraryUrn="urn:adsk.eagle:library:337"
UsedLibraryUrn="urn:adsk.eagle:library:104"
UsedLibraryUrn="urn:adsk.eagle:library:338"
UsedLibraryUrn="urn:adsk.eagle:library:339"
UsedLibraryUrn="urn:adsk.eagle:library:340"
UsedLibraryUrn="urn:adsk.eagle:library:341"
UsedLibraryUrn="urn:adsk.eagle:library:342"
UsedLibraryUrn="urn:adsk.eagle:library:343"
UsedLibraryUrn="urn:adsk.eagle:library:344"
UsedLibraryUrn="urn:adsk.eagle:library:345"
UsedLibraryUrn="urn:adsk.eagle:library:346"
UsedLibraryUrn="urn:adsk.eagle:library:347"
UsedLibraryUrn="urn:adsk.eagle:library:105"
UsedLibraryUrn="urn:adsk.eagle:library:348"
UsedLibraryUrn="urn:adsk.eagle:library:349"
UsedLibraryUrn="urn:adsk.eagle:library:350"
UsedLibraryUrn="urn:adsk.eagle:library:351"
UsedLibraryUrn="urn:adsk.eagle:library:352"
UsedLibraryUrn="urn:adsk.eagle:library:353"
UsedLibraryUrn="urn:adsk.eagle:library:354"
UsedLibraryUrn="urn:adsk.eagle:library:355"
UsedLibraryUrn="urn:adsk.eagle:library:356"
UsedLibraryUrn="urn:adsk.eagle:library:357"
UsedLibraryUrn="urn:adsk.eagle:library:106"