Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.
Epoxy a snippet of brass tubing from the Bottomless Bag o’ Cutoffs into the hole:
Ersatz aluminum heatsink – tubing trial fit
Recycle the old wire and PET loom, solder to another fake Neopixel, blob epoxy inside to anchor everything, and press it into place:
Ersatz aluminum heatsink – epoxying LED
Cutting the failed LED & plastic heatsink off the wire left it a bit too short for that tall bulb, but some rummaging in the heap produced a 100 W incandescent floodlight with a nicely pebbled lens:
Reflector floodlight – overview
A thin ring of clear epoxy secures the ersatz heatsink to the floodlight:
Reflector floodlight – finned LED holder
This time, I paid more attention to centering it atop the General Electric logo ring in the middle of the lens, which you can just barely see around the perimeter of the aluminum fin. By pure raw good fortune, the cable ended up pointed in the general direction of the socket’s pull-chain ferrule; you can’t unscrew the bulb without tediously unsoldering the wires from connector atop the knockoff Pro Mini inside the base and squeezing them back out through the ferrule.
With the firmware set for a single fake Neopixel on pin A3 and a 75 ms update rate, the floodlight bowl fills with color:
Reflector floodlight – purple phase
It puts a colored ring on the ceiling and lights the whole room far more than you’d expect from 200 mW of RGB LEDs.
The QC post and tool holders have very nice machining and surface finish; they evidently come from an entirely different production line than the lathe components. I can definitely get used to using carbide inserts, although I ordered some HSS inserts for interrupted cuts.
The HSS cutoff tool does what you’d expect:
LMS Mini-lathe – first cut – drilled and slotted
The holes in the end came from short (“screw machine”) drill bits I got for the Sherline’s painfully limited Z axis travel. Even so, chucking one in the 1/2 inch capacity LMS drill chuck shows why a 16 inch bed isn’t excessive:
LMS Mini-lathe – drill chuck vs bed length
The 6 inch = 150 mm scale on the bed (to the right of the tailstock) extends to the limit of tailstock travel, so you could have another half foot of stock sticking out of the 3 jaw chuck. A collet in the spindle would give you another two inches, but it’s snug in there.
On the other paw, this is a little lathe intended to make little things. It’ll do fine…
Having that knockoff Neopixel fail from overheating prompted me to measure what was going on. Because the LEDs sink most of their heat into the package leads, the back of the LED strip should be the hottest part of the package and the Mood Light’s central pillar should be pretty nearly isothermal. Despite that, I figured I should measure the temperature closer to the back of the strip, sooo I drilled a hole for the thermocouple…
Clamp the whole Mood Light to the Sherline’s tooling plate with the pillar sides mostly square to the axes and line up the spindle 2 mm behind the LED strip:
Mood Light – aligning thermocouple hole
The two clamp pads are CD chunks, under just enough pressure to anchor the Mood Light.
Screw the cap in place (to match-drill both holes at once) and drill a 2 mm (#46, close enough) hole down past the top LED:
Mood Light – drilling thermocouple hole
I tucked the Mood Light into a box to ward off breezes, jammed one thermocouple into the new hole, let another float over the top platter, then forced the Neopixels to display constant grayscale PWM values (R=G=B) while recording the LED and air temperatures every five minutes:
Hard Drive Mood Light – temp vs power data
That was easier and faster than screwing around with automated data collection. The data has some glaring gaps where I went off to do other things during the day.
I turned those numbers into a graph, printed it out, puzzled over it for a bit, then annotated it with useful numbers:
Hard Drive Mood Light – temp vs power data – graph
That first little blip over on the left comes from a minute or two at PWM 32; the cooling time constant works out to be a bit under 10 minutes. The warming time constant looks to be somewhat longer, but not by much.
Eyeballing the endpoint temperatures for each PWM value, feeding in the current measurements, and creating a small table:
VCC
5
V
Current
0.057
A
Package
0.285
W
Total
3.42
W
PWM
Duty
Nom Power
Failed LEDs
Net Power
°C Rise
0
0.00
0.00
0
0.00
0
32
0.13
0.43
0
0.43
6
64
0.25
0.86
0
0.86
12
85
0.33
1.14
1
1.04
16
128
0.50
1.71
1
1.62
24
192
0.75
2.57
1
2.47
35
255
1.00
3.41
4
3.03
42
The same blue LED that failed earlier dropped out again, plus another package (on a different strip) went completely dark shortly after I clobbered the LEDs with full power at PWM 255. The Net Power column deducts the power not used by the failed LEDs, under the reasonable assumption that the total heating depends on the number of active LEDs.
All the failed LEDs worked fine when they cooled to room temperature, so, whatever the failure mode might be, it’s not permanent. The skimpy WS2812B datasheet says bupkis about a protective thermal shutdown circuit, although it specs an 80 °C maximum operating junction temperature. I’ll stipulate a 20 °C temperature difference from junction to thermocouple at PWM 255, but that doesn’t explain the first blue LED failure at PWM 85.
Methinks these knockoffs will be much happier operating in the mid-30s.
Turning the last two columns of that table into a graph (minus the PWM 0 line to let the intercept float around) looks like I’m faking it:
Hard Drive Mood Light – Temperature vs Power
The Y intercept is off by less than 1 °C, which seems pretty good under the circumstances. The kink at PWM 85 shows that I probably didn’t allow enough time for the temperature to stabilize after the blue LED failed.
So, in round numbers, the thermal coefficient for a dozen knockoff Neopixels on a plastic pillar inside a stack of hard drive platters works out to 14 °C/W.
The raised sine waves in the Mood Light produce a long-term average PWM half of their maximum PWM. They’ve been perfectly happy with MaxPWM = 64 pushing them barely 6 °C over ambient, so they should continue to work fine at PWM 128 for a 12 °C rise… except, perhaps, during the hottest of mid-summer days.
Obviously, I should jam a thermistor inside the column and have the Arduino wrap a feedback loop around the column temperature…
Some rummaging produced a tiny DPDT switch that actually fit the holes intended for a pin header on the recently arrived Ham It Up board, at least after I amputated 2/3 of the poor thing’s legs:
Ham-It-Up – noise source switch – B
The new SMA noise output jack sits in the front left, with the white “noise on” LED just left of the switch:
Ham-It-Up – noise source switch – A
There’s no way to measure these things accurately, at least as far as I can tell, but the holes came out pretty close to where they should be. The new SMA connector lined up horizontally with the existing IF output jack and vertically with the measured / rounded-to-the-nearest-millimeter on-center distance:
Ham It Up – noise SMA drilling
The Enable switch doesn’t quite line up with the LED, so the holes will always look like I screwed up:
Ham-It-Up – noise source switch – case holes
That’s OK, nobody will ever notice.
Now, to stack up enough adapters to get from the SMA on the Ham It Up board to the N connector on the spectrum analyzer …
Although Mary’s name in the base of the Clover Mini Iron holder was readable in person, I wondered what filling the characters with epoxy would do. A bit of tinkering produced a name plate:
Text Block – solid model
Which is more readable in person, but magenta PETG renders it basically unreadable here:
Text Block – unfilled
The intent of this was not to produce a lovely name block, but to see what various epoxy fills and techniques produced. Think of this as the one you must build to throw away…
I tediously filled the first line with straight JB Weld epoxy, deliberately ruining the least functional of my 1 ml syringes to ease a strand of epoxy into each letter, then poking the goo into place with a pointed rod:
Text Block – plain epoxy fill
That was way tedious.
Having recently replaced the cartridge in our trusty HP Laserjet 1200, I had no qualms about step-drilling the “empty” cartridge to get the toner. For future reference, here’s where you drill into a 7115X cartridge:
HP 7115X Toner Cartridge – holes in waste and supply compartments
I probably used too much toner, but one heaping pile on that wooden stick didn’t seem like a lot at the time:
Text Block – toner black epoxy
This turned the epoxy rather thick and pasty; it didn’t ease into the letters very well at all. After the usual day, it cured into a slightly rubbery solid, quite unlike the usual rock-solid epoxy blob.
Some rummaging in the Basement Laboratory Warehouse Wing turned up two containers of aluminum powder from an Etch-a-Sketch; I mixed some into another batch of epoxy, to very little effect. With both blends, I just squished the epoxy into the letters and didn’t worry too much about slobbering any over the surface of the block.
To even off the top surface, I affixed the block to the Sherline’s tooling plate with tapeless sticky (basically double-sided tape without the tape):
Text Block – milling setup
Manually traversing the surface (3 k rpm, 24 inch/min) and stepping downward about 0.1 mm per pass gradually crisped up the letters. I expected the excess epoxy to vanish after going 0.1 mm or so into the top layer, but it actually required removing the entire 0.25 mm Hilbert-curve-filled surface layer to get rid of the epoxy that soaked into / through the tiny gaps. This is 0.4 mm down from the first pass, maybe 0.1 mm into the plastic:
Text Block – milled 0.4 mm
With the top layer gone, it looked rather gnarly, so I applied a sanding block that didn’t do much at all: smoother, still gnarly. Spreading maybe 0.3 ml of IPS 4 solvent adhesive over the sanded surface smoothed it a bit:
Text Block – sanded and leveled with IPS 4
Perhaps a topcoat of clear epoxy, along the lines of XTC-3D, would produce better results.
The small black dots in the top line are holes from bubbles in the epoxy. The missing section of the M started out as a bubble (just visible at 0.4 mm) and gradually enlarged as pieces tore out of the recess. There’s another bubble breaking the right stroke of the “y”.
The small dots in the “ley” are plastic spheres that carried the aluminum powder in the Etch-a-Sketch; they’re cross-sectioned and perfectly flat. The epoxy color is marginally lighter than the top line, but not enough to notice.
Backlit on a window, nearly all of the ugly fades away:
Text Block – backlit
It’s definitely not presentation quality, that’s for sure, and I won’t attempt to fill the Mini Iron holder…
The OpenSCAD source code, which can also produce the soldering iron holder:
// Clover MCI-900 Mini Iron holder
// Ed Nisley KE4ZNU - August 2015
Layout = "Text"; // Iron Holder Show Text
//- Extrusion parameters - must match reality!
ThreadThick = 0.25;
ThreadWidth = 0.40;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
Protrusion = 0.1;
HoleWindage = 0.2;
inch = 25.4;
Tap10_32 = 0.159 * inch;
Clear10_32 = 0.190 * inch;
Head10_32 = 0.373 * inch;
Head10_32Thick = 0.110 * inch;
Nut10_32Dia = 0.433 * inch;
Nut10_32Thick = 0.130 * inch;
Washer10_32OD = 0.381 * inch;
Washer10_32ID = 0.204 * inch;
//------
// Dimensions
CornerRadius = 4.0;
CenterHeight = 25; // center at cord inlet on body
BodyLength = 110; // cord inlet to body curve at front flange
Incline = 10; // central angle slope
FrontOD = 29;
FrontBlock = [20,1.5*FrontOD + 2*CornerRadius,FrontOD/2 + CenterHeight + BodyLength*sin(Incline)];
CordOD = 10;
CordLen = 10;
RearOD = 22;
RearBlock = [15 + CordLen,1.5*RearOD + 2*CornerRadius,RearOD/2 + CenterHeight];
PlateWidth = 2*FrontBlock[1];
TextDepth = 4*ThreadThick;
ScrewOC = BodyLength - FrontBlock[0]/2;
ScrewDepth = CenterHeight - FrontOD/2 - 5;
echo(str("Screw OC: ",ScrewOC));
BuildSize = [200,250,200]; // largest possible thing
module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes
Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
FixDia = Dia / cos(180/Sides);
cylinder(r=(FixDia + HoleWindage)/2,
h=Height,
$fn=Sides);
}
// Trim bottom from child object
module TrimBottom(BlockSize=BuildSize,Slice=CornerRadius) {
intersection() {
translate([0,0,BlockSize[2]/2])
cube(BlockSize,center=true);
translate([0,0,-Slice])
children();
}
}
// Build a rounded block-like thing
module RoundBlock(Size=[20,25,30],Radius=CornerRadius,Center=false) {
HS = Size/2 - [Radius,Radius,Radius];
translate([0,0,Center ? 0 : (HS[2] + Radius)])
hull() {
for (i=[-1,1], j=[-1,1], k=[-1,1]) {
translate([i*HS[0],j*HS[1],k*HS[2]])
sphere(r=Radius,$fn=4*4);
}
}
}
// Create a channel to hold something
// This will eventually be subtracted from a block
// The offsets are specialized for this application...
module Channel(Dia,Length) {
rotate([0,90,0])
linear_extrude(height=Length)
rotate(90)
hull() {
for (i=[-1,1])
translate([i*Dia,2*Dia])
circle(d=Dia/8);
circle(d=Dia,$fn=8*4);
}
}
// Iron-shaped series of channels to be removed from blocks
module IronCutout() {
union() {
translate([-2*CordLen,0,0])
Channel(CordOD,2*CordLen + Protrusion);
Channel(RearOD,RearBlock[0] + Protrusion);
translate([BodyLength - FrontBlock[0]/2 - FrontBlock[0],0,0])
Channel(FrontOD,2*FrontBlock[0]);
}
}
module TextBlock() {
translate([2,10,0])
linear_extrude(height=TextDepth + Protrusion,convexity=2) // rendering glitches for convexity > 1
// text("Mary",font="Ubuntu:style=Bold Italic",halign="center",valign="center");
text("Mary",font="Junicode:style=Bold Italic",halign="center",valign="center",size=20,spacing=1.05);
translate([2,-15,0])
linear_extrude(height=TextDepth + Protrusion,convexity=2)
text("Nisley",font="Junicode:style=Bold Italic",halign="center",valign="center",size=20,spacing=1.05);
}
//- Build it
if (Layout == "Iron")
IronCutout();
if (Layout == "Holder" || Layout == "Show")
difference() {
union() {
translate([(BodyLength + CordLen)/2 - CordLen,0,0])
TrimBottom()
RoundBlock(Size=[(CordLen + BodyLength),PlateWidth,CornerRadius]);
translate([(RearBlock[0]/2 - CordLen),0,0])
TrimBottom()
RoundBlock(Size=RearBlock);
translate([BodyLength - FrontBlock[0]/2,0,0]) {
TrimBottom()
RoundBlock(Size=FrontBlock);
}
}
translate([0,0,CenterHeight])
rotate([0,-Incline,0])
if (Layout == "Show")
# IronCutout();
else
IronCutout();
translate([0,0,-Protrusion])
PolyCyl(Tap10_32,ScrewDepth + Protrusion,6);
translate([ScrewOC,0,-Protrusion])
PolyCyl(Tap10_32,ScrewDepth + Protrusion,6);
translate([(RearBlock[0] - CordLen) + BodyLength/2 - FrontBlock[0],0,CornerRadius - TextDepth])
TextBlock();
}
if (Layout == "Text")
difference() {
translate([0,0,0])
TrimBottom(Slice=8*ThreadThick)
RoundBlock(Size=[80,65,8*ThreadThick],Radius=8*ThreadThick);
# translate([-2,2,8*ThreadThick - TextDepth])
TextBlock();
}
Thinwall open boxes – side detail – 4.98 4.85 measured
Alas, the shutter failed after that image, leaving me with pictures untaken and naught to take them with.
The least-awful alternative seems to be gimmicking up an adapter for a small USB camera from the usual eBay source:
Fashion USB video – case vs camera
The camera’s 640×480 VGA resolution is marginally Good Enough for the purpose, as I can zoom the microscope to completely fill all those pixels. The optics aren’t up to the standard set by the microscope, but we can cope with that for a while.
A bit of doodling & OpenSCAD tinkering produced a suitable adapter:
USB Camera Microscope Mount – solid model
To which Slic3r applied the usual finishing touches:
USB Camera Microscope Mount – Slic3r preview
A bit of silicone tape holds the sloppy focusing thread in place:
USB Camera Microscope Mount – cap with camera
Those are 2-56 screws that will hold the cap onto the tube. I drilled out the clearance holes in the cap and tapped the holes in the eyepiece adapter by hand, grabbing the bits with a pin vise.
Focus the lens at infinity, which in this case meant an old DDJ cover poster on the far wall of the Basement Laboratory, and then it’ll be just as happy with the image coming out of the eyepiece as a human eyeball would be.
I put a few snippets of black electrical tape atop the PCB locating tabs before screwing the tube in place. The tube ID is 1 mm smaller than the PCB OD, in order to hold the PCB perpendicular to the optical axis and clamp it firmly in place. Come to find out that the optical axis of the lens isn’t perfectly perpendicular to the PCB, but it’s close enough for my simple needs.
And then it fits just like you’d expect:
USB Camera Microscope Mount – on eyepiece
Actually, that’s the second version. The distance from the camera lens (equivalently: the PCB below the optical block, which I used as the datum plane) to the eyepiece is a critical dimension that determines whether the image fills the entrance pupil. I guesstimated the first version by hand-holding the camera and measuring with a caliper, tried it out, then iteratively whacked 2 mm off the tube until the image lit up properly:
USB Camera Microscope Mount – adjusting tube length
Minus 4 mm made it slightly too short, but then I could measure the correct position, tweak that dimension in the code, and get another adapter, just like the first one (plus a few other minor changes), except that it worked:
USB Camera Microscope Mount – first light
That’s a screen capture from VLC, which plays from /dev/video0 perfectly. Some manual exposure & color balance adjustment may be in order, but it’s pretty good for First Light.
It turns out that removing the eyepiece and holding the bare sensor over the opening also works fine. The real image from the objective fills much more area than the camera’s tiny sensor: the video image covers about one digit in that picture, but gimmicking up a bare-sensor adapter might be useful.
The Squidwrench Power Wheels Racer needed a mounting bracket for its DC motor, so Matt handed me a precut steel slab and some drawings. I did a manual layout to get a feel for the sizes:
Motor Mount – dye layout
Yes, it’s slightly rhomboid & irregular on the sides; it’ll be welded to a U-channel. The front edge is the straightest and I scribed a perpendicular datum line over on the right, from which to measure the motor center point.
But then, realizing I’d have to mill the central hole anyway, I did what I should have done from the beginning and lined it up on the Sherline:
Motor Mount – Sherline laser centering
With the part zeroed at the center, everything has polar coordinates. The bolt holes are #10 on a 50 mm BCD, which is G0 @25^[45+90*i]. Rather than writing & debugging a program, I did it all by feeding manual instructions into the interpreter; the i gets typed as 0, 1, 2, and 3 by clicking on a previous command, backspacing, and retyping, which is both faster and easier than it sounds. The holes are drill cycles: G81 Z-7 R1 F30
This being steel on a Sherline, the rule of thumb that says you can drill at 100x the drill diameter (in inch/min or mm/min, as appropriate) at 3000 RPM gets derated by at least factor of 10. I settled on 30 mm/min for a #10 drill (0.194 inch = 4.9 mm → 500 mm/min = hogwash) after trying the first hole at 50 mm/min:
Motor Mount – bolt holes
The least horrible way to cut out the hole for the motor mounting boss involved chain drilling to excavate the most steel with the least effort. These center drill points are at G0 @14 ^[15*i] with i in [0..23]:
Motor Mount – chain center drilling
I drilled every even hole #27, then every odd hole #28, both at 50 mm/min, to get a thin web:
Motor Mount – chain drilled
Then helix-mill downward with a 1/8 inch end mill at 1 mm per pass:
Motor Mount – helix milling
That started at 14 mm from the origin to match the hole circle: G3 I-14 F100 Z-1
Then I switched to a 3/8 inch = 9.5 mm end mill to bring the hole up to size, ending with G3 I-12.75 F300
Motor Mount – center hole milled
A trial fit showed the hole was slightly off-round, probably due to a few mils of backlash in both axes, and slightly too small, because that’s how I wanted it. Flipped back-to-front, reclamped, recentered, ran the cutter around at 12.75 mm to clear the ovalness, then crept out to 12.8 mm, and it was all good:
Motor Mount – test fit
That’s an easy fit with maybe 0.1 mm = 4 mil radial play around the boss. Better than that, I cannot do.
Lacquer thinner stripped the layout dye and it’s ready for welding:
Motor Mount – with motor
Reminders for next time…
The drill feed on a rigid machine with plenty of spindle power is 100 x (drill dia) @ 3000 RPM. On the Sherline, in steel, 10 x dia is optimistic. Aluminum feeds run higher, but don’t get stupid.
Re-centering to the accuracy required for this job is a matter of noting the coordinates where the cutter kisses the perimeter across a diameter along each axis, adding the coordinates, dividing by two, moving to that position, and zeroing the origin. Do that in X, Y, X, and Y and it’s good enough. You could automate that with a touch probe, of course. Hand-turning the spindle with the cutter in place to feel it kiss the workpiece is fine, but use the same cutting edge on both sides of the diameter.
Figure the chain drill diameter thusly:
Pick a reasonable drill diameter; #10 is about as large as you want on a Sherline
Drill circle dia = final milled hole diameter – drill dia – 2 mm, round down to lower integer
# holes = π x DCD / drill dia, rounded down to lower integer
Hole angle = 360 / # holes
Hole radius = DCD / 2
Wisely is it written that a man with a CNC milling machine has many friends.