December 28, 2015

High-Speed Quadrature Decoding with the STM32F4 Nucleo...Because Lasers and Bass

I've been using the STM32F4 Nucleo dev boards for everything lately, and needed to do high speed (edges at MHz frequency) quadrature decoding with one.  Here are the snippets of code to do this.

This setup uses PA_0 and PA_1 plus Timer 2 (one of the two 32-bit timers), which are on the Arduino-compatible A0 and A1 of the Nucleo board (pinout).

The setup code is mostly copy-and-pasted from here.  That code got me to encoder edges at ~600 Khz before it started losing counts.  Turns out there's a digital filter on the GPIO pins I had inadvertently turned on with the copy-pasta code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
    // configure GPIO PA0 & PA1 as inputs for Encoder
    RCC->AHB1ENR |= 0x00000001;  // Enable clock for GPIOA
 
    GPIOA->MODER   |= GPIO_MODER_MODER0_1 | GPIO_MODER_MODER1_1 ;           //PA0 & PA1 as Alternate Function   /*!< GPIO port mode register,               Address offset: 0x00      */
    GPIOA->OTYPER  |= GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1 ;                 //PA0 & PA1 as Inputs               /*!< GPIO port output type register,        Address offset: 0x04      */
    GPIOA->OSPEEDR |= 0x00000011;//|= GPIO_OSPEEDER_OSPEEDR0 | GPIO_OSPEEDER_OSPEEDR1 ;     // Low speed                        /*!< GPIO port output speed register,       Address offset: 0x08      */
    GPIOA->PUPDR   |= GPIO_PUPDR_PUPDR0_1 | GPIO_PUPDR_PUPDR1_1 ;           // Pull Down                        /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */
    GPIOA->AFR[0]  |= 0x00000011 ;                                          //  AF01 for PA0 & PA1              /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */
    GPIOA->AFR[1]  |= 0x00000000 ;                                          //                                  /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */
   
    // configure TIM2 as Encoder input
    RCC->APB1ENR |= 0x00000001;  // Enable clock for TIM2
 
    TIM2->CR1   = 0x0001;     // CEN(Counter ENable)='1'     < TIM control register 1
    TIM2->SMCR  = 0x0003;     // SMS='011' (Encoder mode 3)  < TIM slave mode control register
    TIM2->CCMR1 = 0x0101;     // CC1S='01' CC2S='01'         < TIM capture/compare mode register 1
    TIM2->CCMR2 = 0x0000;     //                             < TIM capture/compare mode register 2
    TIM2->CCER  = 0x0011;     // CC1P CC2P                   < TIM capture/compare enable register
    TIM2->PSC   = 0x0000;     // Prescaler = (0+1)           < TIM prescaler
    TIM2->ARR   = 0xffffffff; // reload at 0xfffffff         < TIM auto-reload register
    //Tim2->BDTR
    TIM2->CNT = 0x0000;  //reset the counter before we use it  

And to read the count, just


position = TIM2->CNT;

The critical change was in line 16, which used to read


    TIM2->CCMR1 = 0xF1F1;     

Changing "F" to "0" disables the filter for input capture 1 and 2.  "F" sets the filter as slow as possible, so I likely could have left some filtering and still gotten good enough results (with perhaps better noise-immunity).  More details about filtering can be found on page 358 of the 841 page reference manual for the STM32F4 series.

I was able to test up to ~5 Mhz edges using a 12,500 CPR optical encoder coupled to a DC motor, with no missed counts.  Probably could have gone faster, but I didn't have an easy way of testing.

%%  end of useful reference material, on to project-ramblings  %%
%%  proceed at your own risk  %%

Now why did I need to read encoder edges at several megahertz?  Well, this term I took 2.171 (Digital Feedback Control Systems, with Prof. David Trumper and TA Will Bosworth.  A++, would highly recommend.), and for my final project built a subwoofer with closed-loop velocity control of the speaker cone from an audio signal reference.

Lots of possible velocity sensing methods exist, and they can basically all be broken down into three categories:  direct velocity measurement, position measurement with differentiation to get velocity, and acceleration measurement with integration to get velocity.

