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: Software

General-purpose computers doing something specific

  • Skeinforge Build Parameters

    The extrusion settings, more or less, kinda-sorta, for the latest objects:

    • Layer thickness 0.33 mm
    • Perimeter w/t = 1.75 = 0.58 mm
    • Fill w/t = 1.65 (or as needed)
    • Feed 40 mm/s
    • Flow 2 rev/min with geared stepper
    • Perimeter feed/flow 75% of normal (probably not needed)
    • First layer at 20% of normal feed & flow
    • 210 °C (some at 220 °C) Thermal Core
    • 120 °C build platform (lower at plate surface)
    • Reversal: 20 rev/min, 90 ms reverse & push-back (lower better?)
    • Fill: 2 extra shells, 3 solid surface layers, 0.25 solidity, 0.3 overlap
    • Thread sequence: Loops / perimeter / infill
    • Cool: slow down, minimum 15 sec/layer
    • Bottom / splodge / stretch disabled

    Wouldn’t it be great if you could export all that stuff to a text file in a readable format? The CSV files come close, but they’re not really meant for human consumption.

    Subject to revision, your mileage may vary, past performance is no indication of future yield, perfectly safe when used exactly as directed, shake before using, don’t touch that dial!

  • Adobe Reader Print Colors

    While printing up handouts for my talk at Cabin Fever, I finally tracked down why Adobe Reader was producing such crappy colors.

    The left is before and the right is after the fix, scanned at the same time with the same image adjustments:

    Oversaturated vs normal printing
    Oversaturated vs normal printing

    All of the print settings appeared correct (plain paper, 720 dpi, normal contrast, etc, etc), but Adobe Reader (and only Adobe Reader) looked like it was trying to print on vastly higher quality paper than I was using. Too much ink, too much contrast, generally useless results.

    The solution was, as always, trivial, after far too much fiddling around.

    In Reader’s Print dialog, there’s a button in the lower-left corner labeled Advanced. Clicky, then put a checkmark in the box that says Let printer determine colors.

    And then It Just Works.

    Equally puzzling: ask for 25 copies of a two-page document, check the Collate box, and you get 25 page 1, 25 page 2, then more page 1 starts coming out. I bet I’d get 25 x 25 sheets of paper by the time it gave up.

    I have no idea what’s going on, either.

    Memo to Self: verify that the box stays checked after updates.

  • Installing OpenSCAD on Arch Linux

    This was more tedious than it ought to be, but OpenSCAD now runs on my desktop box and uses OpenGL 2.2, courtesy of a not too obsolete nVidia GeForce 9400 dual-head card.

    OpenSCAD has a slew of pre-reqs, most of which were already installed. However, the openscad and cgal non-packages live in the Arch AUR collection, so they required manual twiddling to install.

    The pre-reqs:

    • cgal, which in turn requires cmake via pacman
    • opencsg

    The recommended PKGBUILD patch is easy enough to do by hand.

    The final build step takes ten minutes using both cores, but the final result uses OpenCSG the way it should.

    Oddly, the OpenSCAD rendering process for the few objects I’ve checked takes longer than on the laptop. Weird.

    This does not get the most recent build from the developers, but it’s close enough for my simple needs right now. The mailing list archive is invaluable.

    Then there was the laptop saga. Maybe the reason the laptop is faster is that it’s not actually using OpenCSG at all.

  • Thermocouple Calibration: Linear Regression

    With the thermistors nestled all snug in their wells, I turned on the heat and recorded the temperatures. I picked currents roughly corresponding to the wattages shown, only realizing after the fact that I’d been doing the calculation for the 5 Ω Thing-O-Matic resistors, not the 6 Ω resistor I was actually using. Doesn’t matter, as the numbers depend only on the temperatures, not the wattage.

    This would be significantly easier if I had a thermocouple with a known-good calibration, but I don’t. Assuming that the real temperature lies somewhere near the average of the six measurements is the best I can do, so … onward!

    Plotting the data against the average at each measurement produces a cheerful upward-and-to-the-right graph:

    Data vs Ensemble Average
    Data vs Ensemble Average

    So the thermocouples seem reasonably consistent.

    Plotting the difference between each measurement and the average of all the measurements at that data point produces this disconcertingly jaggy result:

    Difference from Ensemble Average
    Difference from Ensemble Average

    The TOM thermocouple seems, um, different, which is odd, because the MAX6675 converts directly from thermocouple voltage to digital output with no intervening software. It’s not clear what’s going on; I don’t know if the bead was slightly out of its well or if that’s an actual calibration difference. I’ll check it later, but for now I will simply run with the measurements.

    Eliminating the TOM data from the average produces a better clustering of the remaining five readings, with the TOM being even further off. The regression lines show the least-squares fit to each set of points, which look pretty good:

    Difference from Average without TOM
    Difference from Average without TOM

    Those regression lines give the offset and slope of the best-fit line that goes from the average reading to the actual reading, but I really need an equation from the actual reading for each thermocouple to the combined average. Rather than producing half a dozen graphs, I applied the spreadsheet’s SLOPE() and INTERCEPT() functions with the average temperature as Y and the measured temperature as X.

    That produced this table:

                        TOM     MPJA  Craftsman A  Craftsman B   Fluke T1  Fluke T2
    M = slope        1.0534   0.5434       0.5551       0.5539     1.0112    1.0154
    B = intercept   -1.6073 -15.3703     -19.4186     -16.9981    -0.7421   -0.3906
    

    And then, given a reading from any of the thermocouples, converting that value to the average requires plugging the appropriate values from that table into good old

    • y = mx + b

    For example, converting the Fluke 52 T1 readings produces this table of values. The Adjusted column shows the result of that equation and the Delta Avg column gives the difference from the average temperature (not shown here) for that reading.

    Fluke T1    Adjusted   Delta Avg   Max Abs Err
    21.0        20.5        -0.4          0.78
    29.0        28.6        -0.3
    34.8        34.4        -0.3
    45.5        45.3        -0.2
    50.1        49.9         0.0
    52.0        51.8         0.2
    69.3        69.3         0.3
    76.4        76.5         0.4
    78.9        79.0         0.6
    107.9       108.4         0.2
    112.3       112.8         0.4
    117.5       118.1         0.3
    127.8       128.5        -0.2
    133.2       134.0         0.1
    136.6       137.4         0.1
    138.1       138.9         0.1
    146.4       147.3        -0.4
    155.8       156.8        -0.8
    

    The Max Avg Error (the largest value of the absolute difference from the average temperature at each point) after correction is 0.78 °C for this set. The others are less than that, with the exception of the TOM thermocouple, which differs by 1.81 °C.

    So now I can make a whole bunch of temperature readings, adjust them to the same “standard”, and be off by (generally) less than 1 °C. That’s much better than the 10 °C of the unadjusted readings and seems entirely close enough for what I need…

  • Faking OpenGL 2.0 on Intel i945 Hardware

    OpenSCAD grumps about not finding OpenGL 2.0 whenever it starts up on my ancient laptop, which is tedious: that situation just isn’t going to change. Not a fatal error, although I do wonder what the OpenCSG rendering would look like.

    Anyhow, a bit of rummaging turns up a hack that’ll cause OpenSCAD to STFU and just start up. That doesn’t make OpenCSG work, which is pretty much not a problem for my simple needs.

    On Ubuntu-flavored distros, install driconf, then activate two options (in the Performance and Debugging tabs, respectively):

    • Enable limited ARB_fragment_shader support on 915/945
    • Enable stub ARB_occlusion_query support on 915/945

    And then It Just Works…

     

     

  • Cabin Fever Tchotchke: Engraved Dog Tag

    Once again I’m planning to attend the Cabin Fever Expo in York; my shop assistant says this year she won’t barf in the kitchen sink Thursday evening just before bedtime…

    If I’m going to haul a Sherline CNC setup that far and spend all day talking machining, I must have some tchotchkes / swag to talk about. We figured a small plastic dog tag with relevant URLs would be appropriate.

    Cabin Fever Dog Tag
    Cabin Fever Dog Tag

    I modeled the tag after my father’s WWII tag, including the mysterious notch. The rounded ends actually have three curves: two small fairing arcs blend the sides into the end cap.

    The G-Code routine figures out all the coordinates and suchlike from some basic physical measurements & guesstimates, so tweaking the geometery is pretty straightforward. There was a blizzard going on while I wrote it: a fine day to spend indoors hacking code.

    My assistant fired up Inkscape, laid out the text, figured out how to coerce G-Code out of Inkscape using the cnc-club.ru extension, then aligned it properly with the center of the chain hole as the origin on the right side. My routine calls the text G-Code file as a subroutine.

    The extension’s header and footer files wrap EMC2’s SUB / ENDSUB syntactic sugar around the main file. The default files include an M2 that kills off the program; took a while to track that one down.

    The header file:

    O<dogtagtext> SUB
    

    And the matching footer file:

    O<dogtagtext> ENDSUB
    

    The Inkscape-to-gcode instructions come out with absolute coordinates relative to the origin you define when you create the layout. The nested loops in my wrapper slap a G55 coordinate offset atop each label in turn, then call the subroutine.

    The result is pretty slick:

    Screenshot: AXIS Dog Tags
    Screenshot: AXIS Dog Tags

    I carved out that proof-of-concept label atop double-sided adhesive tape, but peeling off the goo is a real pain; a 2×3 array will be much worse. I’d rather do that than figure out how to clamp the fool things to the sacrificial plate, though.

    The engraving is 0.2 mm deep with a Dremel 30 degree tool. My shop assistant describes it as “disturbing” the acrylic, not actually engraving a channel. This isn’t entirely a Bad Thing, as the font isn’t quite a stick font and the outline of each character mushes together. We must fiddle with the font a bit more; she favors a boldified OCR-A look.

    Some lessons:

    • The Kate G-Code syntax highlighter isn’t down with EMC2’s dialect
    • Be very sure you touch off the workpiece origin in G54, not G55
    • Xylene doesn’t bother acrylic and works fine on tape adhesive
    • Symlinks aimed across an NFS link work fine in ~/emc2/nc_files/
    • That 2×3 array may be too big for the Sherline’s tooling plate
    • Tool length probing FTW!

    The G-Code:

    (Cabin Fever 2011 Dogtag)
    (Ed Nisley - KE4ZNU - December 2010)
    (Origin at center of chain hole near right side)
    (Stock held down with double-stick tape)
    
    (--------------------)
    (Flow Control)
    
    #<_DoText>      = 1
    #<_DoDrill>     = 1
    #<_DoMill>      = 1
    
    ( Sizes and Shapes)
    
    (-- Tag array layout)
    
    #<_NumTagsX>    = 3                         (number of tags along X axis)
    #<_NumTagsY>    = 2                         ( ... Y axis)
    
    #<_TagSpaceX>   = 60                        (center-to-center along X axis)
    #<_TagSpaceY>   = 35                        ( ... Y axis)
    
    (-- Tag Dimensions)
    
    #<_TagSizeX>    = 50.8                      (2.0 inches in WWII!)
    #<_TagSizeY>    = 28.6                      (1-1/8 inches)
    #<_TagSizeZ>    = 2.0
    
    #<_HoleOffsetX> = 4.0                       (hole center to right-side tag edge)
    
    #<_NotchSizeX>      = 3.5                   (locating notch depth from far left edge)
    #<_NotchCtrY>       = 5.0                   (locating notch from Y=0)
    
    #<_NotchAngleBot>   = 30                    (lower angle in notch)
    #<_NotchAngleTop>   = 45                    (upper angle in notch)
    
    (-- Fairing Curve Dimensions as offsets from end arc center)
    
    #<_EndFairR>    = [0.68 * #<_TagSizeY>]
    #<_CornerFairR> = [0.25 * #<_TagSizeY>]
    
    #<_PCRadius>    = [#<_EndFairR> - #<_CornerFairR>]
    #<_PCY>         = [[#<_TagSizeY> / 2] - #<_CornerFairR>]
    #<_PCTheta>     = ASIN [#<_PCY> / #<_PCRadius>]
    #<_PCX>         = [#<_PCRadius> * COS [#<_PCTheta>]]
    
    #<_P1Y>         = [#<_TagSizeY> / 2]                    (top / bottom endpoint)
    #<_P1X>         = #<_PCX>
    
    #<_P2X>         = [#<_EndFairR> * COS [#<_PCTheta>]]
    #<_P2Y>         = [#<_EndFairR> * SIN [#<_PCTheta>]]
    
    (-- Tooling)
    
    #<_TraverseZ>   = 1.0                       (safe clearance above workpiece)
    
    #<_DrillDia>    = 3.2                       (drill for hole and notch)
    #<_DrillNum>    = 1                         ( ... tool number)
    #<_DrillRadius> = [#<_DrillDia> / 2]
    #<_DrillFeed>   = 200                       (drill feed for holes)
    #<_DrillRPM>    = 3000
    
    #<_MillDia>     = 3.2                       (mill for outline)
    #<_MillNum>     = 1                         ( ... tool number)
    #<_MillRadius> = [#<_MillDia> / 2]
    #<_MillFeed>    = 150                       (tool feed for outlines)
    #<_MillRPM>     = 5000
    
    #<_TextDia>     = 0.1                       (engraving tool)
    #<_TextNum>     = 1
    #<_TextFeed>    = 600                       (tool feed for engraving)
    #<_TextRPM>     = 10000
    
    (-- Useful calculated values)
    
    #<_TagRightX>   = #<_HoleOffsetX>           (extreme limits of tag in X)
    #<_TagLeftX>    = [#<_TagRightX> - #<_TagSizeX>]
    
    #<_EndFairRtX>  = [#<_TagRightX> - #<_EndFairR>]
    #<_EndFairLfX>  = [#<_TagLeftX> + #<_EndFairR>]
    
    #<_NotchCtrX>   = [#<_TagLeftX> + #<_NotchSizeX> - #<_DrillRadius>]
    
    (--------------------)
    (--------------------)
    ( Initialize first tool length at probe switch)
    (    Assumes G59.3 is still in machine units, returns in G54)
    ( ** Must set these constants to match G20 / G21 condition!)
    
    #<_Probe_Speed>     = 400            (set for something sensible in mm or inch)
    #<_Probe_Retract>   =   1            (ditto)
    
    O<Probe_Tool> SUB
    
    G49                     (clear tool length compensation)
    G30                     (move above probe switch)
    G59.3                   (coord system 9)
    
    G38.2 Z0 F#<_Probe_Speed>           (trip switch on the way down)
    
    G0 Z[#5063 + #<_Probe_Retract>]     (back off the switch)
    
    G38.2 Z0 F[#<_Probe_Speed> / 10]    (trip switch slowly)
    
    #<_ToolZ> = #5063                    (save new tool length)
    
    G43.1 Z[#<_ToolZ> - #<_ToolRefZ>]    (set new length)
    
    G54                     (coord system 0)
    G30                     (return to safe level)
    
    O<Probe_Tool> ENDSUB
    
    (-------------------)
    (-- Initialize first tool length at probe switch)
    
    O<Probe_Init> SUB
    
    #<_ToolRefZ> = 0.0      (set up for first call)
    
    O<Probe_Tool> CALL
    
    #<_ToolRefZ> = #5063    (save trip point)
    
    G43.1 Z0                (tool entered at Z=0, so set it there)
    
    O<Probe_Init> ENDSUB
    
    (--------------------)
    (Start machining)
    
    G40 G49 G54 G80 G90 G94 G97 G98     (reset many things)
    
    G21                                 (metric!)
    
    (msg,Verify G30.1 position in G54 above tool change switch)
    M0
    (msg,Verify XYZ=0 touched off at left front tag hole center on surface)
    M0
    
    O<Probe_Init> CALL
    T0 M6                           (clear the probe tool)
    
    (-- Engrave Text)
    
    O<DoText> IF [#<_DoText>]
    
    (msg,Insert engraving tool)
    T#<_TextNum> M6         (load engraving tool)
    O<Probe_Tool> CALL
    
    F#<_TextFeed>
    S#<_TextRPM>
    
    (debug,Set spindle to #<_TextRPM>)
    M0
    
    G0 X0 Y0                (get safely to first tag)
    G0 Z#<_TraverseZ>       (to working level)
    
    G10 L20 P2 X0 Y0 Z#<_TraverseZ>         (set G55 origin to 0,0 at this point)
    G55                                     (activate G55 coordinates)
    
    O3000 REPEAT [#<_NumTagsX>]
    
    O3100 REPEAT [#<_NumTagsY>]
    
    O<dogtagtext> CALL
    
    G0 X0 Y0
    G10 L20 P2 Y[0 - #<_TagSpaceY>]         (set Y orgin relative to next tag in +Y direction)
    
    O3100 ENDREPEAT
    
    G10 L20 P2 X[0 - #<_TagSpaceX>] Y[[#<_NumTagsY> - 1] * #<_TagSpaceY>] (next to +X, Y to front)
    
    O3000 ENDREPEAT
    
    G54                                     (bail out of G55 coordinates)
    
    (-- Drill holes)
    
    O<DoDrill> IF [#<_DoDrill>]
    
    T0 M6
    (msg,Insert drill)
    T#<_DrillNum> M6
    O<Probe_Tool> CALL
    
    F#<_DrillFeed>
    S#<_DrillRPM>
    
    #<_DrillZ> = [0 - #<_TagSizeZ> - #<_DrillRadius>]
    
    (debug,Set spindle to #<_DrillRPM>)
    M0
    
    G0 X0 Y0                (get safely to first tag)
    G0 Z#<_TraverseZ>       (to working level)
    
    #<IndexX> = 0
    O1000 DO
    
    #<IndexY> = 0
    O1100 DO
    
    #<TagOriginX> = [#<IndexX> * #<_TagSpaceX>]
    #<TagOriginY> = [#<IndexY> * #<_TagSpaceY>]
    
    G81 X#<TagOriginX> Y#<TagOriginY> Z#<_DrillZ> R#<_TraverseZ>
    G81 X[#<TagOriginX> + #<_NotchCtrX>] Y[#<TagOriginY> + #<_NotchCtrY>] Z#<_DrillZ> R#<_TraverseZ>
    
    #<IndexY> = [#<IndexY> + 1]
    O1100 WHILE [#<IndexY> LT #<_NumTagsY>]
    
    #<IndexX> = [#<IndexX> + 1]
    O1000 WHILE [#<IndexX> LT #<_NumTagsX>]
    
    G30     (go home)
    
    O<DoDrill> ENDIF
    
    (-- Machine outlines)
    
    O<DoMill> IF [#<_DoMill>]
    
    T0 M6                   (eject drill)
    (msg,Insert end mill)
    T#<_MillNum> M6         (load mill)
    O<Probe_Tool> CALL
    
    F#<_MillFeed>
    S#<_MillRPM>
    
    (debug,Set spindle to #<_MillRPM>)
    M0
    
    G0 X0 Y0                (get safely to first tag)
    G0 Z#<_TraverseZ>       (to working level)
    
    G10 L20 P2 X0 Y0 Z#<_TraverseZ>         (set G55 origin to 0,0 at this point)
    G55                                     (activate G55 coordinates)
    
    O2000 REPEAT [#<_NumTagsX>]
    
    O2100 REPEAT [#<_NumTagsY>]
    
    G0 X[#<_NotchCtrX>] Y[#<_NotchCtrY>]     (get to center of notch hole)
    G0 Z[0 - #<_TagSizeZ>]                      (down to cutting level)
    
    G91                                         (relative coordinate for notch cutting)
    G1 X[0 - #<_NotchSizeX>] Y[0 -  #<_NotchSizeX> * TAN [#<_NotchAngleBot>]]
    G1 X[0 + #<_NotchSizeX>] Y[0 +  #<_NotchSizeX> * TAN [#<_NotchAngleBot>]]
    G1 X[0 - #<_NotchSizeX>] Y[0 +  #<_NotchSizeX> * TAN [#<_NotchAngleTop>]]
    G90                                         (back to abs coords)
    
    G42.1 D#<_MillDia>                          (cutter comp to right)
    G1 X[#<_TagLeftX>] Y0                       (comp entry move to tip of left endcap)
    
    G3 X[#<_EndFairLfX> - #<_P2X>] Y[0 - #<_P2Y>] I[#<_EndFairR>] J0    (left endcap front half)
    
    G3 X[#<_EndFairLfX> - #<_P1X>] Y[0 - #<_P1Y>] I[#<_P2X> - #<_PCX>] J[#<_P2Y> - #<_PCY>]
    
    G1 X[#<_EndFairRtX> + #<_P1X>]                                      (front edge)
    
    G3 X[#<_EndFairRtX> + #<_P2X>] Y[0 - #<_P2Y>] I0 J[#<_CornerFairR>]
    
    G3 X[#<_EndFairRtX> + #<_P2X>] Y[#<_P2Y>] I[0 - #<_P2X>] J[#<_P2Y>]    (right endcap)
    
    G3 X[#<_EndFairRtX> + #<_P1X>] Y[#<_P1Y>] I[#<_PCX> - #<_P2X>] J[#<_PCY> - #<_P2Y>]
    
    G1 X[#<_EndFairLfX> - #<_P1X>]                                      (rear edge)
    
    G3 X[#<_EndFairLfX> - #<_P2X>] Y[#<_P2Y>] I0 J[0 - #<_CornerFairR>]
    
    G3 X[#<_EndFairLfX> - #<_P2X>] Y[0 - #<_P2Y>] I[#<_P2X>] J[0 - #<_P2Y>]    (left endcap complete)
    
    G0 Z#<_TraverseZ>
    
    G40
    
    G0 X0 Y0
    G10 L20 P2 Y[0 - #<_TagSpaceY>]         (set Y orgin relative to next tag in +Y direction)
    
    O2100 ENDREPEAT
    
    G10 L20 P2 X[0 - #<_TagSpaceX>] Y[[#<_NumTagsY> - 1] * #<_TagSpaceY>] (next to +X, Y to front)
    
    O2000 ENDREPEAT
    
    G54                                     (bail out of G55 coordinates)
    
    G30         (go home)
    
    O<DoMill> ENDIF
    
    M2
    
    

    The doodles leading to the equations:

    Dog Tag Geometry Doodles
    Dog Tag Geometry Doodles

    We’ll see you there!

  • Sherline EMC2 CNC Mill: Configuration Files

    This is a stick in the ground for the current config files I’m using with EMC 2.4.5. Even the automagically generated files may have some tweakage, which is why I’m putting them here…

    [Update: this is for a Dell Dimension 4550 with a latency around 10 µs, occasional glitches to 20 µs, and a very rare burp to 80 µs. Worked fine, but those rare burps were disturbing.]

    Sherline.ini

    # Ed Nisley - KE4ZNU
    # Just don't 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 = Sherline.gif
    INTRO_TIME = 3
    PROGRAM_PREFIX = /mnt/bulkdata/
    #PROGRAM_PREFIX = /home/ed/
    #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 = 100000
    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.333
    DEFAULT_VELOCITY = 0.475
    #MAX_LINEAR_VELOCITY = 0.400
    MAX_LINEAR_VELOCITY = 0.500
    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_VELOCITY = 0.475
    #MAX_ACCELERATION = 1.5
    MAX_ACCELERATION = 5.0
    #STEPGEN_MAXACCEL = 1.7
    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_VELOCITY = 0.475
    #MAX_ACCELERATION = 1.5
    MAX_ACCELERATION = 5.0
    #STEPGEN_MAXACCEL = 1.7
    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_VELOCITY = 0.400
    #MAX_ACCELERATION = 1.0
    MAX_ACCELERATION = 3.0
    #STEPGEN_MAXACCEL = 1.2
    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
    

    Sherline.tbl

    ;common end mills
    T1 P1 Z1 D0.1225 ; 1/8
    T2 P2 Z1 D0.1535 ; 5/32
    T3 P3 Z1 D0.1870 ; 3/16
    T4 P4 Z1 D0.2500 ; 1/4
    T5 P5 Z1 D0.3122 ; 5/16
    T6 P6 Z1 D0.3755 ; 3/8 - 4 flute long
    T7 P7 Z1 D0.4374 ; 7/16
    T8 P8 Z1 D0.4720 ; 1/2
    ;random metric equivalents
    T20 P20 Z1 D0.09787 ; 2 mm
    ;number drills 1xx = xx
    T107 P107 Z1 D0.201 ;  7	 5.11	10-32 clear
    T109 P109 Z1 D0.196 ;  9	 4.98	10-32 clear
    T118 P118 Z1 D0.170 ; 18	 4.32	 8-32 clear
    T121 P121 Z1 D0.159 ; 21	 4.04	10-32 tap
    T127 P127 Z1 D0.144 ; 27	 3.66	 6-32 clear
    T129 P129 Z1 D0.136 ; 29	 3.45	 8-32 tap
    T136 P136 Z1 D0.107 ; 36	 2.72	 6-32 tap
    T132 P132 Z1 D0.116 ; 32	 2.95	 4-40 clear
    T143 P143 Z1 D0.089 ; 43	 2.26	 4-40 tap
    T141 P141 Z1 D0.096 ; 41	 2.44	 2-56 clear
    T146 P146 Z1 D0.081 ; 46	 2.06	 good for 2 mm pin
    T148 P148 Z1 D0.076 ; 48	 1.93	 1-72 clear
    T150 P150 Z1 D0.070 ; 50	 1.78	 2-56 tap 0-80 clear
    T152 P152 Z1 D0.064 ; 52	 1.63	 0-80 clear
    T153 P153 Z1 D0.060 ; 53	 1.52	 1-72 tap
    ;fraction drills 2xx = xx/64
    T203 P203 Z1 D0.047 ; 3/64	 1.2	 0-80 tap
    ;inch decimal drills for eagle drilling
    ; 1xxx = xxx/1000
    T1000 P1000 Z1 D0.000	; center drill
    T1024 P1024 Z1 D0.024
    T1025 P1025 Z1 D0.025
    T1032 P1032 Z1 D0.032
    T1039 P1039 Z1 D0.039
    T1040 P1040 Z1 D0.040
    T1045 P1045 Z1 D0.045
    T1047 P1047 Z1 D0.047
    T1052 P1052 Z1 D0.052
    T1067 P1067 Z1 D0.067
    T1125 P1125 Z1 D0.125
    T1140 P1140 Z1 D0.140
    T1150 P1150 Z1 D0.150
    

    custom.hal

    # Include your customized HAL commands here
    # This file will not be overwritten when you run stepconf again
    
    #--------------
    # Get buttons and joysticks from Logitech Dual Action gamepad
    
    loadusr -W hal_input -KA Dual
    
    #--------------
    # Home switches are all in parallel, active low
    
    net homeswitches <= parport.0.pin-10-in-not
    net homeswitches => axis.0.home-sw-in
    net homeswitches => axis.1.home-sw-in
    net homeswitches => axis.2.home-sw-in
    
    #--------------
    # Probe input is active low
    
    net probe-in <== parport.0.pin-15-in-not
    net probe-in ==> motion.probe-input
    

    custom_postgui.hal

    #-- empty
    

    Logitech_Gamepad.hal

    # HAL config file automatically generated by Eagle-CAD ULP:
    # [/mnt/bulkdata/Project Files/eagle/ulp/hal-write-array.ulp]
    # (C) Martin Schoeneck.de 2008
    # Mods Ed Nisley 2010
    # Path        [/mnt/bulkdata/Project Files/eagle/projects/EMC2 HAL Configuration/]
    # ProjectName [Logitech Gamepad]
    # File name   [/mnt/bulkdata/Project Files/eagle/projects/EMC2 HAL Configuration/Logitech_Gamepad.hal]
    # Created     [11:51:27 10-Nov-2010]
    
    ####################################################
    # Load realtime and userspace modules
    loadrt constant		count=16
    loadrt and2		count=17
    loadrt flipflop		count=4
    loadrt mux2		count=5
    loadrt mux4		count=1
    loadrt not		count=8
    loadrt or2		count=10
    loadrt scale		count=7
    loadrt timedelay		count=1
    loadrt toggle		count=1
    loadrt wcomp		count=6
    
    ####################################################
    # Hook functions into threads
    addf toggle.0		servo-thread
    addf wcomp.1		servo-thread
    addf wcomp.2		servo-thread
    addf wcomp.3		servo-thread
    addf and2.0		servo-thread
    addf and2.4		servo-thread
    addf and2.3		servo-thread
    addf and2.2		servo-thread
    addf and2.1		servo-thread
    addf constant.6		servo-thread
    addf constant.5		servo-thread
    addf constant.4		servo-thread
    addf constant.3		servo-thread
    addf constant.2		servo-thread
    addf constant.1		servo-thread
    addf constant.0		servo-thread
    addf constant.7		servo-thread
    addf constant.8		servo-thread
    addf scale.1		servo-thread
    addf scale.2		servo-thread
    addf scale.3		servo-thread
    addf mux4.0		servo-thread
    addf mux2.0		servo-thread
    addf scale.4		servo-thread
    addf scale.0		servo-thread
    addf wcomp.5		servo-thread
    addf wcomp.4		servo-thread
    addf wcomp.0		servo-thread
    addf flipflop.1		servo-thread
    addf flipflop.0		servo-thread
    addf and2.5		servo-thread
    addf and2.6		servo-thread
    addf and2.7		servo-thread
    addf and2.8		servo-thread
    addf flipflop.2		servo-thread
    addf flipflop.3		servo-thread
    addf or2.4		servo-thread
    addf or2.8		servo-thread
    addf or2.7		servo-thread
    addf or2.6		servo-thread
    addf or2.5		servo-thread
    addf or2.3		servo-thread
    addf or2.2		servo-thread
    addf or2.1		servo-thread
    addf or2.0		servo-thread
    addf not.1		servo-thread
    addf not.2		servo-thread
    addf not.3		servo-thread
    addf not.4		servo-thread
    addf not.5		servo-thread
    addf not.6		servo-thread
    addf not.7		servo-thread
    addf not.0		servo-thread
    addf constant.9		servo-thread
    addf mux2.1		servo-thread
    addf mux2.2		servo-thread
    addf mux2.3		servo-thread
    addf mux2.4		servo-thread
    addf constant.10		servo-thread
    addf constant.11		servo-thread
    addf scale.5		servo-thread
    addf scale.6		servo-thread
    addf constant.12		servo-thread
    addf constant.13		servo-thread
    addf timedelay.0		servo-thread
    addf constant.14		servo-thread
    addf constant.15		servo-thread
    addf and2.16		servo-thread
    addf and2.15		servo-thread
    addf and2.14		servo-thread
    addf and2.13		servo-thread
    addf and2.12		servo-thread
    addf and2.11		servo-thread
    addf and2.10		servo-thread
    addf and2.9		servo-thread
    addf or2.9		servo-thread
    
    ####################################################
    # Set parameters
    
    ####################################################
    # Set constants
    setp constant.0.value	+0.02
    setp constant.1.value	-0.02
    setp constant.2.value	60
    setp constant.3.value	1.00
    setp constant.4.value	0.10
    setp constant.5.value	0.50
    setp constant.6.value	0.10
    setp constant.7.value	+0.5
    setp constant.8.value	-0.5
    setp constant.9.value	0.0
    setp constant.10.value	[TRAJ]MAX_LINEAR_VELOCITY
    setp constant.11.value	[TRAJ]MAX_ANGULAR_VELOCITY
    setp constant.12.value	-1.0
    setp constant.13.value	0.1
    setp constant.14.value	0.020
    setp constant.15.value	0.000
    
    ####################################################
    # Connect Modules with nets
    net a-button-minus input.0.btn-trigger or2.2.in0 and2.15.in0
    net a-button-plus input.0.btn-thumb2 or2.2.in1 and2.16.in0
    net a-buttons-active or2.2.out or2.3.in0 or2.4.in1
    net a-disable not.7.out and2.5.in1
    net a-enable or2.4.in0 flipflop.3.out not.7.in mux2.4.sel
    net a-jog wcomp.2.in input.0.abs-z-position mux2.4.in1
    net a-knob-active not.2.out and2.7.in1
    net a-knob-inactive wcomp.2.out not.2.in and2.6.in1
    net a-select and2.8.in0 and2.7.out
    net a-set flipflop.3.set and2.8.out
    net angular_motion or2.4.out mux2.0.sel
    net any-buttons-active mux4.0.sel0 or2.8.out
    net az-buttons-active or2.3.out or2.8.in1 or2.9.in0
    net az-reset flipflop.2.reset and2.6.out flipflop.3.reset
    net button-crawl scale.4.out mux4.0.in3
    net button-fast scale.2.out mux4.0.in1 scale.4.in
    net jog-crawl toggle.0.out mux4.0.sel1
    net jog-speed halui.jog-speed mux4.0.out
    net knob-crawl mux4.0.in2 scale.3.out
    net knob-fast mux4.0.in0 scale.1.out scale.3.in
    net n_1 constant.10.out mux2.0.in0
    net n_2 and2.0.in0 input.0.btn-top2
    net n_3 and2.0.in1 input.0.btn-base
    net n_4 and2.0.out halui.abort
    net n_5 halui.mode.manual input.0.btn-base3
    net n_6 wcomp.0.max wcomp.1.max wcomp.2.max wcomp.3.max constant.0.out
    net n_7 halui.program.resume input.0.btn-base4
    net n_8 wcomp.0.min wcomp.1.min wcomp.2.min wcomp.3.min constant.1.out
    net n_9 mux2.0.in1 constant.11.out
    net n_10 constant.12.out scale.5.gain scale.6.gain
    net n_11 input.0.btn-base5 or2.0.in0
    net n_12 input.0.btn-base6 or2.0.in1
    net n_13 constant.9.out mux2.1.in0 mux2.2.in0 mux2.3.in0 mux2.4.in0
    net n_14 mux2.1.out halui.jog.0.analog
    net n_15 toggle.0.in or2.0.out
    net n_16 constant.2.out scale.0.gain
    net n_17 constant.5.out scale.1.gain
    net n_18 constant.3.out scale.2.gain
    net n_19 constant.4.out scale.3.gain
    net n_20 scale.4.gain constant.6.out
    net n_21 halui.jog.1.analog mux2.2.out
    net n_22 mux2.2.in1 scale.5.out
    net n_23 scale.6.out mux2.3.in1
    net n_24 constant.13.out halui.jog-deadband
    net n_25 wcomp.4.max constant.7.out wcomp.5.max
    net n_26 constant.8.out wcomp.4.min wcomp.5.min
    net n_27 mux2.3.out halui.jog.2.analog
    net n_28 halui.jog.3.analog mux2.4.out
    net n_29 timedelay.0.out and2.9.in1 and2.10.in1 and2.12.in1 and2.11.in1 and2.13.in1 and2.14.in1 and2.16.in1 and2.15.in1
    net n_30 and2.9.out halui.jog.0.minus
    net n_31 or2.9.out timedelay.0.in
    net n_32 constant.14.out timedelay.0.on-delay
    net n_33 constant.15.out timedelay.0.off-delay
    net n_34 and2.10.out halui.jog.0.plus
    net n_35 and2.11.out halui.jog.1.minus
    net n_36 halui.jog.1.plus and2.12.out
    net n_37 and2.13.out halui.jog.2.minus
    net n_38 and2.14.out halui.jog.2.plus
    net n_39 and2.15.out halui.jog.3.minus
    net n_40 and2.16.out halui.jog.3.plus
    net vel-per-minute scale.0.out scale.1.in scale.2.in
    net vel-per-second mux2.0.out scale.0.in
    net x-buttons-active or2.7.in0 or2.5.out
    net x-disable not.4.out and2.4.in1
    net x-enable not.4.in flipflop.0.out mux2.1.sel
    net x-hat-jog wcomp.4.in input.0.abs-hat0x-position
    net x-hat-minus wcomp.4.under or2.5.in1 and2.9.in0
    net x-hat-plus or2.5.in0 wcomp.4.over and2.10.in0
    net x-jog wcomp.0.in input.0.abs-x-position mux2.1.in1
    net x-knob-active not.0.out and2.1.in0
    net x-knob-inactive wcomp.0.out not.0.in and2.2.in0 and2.3.in0
    net x-set and2.1.out flipflop.0.set
    net xy-buttons-active or2.7.out or2.8.in0 or2.9.in1
    net xy-reset flipflop.0.reset and2.2.out flipflop.1.reset
    net y-buttons-active or2.6.out or2.7.in1
    net y-disable not.5.out and2.1.in1
    net y-enable flipflop.1.out not.5.in mux2.2.sel
    net y-hat-jog input.0.abs-hat0y-position wcomp.5.in
    net y-hat-minus wcomp.5.under or2.6.in1 and2.12.in0
    net y-hat-plus or2.6.in0 wcomp.5.over and2.11.in0
    net y-jog wcomp.1.in input.0.abs-y-position scale.5.in
    net y-knob-active not.1.out and2.3.in1
    net y-knob-inactive not.1.in wcomp.1.out and2.2.in1
    net y-select and2.4.in0 and2.3.out
    net y-set flipflop.1.set and2.4.out
    net z-button-minus input.0.btn-thumb or2.1.in0 and2.13.in0
    net z-button-plus or2.1.in1 input.0.btn-top and2.14.in0
    net z-buttons-active or2.1.out or2.3.in1
    net z-disable not.6.out and2.8.in1
    net z-enable not.6.in flipflop.2.out mux2.3.sel
    net z-jog wcomp.3.in input.0.abs-rz-position scale.6.in
    net z-knob-active not.3.out and2.5.in0
    net z-knob-inactive not.3.in wcomp.3.out and2.7.in0 and2.6.in0
    net z-set and2.5.out flipflop.2.set
    

    Sherline.hal

    # 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=0xecd8
    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 1
    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 1
    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 1
    net adir => parport.0.pin-08-out
    net astep => parport.0.pin-09-out
    setp parport.0.pin-09-out-reset 1
    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 0
    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 0
    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 0
    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 0
    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