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

  • Stepper Motor Idle Current

    The motor driver box on my Sherline mill started out as a stock unit, but I’ve tweaked the circuitry to improve the analog performance. Those adventures formed the basis of my Above the Ground Plane columns in Circuit Cellar magazine columns for August & October 2004.

    Because the firmware for the PIC microcontrollers wasn’t available, I wrote a clean-room version so I could show how it all worked for the column. My code won’t run on a stock Sherline board, though, so it’s not a drop-in replacement for the stock firmware.

    One of the reasons I attacked the controller was to reduce the audible noise coming from the motors. That’s an inescapable part of chopped-current stepper motor drive circuitry, but the noise was modulated by all manner of things that shouldn’t have affected it; just touching the box shouldn’t make any difference at all. The fact that it did meant the circuit board had some, well, infelicitous layouts.

    Although the final result was much more stable, I decided to turn off each motor if it didn’t move for at least five seconds; that’s a simple firmware tweak when you write your own code. As a result, the shop was quiet when I wasn’t actively milling.

    Solar Measurements Circuit Board - Top Side
    Solar Measurements Circuit Board – Top Side

    Now, having a motor be completely turned off while milling is going on isn’t generally a good idea, because milling forces from the other axes can push the table against the leadscrew and, perhaps, turn the screw against the unresisting motor. I figured that on a Sherline mill, what with the sissy little cuts I take, that wouldn’t be a problem.

    And I was right for the better part of four years!

    A benefit of turning the driver circuitry off was that I could easily twist the knobs by hand to fine-tune the XYZ position during setup. That worked out really well.

    However, drilling the seemingly simple circuit board pattern you see here (for my February 2009 CC column) produced exactly the right collection of forces (while drilling? Huh?), vibration (maybe) and motor pauses (for sure) to introduce an absolutely repeatable positioning error that Went Away when I tweaked the firmware to keep the motors enabled at all times.

    I’ve since made another tweak that reduces the current to an idle level after five seconds. That both reduces the audible noise and drills the board correctly, so I’ll keep an eye on it for a while before declaring victory.

    The PCB has a few unused (in my code, anyway) chip-to-chip connections that I could employ to let them all decide when nobody’s moving. I think turning the motors off 20 seconds after the last axis stops moving should work Just fine; my G-code doesn’t wait around that long except for manual tool changes.

    Update: More on PCB drilling there.

  • Fairing Arcs

    In CNC machining, at least the kind I do on my Sherline CNC mill, you can’t mill around acute inside corners: a round milling bit doesn’t fit into a straight-sided angle. You must add a fairing arc that smoothly connects the two sides; the catch is that “smooth” means it’s tangent to the sides. And EMC2 is really, really fussy about smooth, to the point where you can’t just wing it with a calculator and type in the numbers.

    Fairing arc doodles
    Fairing arc doodles

    There are nice analytic geometry methods for finding the intersection of two line segments, then laying in the arc that connects them, but this example weighs in at over two pages of G-Code. Mostly, what I need is an arc that connects a vertical or horizontal edge to an angled edge, so some simplification is in order.

    Herewith, the quick-and-dirty…

    The cutter enters from the left side, moving horizontally to the right, and will depart along the line toward P1, which might be the next corner of the part. The two material edges meet at P0, the vertex of the angle. The fairing arc is tangent to the two edges at PA and PB, centered at PC, and with a radius R.

    We know the coordinates of P0 and P1 and the arc radius. That radius must be larger than the cutter radius, as you can’t tuck a fat cutter into a narrow corner.

    The problem is to find PA, PB, and PC, so that we can write the G-code commands that travel along the sides & the arc.

    The first step is finding Φ (Phi), the angle between the outgoing edge and the X axis:

    Φ = arctan Δy/Δx = arctan (P1y – P0y) / (P1x – P0x)

    I’m pretty sure if you use a 4-quadrant arctan, as shown in the doodle, all the angles will work out perfectly on either side of the axis, but it’s easy enough to fake the signs to get the right answer in any specific case. If you wanted a general solution, you’d have a two-page subroutine, right?

    You’ll need the complement of that angle, hereinafter known as Theta:

    Θ = 90 – Φ

    Find the distances between various points using good old trig and right triangles:

    • CBx = R · sin Φ
    • CBy = R · cos Φ
    • P0PBy = R · (1 – cos Φ)
    • P0PBx = P0PBy · tan Θ

    Then the coordinates fall out thusly:

    Plastic Spring with Faired Corners
    Plastic Spring with Faired Corners
    • PCy = P0y + R
    • PBy = PCy – CBy
    • PBx = P0x + P0PBx
    • PCx = PBx – CBx
    • PAx = PCx
    • PAy = P0y

    Remember, you do not figure all this out with your calculator and plug the numbers into the G-code, not if you have any sense. If you have just a few corners, write the commands directly, otherwise gimmick up a little subroutine. Earlier versions of EMC2 used numbered parameters (#100), but now that you can have named parameters (#<_Fairing_Radius>), what’s holding you back?

    For example:

    #<_CBy>	= [#<_Fairing_Radius> * COS [#<_Phi>]]	(Y distance PC to PB)

    If your edge doesn’t come in from the left, then manual 90 degree rotations apply.

    0: (x,y) -> (x,y)
    90: (x,y) -> (y,-x)
    180: (x,y) -> (-x,-y)
    270: (x,y) -> (-y,x)

    If you’re using a CAD program to lay out your parts, all this is largely irrelevant. I hammer out the G-code for the simple 2-1/2-D parts I make by hand, so rounding off a few corners comes in handy.

    Because the lines & arc define the material edge contour, you can mill on either side of it and use cutter radius compensation to make the answer come out right. Works like a champ!

    For what it’s worth, the arc is tangent at PA and PB, making the line from PC to the corner (a.k.a. vertex) P0 the bisector of angle Φ. That’s not directly useful here, but keep it in mind when you solve similar problems.

    Update: As of mid-January, the newest trunk version of EMC2 can automagically insert fillets when cutter comp is turned on. That’ll be in the stable version in a while, after which I’ll need this math only for decorative fillets. That’s fine with me!

  • Oscilloscope Screen Shots

    A long time ago I got an HP54602B oscilloscope with a serial port data link. HP provided a sample app that snarfed screenshots & data from the scope, but it wasn’t really ready for prime time and, besides, I vastly preferred to use OS/2 (!) and then Linux rather than Windows.

    Here’s my Kermit script to fetch screenshots. All the software comes more-or-less standard in Ubuntu Linux and (I presume) in most others. If you’re running Windows, you’re on your own.

    Scope Setup

    HP54602B Serial Setup Screenshot
    HP54602B Serial Setup Screenshot

    The oscilloscope’s HP Plotter setting spits out bog-standard HPGL commands in flat ASCII. I’ve always meant to investigate what HP Printer does, but …

    I wish the scope ran faster than 19200 b/s, but that speed works reliably over generic USB-to-serial converters (and the scope can’t feed data that fast, anyway). The other choice, back in the day, was HPIB / GPIB; I’d have had to buy three or four different adapters to suit all the PC data buses since then: ISA, EISA, VLB, PCI …

    Xon/Xoff flow control (a.k.a. handshaking) works better than hardware flow control, simply because the cable’s easier to build.

    The Factors setting adds a bunch of text to the end of the data stream that’s not useful, except for the fact that an HPGL LB instruction follows all of the useful data and gives the Kermit script something to look for. Otherwise, the only way to detect the end of the stream is to time out after a looong time.

    I haven’t the foggiest idea what Resolution does, but High seems appropriate.

    Hardware Notes

    The scope requires a Null Modem in front of a standard DB-25 to DB-9 cable. I’ve been meaning to rewire my standard cable to eliminate the Null Modem, but …

    Adding an LED breakout / monitoring adapter to the serial port loads the signals too much and can lead to puzzling errors. Maybe it’s just my adapter: YMMV.

    I’ve run the cable all the way across my basement lab with no problem. This is, after all, good old RS-232, not some high-falutin’ USB or Firewire interconnect.

    Taking the Shot

    Get a picture you like, poke the Print Screen button, then quick like a bunny run the script. The scope copies the current screen into an internal buffer, then sends out a torrent of HPGL commands. The script will capture the data and eventually spit out a PNG file.

    You may want to Stop the trace, rather than leave it running.

    In XY mode, the scope seems to have trouble copying the entire trace. I tap Auto Store twice, then Stop, then Print Screen. It’s fuzzier, but copies the whole thing.

    What Happens

    The script captures the incoming serial data into a log file, processes that text through the hp2xx program to get an Encapsulated Postscript EPS file, then runs that though convert to get a PNG file. The bank shot off EPS results in better-looking output, for reasons I don’t understand.

    The 240-second timeout value for the Input command seems long, but it takes a lot of plotter commands to define a four-trace plot. A too-short timeout chops off the tail end of the HPGL stream and prompts bizarre error messages from hp2xx.

    The parameters for hp2xx and convert came from protracted and tedious twiddling. The ‘scope image is 512 dots across and 300-some-ish vertically; the output mimics the not-quite-square graticule aspect ratio on the actual screen. If HP thinks it looks good, then it looks good to me.

    The active (bright) traces use Pen 2, which I’ve set to Blue (color 4). The graticule, annotations, and stored traces all use Pen 1, which appears as Black (color 1). Tweak -c 14 as you wish.

    The pen widths (set by -p 34) don’t actually seem to do very much, although I vaguely recall that using the default width of 1 makes the output entirely too faint.

    The PNG has a transparent background that turns white when you actually use it in a document; I suppose you could overlay it atop a background image if you wanted to get cute.

    When the dust settles and the smoke clears, you get PNG images like this. It’s an XY plot, so the blue section appears as a bright trace on the oscilloscope’s screen.

    BH curve for LC0263-A coil
    BH curve for LC0263-A coil

    Kermit Script

    #!/usr/bin/kermit +
    # Fetches screen shot from HP54602B oscilloscope
    # Presumes it's set up for plotter output...
    # Converts HPGL to PNG image

    set modem none
    set line /dev/ttyS0
    set speed 19200
    set flow xon/xoff
    set carrier-watch off

    # Make sure we have a param
    if not defined %1 ask %1 {File name? }

    set input echo off
    set input buffer-length 150000

    # Wait for PRINT button to send the plot
    echo Set HP54602B for HP Plotter, FACTORS ON, 19200, XON/XOFF
    echo Press PRINT SCREEN button on HP54602B…

    log session “%1.hgl”

    # Wait for end of data stream
    input 240 lb

    echo … got final lb command

    close session
    close

    echo Converting HPGL in
    echo — %1.hgl
    echo to PNG in
    echo — %1.png

    # without labels = no terminating lb info
    #run hp2xx -m png -a 1.762 -h 91 -c 14 “%1.hgl”
    #run mogrify -density 300 -resize 200% “%1.png”

    # with labels = terminating lb
    run hp2xx -q -m eps -r 270 -a 0.447 -d 300 -w 130 -c 14 -p 34 “%1.hgl”
    run convert -density 300 -resize 675×452+2+2 “%1.eps” “%1.png”

    echo Finished!

    exit 0