For direct velocity measurement, I thought of a few strategies.
  • Attach a second voice coil to the speaker cone.  Voice coil voltage will be proportional to velocity.  The only tricky bit is making sure the magnetics of the second voice coil are completely isolated from those of the driving coil.
  • Wrap a second coil of very thin sense-windings around the original voice coil windings.  This has been done.  The problem with this strategy is that, in addition to the back-emf from the permanent magnet, the driving coil and sense coil are coupled.  This can be sorted out with some math, but I preferred not to go that route.
  • Somehow measure the back-emf of the coil between switching transients.  During the dead-time in the switching of the h-bridge (or Class-D amplifier with no output filter, in audio-lingo), the voltage across the coil isn't railed at (±)power-supply voltage, and it should be possible to figure out the speaker's back emf during this period.  I stared at a scope trace of coil voltage for a few minutes and decided this would be really hard.  This would be the holy grail of closed-loop speaker nonsense, as it requires no external sensor.
Measuring position and differentiating can be risky business, because high-frequency noise gets amplified by differentiation.  A few linear position measuring methods are:
  • Laser + mirror + 1-D PSD, as suggested by Prof. Trumper.  Fix a laser, and point it at a little mirror on the speaker cone.  The reflected laser spot lands on the PSD, which gives you cone position.  Gain of the sensor can be adjusted by changing the angles of the laser, mirror, or PSD.  Sadly, PSDs proved difficult to find over a short timeframe.
  • Linear optical encoder strip.  These exist down to absurd resolution.
  • Magnet + hall effect sensor.  I built one of these, but it just didn't have the necessary resolution. 
  • And many more
And of course, for acceleration + integration to get velocity, just stick an accelerometer on the speaker cone.  This could be an attractive option- the usual drift problem associated with integrating an accelerometer can be solved by a slow high-pass filter, since audio is always AC anyway.  However, the accelerations are actually very large:  1 mm peak-to-peak excursion at 100 Hz is already 20 G's of acceleration, which would saturate a lot of cheap accelerometers.

So the path forward was unclear.  The most reasonable solutions are probably the secondary voice coil for sensing or the secondary sense winding, but I was talking to Peter about this, and he suggested using an interferometer for position feedback, and said he had all the parts to put one together.  Cut to a few days later, I show up at MITERS and Peter's built an interferometer in the back room.  The eventual output of the interferometer was to be a digital quadrature signal, hence the need for high-speed quadrature decoding.

So begins the story of the closed-loop subwoofer with interferometer feedback.  More details about the hardware and controls stuff to follow soon...

December 23, 2015

Metal Electric Ukulele

I like taking my gourd ukulele with me when I leave school for more than a week or so, but it's a little annoying to travel with, since it takes up pretty much an entire backpack and is somewhat fragile.  Inspired by Amy's lovely wooden travel ukulele and an awesome one-stringed electric instrument made out of a pipe made by Mike, I made this tiny electric travel ukulele.

The original intent was to basically make an aluimnum stick with four strings and a pickup on it, but after I machined a fretboard and it turned out really nicely, I figured out I should make the rest of the instrument nice while I was at it.

The entire project, from idea to finish, was completed between Thursday night and early Monday morning before I left back to Atlanta.  Some things could definitely be improved (the pickup and tuners, especially), but were done more simply for time.

I started out with this mystery strip of 1/8" x 1.75"  stainless steel found in the putz cruft closet.


I machined it to size on the MITERS Bridgeport, drilled and tapped six M4 holes in it, and fixtured it up in the newly-revived MITERS CNC mill (now running a modern computer with linux CNC, instead of the old DOS-on-a-Pentium-III system).

Squaring up the stock on the CNC mill

The fretboard was roughed out with a 7/32" endmill, and finished with a 1/8" ballnose.  Here's a crappy video of the roughing:


I have very little experience machining stainless, so I just copied some feeds and speeds off the internet.  Seems to have worked out well enough.  I used a brand new endmill for the roughing, and the surface finish turned out fantastic.  Thank you, internet.


Apparently this stock had a lot of stress pre-baked into it, so it warped like crazy when I unscrewed it from its fixturing.  Fortunately it will get pulled flat again by the neck of the instrument.


I laid out the fretboard and some big bar bar magnets for the pickup on a sheet of 3/8" aluminum plate, and started sketching out the rest of the instrument.  For compactness it's headless and has tuners built into the body instead.


