The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Category: Machine Shop

Mechanical widgetry

  • Recycled Heatsink: Hole Plugs

    I actually did get around to plugging the holes directly under the power resistors on those heatsinks, even though we all know it makes absolutely no difference whatsoever.

    Heatsink hole plugs
    Heatsink hole plugs

    Start with some 5/16-inch aluminum rod, face and center-drill one end, turn down about two inches to a scant 0.200 inch diameter, saw off a stub on the end.

    Grab the stub in the 3-jaw Sherline chuck clamped to the mill table and slice off 0.240 inch slugs using a teeny slitting saw and manual CNC.

    No pix of the setup, for reasons that made sense at the time, but that project gives you the general idea.

    Repeat three times to get 3 x 6 = 18 slugs, plus a few spares.

    Clean out the heatsink holes, clamp a bar (covered with tape) on the flat side, butter up the holes & slugs with JB Weld epoxy, squish ’em in place, scrape off the excess epoxy after a few hours.

    Actually, this was a thinly veiled excuse to get my shop assistant some Quality Shop Time on the lathe and CNC mill. Wouldn’t you do the same?

  • From Peanuts to Chips: EMC2 on the Atom

    Sherline CNC with Foxconn D520 Atom
    Sherline CNC with Foxconn D520 Atom

    Before I forget, here’s how one gets from packing peanuts to a running EMC2 installation:

    The hardware:

    The PC won’t need a CD after it’s up and running, but it’s easiest to boot/install from a CD. Get a random SATA CD drive from eBay or, more usefully, a USB-to-SATA/IDE converter, harvest an IDE CD drive from a old donor box, plug it into the Foxconn box, and tweak the BIOS to boot from that USB device.

    Install Ubuntu 10.04 (not the current 10.10) from CD. I use the mini-iso CD (link to Overview), which has the advantage of fetching the current version of everything from the Ubuntu site. You can putz around making a bootable USB image, which is cute, but the USB-to-IDE drive adapter will come in handy for other things.

    Toward the end of the installation you get a list of configurations and packages to install. Pick Ubuntu desktop, down near the bottom of the list. Include SSH server if you want to do remote maintenance.

    Install / tweak / twiddle to set up some comfort items:

    • NFS shares to the file server holding my CNC files
    • Desktop sharing so I can dry-run from a warmer chair
    • Screen backdrop on file server to show network is running
    • Browser plugins & so forth

    When that’s done, aim Firefox at the EMC2 wiki, and follow the instructions to download & run the script that installs EMC2.

    Then devote one of the CPU cores to the real-time kernel, although the new GRUB2 bootloader is less tweak-friendly. Reboot, select that kernel, and away you go.

    Run the EMC2 Latency Test to be sure everything is OK.

    Run the StepConf Wizard to generate a config file suitable for the new machinery.

    This set of hints & tips may be helpful for new-to-Ubuntu machinists.

    Lest all this seem like a lot of hocus pocus, remember that you’re
    becoming a system integrator with your fingers on all the knobs and
    buttons normally hidden behind the “Do Not Open: No User Serviceable Parts Inside” covers.

    You could, of course, pay somebody to do this for you… [grin]

  • Axial Fan Parameters

    Just got a stack of surplus fans for the heatsinks I’ll probably use in the disinsector: Cofan FP925HH12B. Either these are really old or there’s a typo in the model number printed on the fan label. I’d expect it to be …9225… to indicate a 92 mm frame x 25 mm thickness. It’s close enough to get to their specs page.

    Cofan axial fan
    Cofan axial fan

    They draw 370 mA (rated 450 mA) in free air = 4.4 W. The “HH” designation means “Super High Speed” and wow are they noisy despite their 37.6 dbA spec. Fortunately, that won’t matter inside a closed box.

    The label is downstream, which means the hub and bare blades are upstream. They’ll be under the shelves, so I think I can get away without guards.

    The model number breakdown says that they have a “protection chip” which seems to be the thing that produces the status output. That output (yellow wire) is a square wave with a frequency twice the fan’s actual speed: 107 Hz → 6420 cycles / min → 3210 RPM. The open collector output requires a pullup resistor to +5 V. It take a while to spin up the fan enough to get a decent output waveform; don’t sample the status for maybe a second after power-on.

    Putting a fan on that crude air flow straightener produces about 3.2 m/s across the exit end, which works out to 10.5 ft/s = 630 ft/min. There’s a distinct flow dent near the middle of the air column, so I suspect the baffles are too far upstream for this fan.

    Making a number of barely justifiable assumptions, the output is around 1.4 m3/min = 50 ft3/min, which is close enough to the rated free air output of 1.8 m3/min = 64 ft3/min.

    They will start and run at 5 V (below the 8 V minimum rating), draw 110 mA, spin at 1470 RPM, and push 1.1 m/s. For whatever that’s worth.

  • Atom D520: Config Files for Smoother Sherline Stepping

    The dual-core-ness of the D520, as set up there, allows a distinct improvement in the EMC2 BASE_PERIOD setting, which is exactly why I undertook this adventure.

    The 100 µs period I used on the Dell Dimension 4550 ensured the occasional long-latency burps wouldn’t cause much trouble… and they didn’t. The setup used the HAL step generator’s ability to supply a single pulse within one base period, so the maximum stepping rate was 1/100 µs = 10 k steps / second.

    However, that also determines the granularity of speed changes, so the controller can only drive the motors at multiples of the basic 100 µs without interpolating. For example, the four fastest step rates are:

    • 1/100 µs = 10 k step/sec
    • 1/200 µs =5 k step/sec
    • 1/300 µs = 3.3 k step/sec
    • 1/400 µs = 2.5 k step/sec

    The motors have 200 major steps / revolution and run in quarter-step mode: 800 microsteps / revolution. The axes have 20 turn-per-inch leadscrews, thus requiring 16 k step pulses per inch of travel.

    That means the corresponding traverse speeds are (step/sec) / (step/inch):

    • 10 k step/sec -> 0.625 in/sec = 37 in/min
    • 5 k step/sec -> 0.313 in/sec = 18.75 in/min
    • 3.3 k step/sec -> 0.206 in/sec = 12.37 in/min
    • 2.5 k step/sec -> 0.156 in/sec = 9.37 in/min

    Those are fairly large jumps between the speeds, which means the motor acceleration when the step rate changes is fairly high. HAL interpolates by bunching groups of pulses, but higher resolution is better.

    The Atom CPU has latencies under 10 µs, with no large burps that I’ve seen so far, so I set the BASE_PERIOD to 50 µs. However, that required changing the HAL step generator to produce a pulse during two successive periods (one high, one low) to keep the pulses wide enough for the motor controller. That means the highest step rate is still 10 k steps/sec and the top speed is still 37 inch/min.

    However, HAL can now adjust the period in smaller increments with lower acceleration between the jumps. The four fastest rates are now:

    • 1/100 µs = 10 k step/sec -> 0.625 in/sec = 37 in/min
    • 1/150 µs =6.7 k step/sec -> 0.417 in/sec = 25 in/min
    • 1/200 µs = 5 k step/sec -> 0.313 in/sec = 18.75 in/min
    • 1/250 µs = 4 k step/sec -> 0.250 in/sec = 15 in/min

    A stock Sherline CNC milling machine is rated for 22 inch/min (0.37 inch/sec) rapid motion on all three axes. That means the maximum step rate is

    • (0.37 inch/sec) * (16 k step/in) = 5.9 kHz

    Quite some years ago, I rebuilt my Sherline controller box to reduce its electrical and acoustic noise, then did a clean-room reimplementation of the firmware in the PIC microcontrollers. After the dust settled, my firmware could handle 8 k steps / sec, which works out to 0.5 in/sec = 30 in/min.

    That turns out to be slightly more aggressive than the whole lashup can tolerate; I can hear the motors take occasional hits as they miss the odd step at 30 inch/min.

    So I set the overall MAX_LINEAR_VELOCITY = 0.400 inch/sec = 24 inch/min, which is also the MAX_VELOCITY for both X and Y. The Z axis, as always, is happier with a bit slower top speed: 0.333 inch/sec = 20 inch/min. The maximum step rate is 0.4 x 16 k = 6.4 kHz, comfortably under the controller’s upper limit.

    The MAX_ACCELERATION for X and Y = 5.0 in/sec2, with Z at 3.0. STEPGEN_MAXACCEL for each axis is twice that; I have each axis set for a few mils of backlash compensation.

    With all that in mind, the changed configuration files look like this, with the others remaining as described there.

    Sherline.hal, with the new stepgen pulse specs

    # Generated by stepconf at Sat Aug 23 12:10:22 2008
    # If you make changes to this file, they will be
    # overwritten when you run stepconf again
    loadrt trivkins
    loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD traj_period_nsec=[EMCMOT]SERVO_PERIOD key=[EMCMOT]SHMEM_KEY num_joints=[TRAJ]AXES
    loadrt probe_parport
    loadrt hal_parport cfg="0x378 out"
    setp parport.0.reset-time 60000
    loadrt stepgen step_type=0,0,0,0
    loadrt pwmgen output_type=0
    
    addf parport.0.read base-thread
    addf stepgen.make-pulses base-thread
    addf pwmgen.make-pulses base-thread
    addf parport.0.write base-thread
    addf parport.0.reset base-thread
    
    addf stepgen.capture-position servo-thread
    addf motion-command-handler servo-thread
    addf motion-controller servo-thread
    addf stepgen.update-freq servo-thread
    addf pwmgen.update servo-thread
    
    net spindle-cmd <= motion.spindle-speed-out => pwmgen.0.value
    net spindle-enable <= motion.spindle-on => pwmgen.0.enable
    net spindle-pwm <= pwmgen.0.pwm
    setp pwmgen.0.pwm-freq 100.0
    setp pwmgen.0.scale 1166.66666667
    setp pwmgen.0.offset 0.114285714286
    setp pwmgen.0.dither-pwm true
    net spindle-cw <= motion.spindle-forward
    
    net estop-out => parport.0.pin-01-out
    net xdir => parport.0.pin-02-out
    net xstep => parport.0.pin-03-out
    setp parport.0.pin-03-out-reset 0
    setp parport.0.pin-04-out-invert 1
    net ydir => parport.0.pin-04-out
    net ystep => parport.0.pin-05-out
    setp parport.0.pin-05-out-reset 0
    setp parport.0.pin-06-out-invert 1
    net zdir => parport.0.pin-06-out
    net zstep => parport.0.pin-07-out
    setp parport.0.pin-07-out-reset 0
    net adir => parport.0.pin-08-out
    net astep => parport.0.pin-09-out
    setp parport.0.pin-09-out-reset 0
    net spindle-cw => parport.0.pin-14-out
    net spindle-pwm => parport.0.pin-16-out
    net xenable => parport.0.pin-17-out
    
    setp stepgen.0.position-scale [AXIS_0]SCALE
    setp stepgen.0.steplen 1
    setp stepgen.0.stepspace 1
    setp stepgen.0.dirhold 60000
    setp stepgen.0.dirsetup 60000
    setp stepgen.0.maxaccel [AXIS_0]STEPGEN_MAXACCEL
    net xpos-cmd axis.0.motor-pos-cmd => stepgen.0.position-cmd
    net xpos-fb stepgen.0.position-fb => axis.0.motor-pos-fb
    net xstep <= stepgen.0.step
    net xdir <= stepgen.0.dir
    net xenable axis.0.amp-enable-out => stepgen.0.enable
    
    setp stepgen.1.position-scale [AXIS_1]SCALE
    setp stepgen.1.steplen 1
    setp stepgen.1.stepspace 1
    setp stepgen.1.dirhold 60000
    setp stepgen.1.dirsetup 60000
    setp stepgen.1.maxaccel [AXIS_1]STEPGEN_MAXACCEL
    net ypos-cmd axis.1.motor-pos-cmd => stepgen.1.position-cmd
    net ypos-fb stepgen.1.position-fb => axis.1.motor-pos-fb
    net ystep <= stepgen.1.step
    net ydir <= stepgen.1.dir
    net yenable axis.1.amp-enable-out => stepgen.1.enable
    
    setp stepgen.2.position-scale [AXIS_2]SCALE
    setp stepgen.2.steplen 1
    setp stepgen.2.stepspace 1
    setp stepgen.2.dirhold 60000
    setp stepgen.2.dirsetup 60000
    setp stepgen.2.maxaccel [AXIS_2]STEPGEN_MAXACCEL
    net zpos-cmd axis.2.motor-pos-cmd => stepgen.2.position-cmd
    net zpos-fb stepgen.2.position-fb => axis.2.motor-pos-fb
    net zstep <= stepgen.2.step
    net zdir <= stepgen.2.dir
    net zenable axis.2.amp-enable-out => stepgen.2.enable
    
    setp stepgen.3.position-scale [AXIS_3]SCALE
    setp stepgen.3.steplen 1
    setp stepgen.3.stepspace 1
    setp stepgen.3.dirhold 60000
    setp stepgen.3.dirsetup 60000
    setp stepgen.3.maxaccel [AXIS_3]STEPGEN_MAXACCEL
    net apos-cmd axis.3.motor-pos-cmd => stepgen.3.position-cmd
    net apos-fb stepgen.3.position-fb => axis.3.motor-pos-fb
    net astep <= stepgen.3.step
    net adir <= stepgen.3.dir
    net aenable axis.3.amp-enable-out => stepgen.3.enable
    
    net estop-out <= iocontrol.0.user-enable-out
    net estop-out => iocontrol.0.emc-enable-in
    
    loadusr -W hal_manualtoolchange
    net tool-change iocontrol.0.tool-change => hal_manualtoolchange.change
    net tool-changed iocontrol.0.tool-changed <= hal_manualtoolchange.changed
    net tool-number iocontrol.0.tool-prep-number => hal_manualtoolchange.number
    net tool-prepare-loopback iocontrol.0.tool-prepare => iocontrol.0.tool-prepared
    

    Sherline.ini, with new periods, speeds, and accelerations

    # Ed Nisley - KE4ZNU
    # Just do not run stepconf ever again...
    
    [EMC]
    MACHINE = Sherline-XYZA
    DEBUG = 0
    RS274NGC_STARTUP_CODE = G21 G40 G49 G54 G80 G90 G92.1 G94 G97 G98
    
    [DISPLAY]
    DISPLAY = axis
    EDITOR = gedit
    GEOMETRY = AXYZ
    POSITION_OFFSET = RELATIVE
    POSITION_FEEDBACK = ACTUAL
    MAX_FEED_OVERRIDE = 3.0
    INTRO_GRAPHIC = /home/ed/emc2/configs/Sherline-XYZA/Sherline.gif
    INTRO_TIME = 3
    #PROGRAM_PREFIX = /mnt/bulkdata/
    PROGRAM_PREFIX = ~/emc2/nc_files
    #INCREMENTS = .1in .05in .01in .005in .001in .0005in .0001in
    INCREMENTS = 10 mm, 1 mm, 0.1 mm, 90 deg, 45 deg, 10 deg
    
    [FILTER]
    PROGRAM_EXTENSION = .py Python Script
    py = python
    
    [TASK]
    TASK = milltask
    CYCLE_TIME = 0.010
    
    [RS274NGC]
    PARAMETER_FILE = emc.var
    
    [EMCMOT]
    EMCMOT = motmod
    SHMEM_KEY = 111
    COMM_TIMEOUT = 1.0
    COMM_WAIT = 0.010
    BASE_PERIOD = 50000
    SERVO_PERIOD = 1000000
    
    [HAL]
    HALUI=halui
    HALFILE = Sherline.hal
    HALFILE = custom.hal
    HALFILE = Logitech_Gamepad.hal
    POSTGUI_HALFILE = custom_postgui.hal
    
    [TRAJ]
    AXES = 4
    COORDINATES = X Y Z A
    MAX_ANGULAR_VELOCITY = 45.00
    DEFAULT_ANGULAR_VELOCITY = 36.0
    LINEAR_UNITS = inch
    ANGULAR_UNITS = degree
    CYCLE_TIME = 0.010
    DEFAULT_VELOCITY = 0.400
    MAX_LINEAR_VELOCITY = 0.400
    POSITION_FILE =	lastposition.txt
    NO_FORCE_HOMING = 1
    
    [EMCIO]
    EMCIO = io
    CYCLE_TIME = 0.100
    TOOL_TABLE = Sherline.tbl
    TOOL_CHANGE_AT_G30 = 1
    
    [AXIS_0]
    TYPE = LINEAR
    MAX_VELOCITY = 0.400
    MAX_ACCELERATION = 5.0
    STEPGEN_MAXACCEL = 10.0
    SCALE = 16000.0
    FERROR = 0.05
    MIN_FERROR = 0.01
    MIN_LIMIT = -1.0
    MAX_LIMIT = 9.5
    BACKLASH = 0.003
    HOME_IS_SHARED = 1
    HOME_SEQUENCE = 2
    HOME_SEARCH_VEL = 0.3
    HOME_LATCH_VEL = 0.016
    HOME_FINAL_VEL = 0.4
    HOME_OFFSET = 9.1
    HOME = 4.5
    
    [AXIS_1]
    TYPE = LINEAR
    MAX_VELOCITY = 0.400
    MAX_ACCELERATION = 5.0
    STEPGEN_MAXACCEL = 10.0
    SCALE = 16000.0
    FERROR = 0.05
    MIN_FERROR = 0.01
    MIN_LIMIT = -0.5
    MAX_LIMIT = 4.90
    BACKLASH = 0.003
    HOME_IS_SHARED = 1
    HOME_SEQUENCE = 1
    HOME_SEARCH_VEL = -0.3
    HOME_LATCH_VEL = -0.016
    HOME_FINAL_VEL = 0.4
    HOME_OFFSET = 0.0
    HOME = 4.0
    
    [AXIS_2]
    TYPE = LINEAR
    MAX_VELOCITY = 0.333
    MAX_ACCELERATION = 3.0
    STEPGEN_MAXACCEL = 6.0
    SCALE = 16000.0
    FERROR = 0.05
    MIN_FERROR = 0.01
    MIN_LIMIT = 0.0
    MAX_LIMIT = 6.930
    BACKLASH = 0.005
    HOME_IS_SHARED = 1
    HOME_SEQUENCE = 0
    HOME_SEARCH_VEL = 0.200
    HOME_LATCH_VEL = 0.016
    HOME_FINAL_VEL = 0.3
    HOME_OFFSET = 6.93
    HOME = 6.5
    
    [AXIS_3]
    TYPE = ANGULAR
    ###WRAPPED_ROTARY = 1
    MAX_VELOCITY = 40.0
    MAX_ACCELERATION = 250.0
    STEPGEN_MAXACCEL = 275.0
    SCALE = 160.0
    FERROR = 1
    MIN_FERROR = .25
    MIN_LIMIT = -999999999.9
    MAX_LIMIT =  999999999.9
    HOME_SEARCH_VEL = 0
    HOME_LATCH_VEL = 0
    HOME = 0.0
    

     

     

  • An Atom for the Sherline Milling Machine

    Somewhat against the recommendations of the experts on the EMC2 mailing list, I bought a Foxconn R30-D2 with an Intel Atom D520 from Newegg during a sale: add 2 GB of memory from Crucial, a spare SATA drive from my collection, and it’s ready to go. I also bashed a spare parallel printer port card into the box, although it isn’t really needed right now: unlike the Intel system board, Foxconn brings the on-board parallel port directly to the back panel.

    The Foxconn support site is a nightmare and was, AFAICT, dead for the first few weeks I had the box. The key fact to remember is that the -D2 part of the number specifies the system board / CPU, so the same downloads / BIOS updates apply to the R10, R20, R30, and R40 models. There is no new BIOS available to fix the “fan runs all the time” problem reported by so many people.

    I installed Ubuntu 10.04 LTS from the distro CD, then ran the EMC2 installation script. All that is routine, as described there. You probably want to install the EMC2 Live CD, though, and to get much the same result with less fiddling.

    Turn off Hyperthreading in the BIOS, which seems to make the RTAI real-time hypervisor happier. Under those conditions, the default install has an interrupt latency of about 13 µs.

    The Atom D520 is a dual-core processor and you can devote one core to EMC2’s real-time functions, thus eliminating much of the usual contention and interrupt latency. That works surprisingly well and is completely automagic after you add the isolcpus=1 kernel option to the appropriate line in /boot/grub/grub.cfg. Thusly:

    linux	/boot/vmlinuz-2.6.32-122-rtai root=UUID=57fe2b04-ffe4-4de3-a597-89bd4ed01018 ro  vga=758  noquiet nosplash isolcpus=1
    

    With that done, the latency drops down under 8 µs, which is entirely satisfactory. I can push it to 10 µs by doing stupid things: scrubbing a glxgears window over a Flash video in Firefox, for example.

    The catch is that the wonderful new grub2 bootloader rewrites its boot configuration file on the fly, based on a set of rules that, evidently, cannot apply different kernel configuration parameters to different kernels within the same partition. As a result, you must choose between:

    • Running stock Ubuntu on one core
    • Manually tweaking grub.cfg after every kernel update

    Given that an Atom isn’t exactly a blinding flash and a deafening report in the performance department, I opted for the second method. If Ubuntu was still using Legacy Grub, then I’d just tweak menu.lst and be done with it. This is, I suppose, progress.

    Memo to Self: Adjust grub.cfg every mumble time.

    [Update: There’s now a fix for that, as described in the EMC2 wiki. Go for it!]

  • Opening a USB Stick

    After I failed to fix that old USB memory, my friend suggested a brain transplant: swap the Flash chip from the dead stick into a new one. That has a low chance of success because the innards will be different for every manufacturer and, even for USB sticks of the same vintage, nothing remains the same from lot to lot.

    Anyhow, I removed the fancy end caps from the donor stick, which looks to be swag from a medical conference:

    Case caps removed
    Case caps removed

    The key step is to crack the case open without damaging anything inside. This technique works wonderfully well:

    Cracking the case
    Cracking the case

    Grab diagonally opposing corners in a bench vise and slowly increase the clamping force until the case snaps apart. Poke a screwdriver in the gap, remove the case from the vise, and pry the thing open.

    As it turned out, the innards were completely different: different Flash controllers and different Flash memory chips. So it goes.

    Not surprisingly, you can find the data sheets / manuals / configuration utilities for the Flash controller chips by searching for the obvious keywords. Machine translation is your friend…

  • Salvaged Heatsink Reconstruction

    Heatsink mounting flanges
    Heatsink mounting flanges

    I decided to replace the sawed-off flanges on that salvaged heatsink to make all three use the same mounting arrangement, whatever that might turn out to be.

    Nothing particularly fancy about it: two random chunks of aluminum sheet and two thinner strips, sanded to roughen their surfaces, and epoxied into place.

    The repaired heatsink is marginally taller than its siblings, but not so anybody will ever notice, and it’s no more off-kilter than they are, either.

    A quartet of 5/16-inch lathe bits provided the right spacing to hold the heatsink over its new flanges while the epoxy filled in all the gaps and irregularities. I probably should have paid a bit more attention to squaring things up, but it’s good enough for what it’ll need to do.

    Heatsink up on blocks
    Heatsink up on blocks