Most people I know would have run to a waterjet cutter to cut out the profile, but I have a perhaps somewhat unjustified dislike of waterjets.  Instead, I roughed out the profile on a bandsaw and brought it to shape with some files.  Here's the rough profile after bandsawing:


After shaping the body with some coarse files, I milled the neck to size.  Now I had some nice parallel surfaces for referencing the rest of the machining operations.


Milling slots for the tuners to slide in:


Tuners made from bronze:


The bronze tuners slide in slots, and are each actuated by a screw with a thumbwheel.  I'd have loved to use a proper acme thread screw, but all I could find of appropriate size was a 10-24 threaded rod.

Drilling the holes for the screws to ride in required some interesting fixturing.  I only had an extra 1/2" of vertical space on the bridgeport, after recessing my part in one of the t-slots and putting the drill bit in a collet:


At times like this I wish MITERS had the space for a horizontal mill.  Would make drilling holes like this so much easier.




I CNC milled a bridge of similar style to the fretboard, but out of brass, and made knurled thumbwheels for the tuners:


Milled a cutout for the pickup:



I need to run wires through the body to the pickup, but didn't want to mill a channel in the back of the body.  Instead, I drilled a long hole through the body.  Again, the setup was too tall to use with a chuck, and the particular drill bit I needed didn't fit any collets.  I made a simple split bushing to fit the bit in a 1/2" collet.  These are super simple to make and really handy.  Put round stock in the lathe, turn off a tiny pass to get the OD concentric, center drill, and then drill through with the drill bit you want to hold.  Finally, just bandsaw a slot, and you have a collet to drill bit adapter.


Drilling all the way through to the pickup area:



Next step was finishing body - cleaning up the profile and rounding the edges.  I did the very rough work with a belt sander, and finished with files and sandpaper.

 My selection of files:


Most people seem to shy away from files, but I really love using them.  They can actually remove aluminum remarkably quickly, and you can basically sculpt the metal with files.  It's much more freeform than other machining, which is really refreshing.


And here's the body post filing and sanding:


And here it is assembled.  Yes, that's a carbon fiber pickup cover.  There were some sheets of if lying around, and I thought the contrast with all the shiny metal would be nice.  I don't have any good pictures of winding the pickup, but I just took a big neodymium bar magnet, glued plastic flanges on the front and back, stuck it to a piece steel of stock in the lathe, and put several thousand turns of 36 gauge magnet wire around it.


Side by side with the gourd ukulele:


Here's a pile of nicer pictures:








The only unfinished bit is the headphone jack for plugging it in.  When I get back to a machine shop I'll make a nice cover for it, but right now the jack is just heatshrinked and stuffed into its cavity in the body.

Perhaps a clip of it in-action will follow soon.  I don't have a proper guitar amplifier, so I've just been plugging it into whatever set of speakers is nearby.  A headphone amp for it would be nice, so I can play without bothering people.

November 20, 2015

Shiny Lathe Pictures

Here's a pile of tiny lathe pictures:










Since taking these, I've also re-cut the spindle taper in place to eliminate runout, mounted an encoder to the back of the motor for closed-loop spindle speed control, and leveled the tailstock.  

November 3, 2015

The Tiny Lathe is Working!

After great struggles with the lathe electronics, the lathe is finally working.

One of the main challenges was form factor.  I wanted all the electronics to fit into the base of the lathe, and I wanted the base to be thin (~25mm thick)  so I needed a 600 watt, 45-50 volt power supply that fit in a 25 mm thick package.  Bayley suggested using a Vicor DC-DC converter to generate 48 volts at 600 watts.  Vicor makes some extremely compact converters perfectly suited for this, and they can be had pretty cheaply on ebay.  Only downside is that they need around 300 volts in to turn on.

The basic electronics system would then be wall to doubler for 340 VDC, doubler to Vicor converter for 48 V, and 48 V into an AMC servo drive donated by Dane to drive the spindle motor.

This seemed like a good idea, so I got an appropriately sized Vicor brick on ebay and built up the rest of the system:


And so began the the second challenge: regen.

When the spindle rotates, kinetic energy is stored in the rotating inertia.  When the reference spindle speed is suddenly turned down quickly, the extra kinetic energy in the spindle is converted back into electrical energy and shoved onto the DC bus.  This is all well and good when your power system is supplied by a rechargeable battery, but is much less okay when your source is the wall.  This problem manifests itself as skyrocketing bus voltage when the spindle reference is set to zero from full speed.  The spikes were on the order of 20-30 volts despite the huge bus caps used, which was enough to cause the servo drive's over voltage protection to kick in and shut it down.

One solution is a shunt regulator.  The basic idea is to have a circuit which looks at the bus voltage, and if it sees the bus voltage rising too high, short the bus through a resistor to burn that energy.  Sounds easy enough, should just be  comparator,  FET, big resistor, and some passives, right?

Version 1.  The TO-247 is a big diode to make sure any voltage spike doesn't make it back to the power supply:


Version 1 was derp because the comparator sometimes couldn't pull down the mosfet gate hard enough by itself, or something like that.  The symptom was that occasionally the FET would latch on.

Versions 2/3 had real gate drivers, and actually worked:


At this point, my electronics (minus Vicor brick) looked like this.  Getting less attractive, as I had to shove in an extra 10 V supply to run the shunt regulator.


More problems.  The Vicor converter I got on ebay was DOA.  I returned it, and ordered another identical one from a different seller.  New one shows up and is also DOA.....

Time for something different.  Bayley pointed me to another Vicor product, Vichip BCM converters like this one.  Normally these cost ~$75 a pop on Digikey, but can be found on ebay for $10.  These are unregulated, fixed ratio DC-DC converters good for 300(!) watts each in about a square inch of chip.  They output 1/8 of their input voltage, so like the other Vicor converters I tried, they needed >300 volts in to get useful voltage out.  They also come in a funny surface mount package.

I ordered a few of them, and figured while I was at it I should lay out a PCB for the doubler, Vichips, and shunt regulator:


The shunt regulator is the top left corner.  The large D2-Pak devices are the fet, power resistors, and diode.  In the middle are 3 Vichips, and to the right the rectifier and caps for the doubler.  For gate drive and logic power there's a TI LM2594 12V buck IC.

Through the magic of 3pcb, boards appeared:


Populated:


The board required a little fixing to get working.  I left the comparator ground pin unconnected accidentally (the net in the eagle schematic looked connected but actually wasn't).  More importantly, I didn't read the Vichip datasheet carefully enough, and missed two important details.

First, they really don't like output capacitance.  I had to remove all the output capacitors to get the thing to turn on.  Instead you should put the caps on the input.

Second, the Vichips can be expected to draw 6.5-13 W idle.  They got seriously hot just sitting there doing nothing.  A kill-a-watt confirmed that the board consumed 22W idle.

I didn't design the board for easy heat-sinking, but I was able to make it work by machining an aluminum spacer which gets sandwiched between the Vichips and lathe base with some thermal pads.  I forgot to take any pictures of the final electronics assembly, but here's the first chips generated under the lathe's own power (not a bench supply):


And a beauty shot:


I'lll do another post with more shots of the whole thing soon.  The lathe is currently functional, but there are a number of things I'd still like to do, such as:

  • Take a finishing pass of the inside of the ER-32 taper to guarantee its concentricity with the spindle.
  • Finish the new tailstock riser.  I've machined it, but mismeasured somewhere and it's a millimeter too tall.
  • Add closed-loop spindle speed control.  
  • Make chuck backplates so I can use real chucks, not just collets.
  • Add a leadscrew and motor for power feed.

October 17, 2015

Ball Turner

I recently stumbled across a neat design for a ball turner on youtube, and ebay-rage-ordered all the parts to build one.


It consists of:

- A CXA (fits the MITERSlathe) boring bar holder with a 3/4" split bushing
- The cheapest 2" boring head I could find
- A 3/4" shank for the boring head

Total damage was ~$100.

I turned a couple 3/4" I.D. thrust bushings:


A handle:


The little radial-keyway allows the handle to be rotated 180 degrees and still have positive interference with the back of the boring head shank (which I filed a matching keyway into).



Threw together a quick carbide insert holder.  Someone else was on the mill, so all the shaping was done with a file, belt sander, and bench grinder:


Almost done.  The two set screws are used to tighten the play out of the split bushing:



To test it out, I turned a ball for the end of the handle.  Success!


The ball was tapped, threaded onto the end of the handle, and locked with some red loctite:





Not bad for an afternoon.