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.

Tag: Improvements

Making the world a better place, one piece at a time

  • Rounded Cable Clips

    This isn’t quite the smoothly rounded clip I had in mind:

    LED Cable Clip - rounded channel
    LED Cable Clip – rounded channel

    It seems somewhat better looking than the square design, though:

    LED Cable Clips
    LED Cable Clips

    I ran off a few of both styles to have some on hand:

    Cable clips - on platform
    Cable clips – on platform

    They’re in a bag until I install the new LED strips and needle light.

    The OpenSCAD source code:

    // LED Cable Clips
    // Ed Nisley - KE4ZNU - October 2014
    
    Layout = "Oval";			// Oval Square Build
    
    //- Extrusion parameters must match reality!
    
    ThreadThick = 0.20;
    ThreadWidth = 0.40;
    
    HoleWindage = 0.2;			// extra clearance
    
    Protrusion = 0.1;			// make holes end cleanly
    
    AlignPinOD = 1.70;			// assembly alignment pins: filament dia
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //----------------------
    // Dimensions
    
    Base = [12.0,12.0,IntegerMultiple(2.0,ThreadThick)];	// base over sticky square
    
    CableOD = 2.0;
    
    BendRadius = 3.0;
    
    Bollard = [BendRadius,(sqrt(2)*Base[0]/2 - CableOD - BendRadius),2*CableOD];
    B_BOT = 0;
    B_TOP = 1;
    B_LEN = 2;
    
    NumSides = (Shape == "Square") ? 5*4 : 6*3;
    
    //----------------------
    // Useful routines
    
    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);
    }
    
    module ShowPegGrid(Space = 10.0,Size = 1.0) {
    
      RangeX = floor(100 / Space);
      RangeY = floor(125 / Space);
    
    	for (x=[-RangeX:RangeX])
    	  for (y=[-RangeY:RangeY])
    		translate([x*Space,y*Space,Size/2])
    		  %cube(Size,center=true);
    
    }
    
    //-- Square clip with central bollard
    
    module SquareBollard() {
    
    	intersection() {
    		translate([0,0,(Base[2] + Bollard[B_LEN])/2])			// overall XYZ outline
    			cube(Base + [0,0,Bollard[2]],center=true);
    
    		union() {
    			translate([0,0,Base[2]/2])						// oversize mount base
    				scale([2,2,1])
    					cube(Base,center=true);
    
    			for (i=[-1,1] , j=[-1,1]) {						// corner bollards
    				translate([i*Base[0]/2,j*Base[1]/2,(Base[2] - Protrusion)])
    					rotate(180/NumSides)
    					cylinder(r=Bollard[B_BOT],h=(Bollard[B_LEN] + Protrusion),center=false,$fn=NumSides);
    
    			translate([0,0,(Base[2] - Protrusion)])			// center tapered bollard
    				cylinder(r1=Bollard[B_BOT],r2=Bollard[B_TOP],
    						 h=(Bollard[B_LEN] + Protrusion),
    						 center=false,$fn=NumSides);
    			}
    		}
    	}
    
    }
    
    //-- Oval clip with central passage
    
    module OvalPass() {
    
    	intersection() {
    		translate([0,0,(Base[2] + Bollard[B_LEN])/2])		// overall XYZ outline
    			cube(Base + [0,0,2*CableOD],center=true);
    
    		union() {
    			translate([0,0,Base[2]/2])						// oversize mount base
    				scale([2,2,1])
    					cube(Base,center=true);
    
    			for (j=[-1,1])									// bending ovals
    				translate([0,j*Base[1]/2,(Base[2] - Protrusion)])
    					resize([Base[0]/0.75,0,0])
    						cylinder(d1=0.75*(Base[1]-CableOD),d2=(Base[1]-CableOD)/cos(180/NumSides),
    								h=(Bollard[B_LEN] + Protrusion),
    								center=false,$fn=NumSides);
    		}
    	}
    /*
    #	translate([0,0,6])
    		rotate([0,90,0])
    			cylinder(d=CableOD,h=10,center=true,$fn=48);
    */
    }
    
    //----------------------
    // Build it
    
    ShowPegGrid();
    
    if (Layout == "Square")
    	SquareBollard();
    
    if (Layout == "Oval")
    	OvalPass();
    
  • DC-DC Boost Converter: Another QC FAIL

    Each LED emitter in the Kenmore 158 endcap light contains six chips in series:

    LED mount - lighting test
    LED mount – lighting test

    Even though the current has the usual exponential relationship to the terminal voltage, the slope at 200 mA (100 mA each, assuming they share & share alike) remains low enough that I (think I) can get away with just dialing in a voltage and leaving it at that; changes due to small temperature variations won’t cause meaningful differences in the current.

    That’s easier than building an adjustable current regulator, anyway.

    The heap disgorged two cheap DC-to-DC boost converters from halfway around the planet, with about the right specs:

    • 10 to 32 V DC in
    • 12 to 35 V out
    • 10 A
    • 150 W

    They couldn’t produce their rated output, but a pair of LEDs shouldn’t pose much of a challenge.

    So I wired one up to the bench supply, set it for 12 V, turned it on, and wham it maxed out the supply at 3 A with no load on the converter’s output.

    Huh.

    Adding a suitable load resistor brought the input current down, but the voltage adjustment trimpot didn’t have much effect and the bench supply would still wham hit 3 A with no provocation, so the load resistor didn’t actually make any difference. Eventually, I figured out that simply pressing my finger on the trimpot caused the output to vary wildly.

    Given that fairly broad hint, this became obvious:

    Boost Converter - trimpot pins
    Boost Converter – trimpot pins

    Evidently, I had used the other converter for the previous tests. Huh.

    With that trimpot pin soldered in place, the converter worked fine. Eyeballometrically speaking, the LEDs seem bright enough at 100 mA total (50 mA each) for my purposes, which happens at 18-ish V. Dissipating only 2 W won’t require nearly as much heatsink as they’re presently mounted on, although I should wait for warmer weather before concluding that they’re doing OK while crammed inside the end cap.

    Before declaring victory, I took a closer look at the board and found this mmm oversight:

    Boost Converter - masked 78L09 tab
    Boost Converter – masked 78L09 tab

    Notice the big pad under the 78L09 regulator, with six thermal vias to an expansive copper pour on the other side of the board, completely covered with red solder mask.

    Removing the regulator show the regulator’s footprint didn’t include the tab:

    Boost Converter - 78L09 footprint
    Boost Converter – 78L09 footprint

    Maybe they decided, after a careful analysis, that the regulator couldn’t possibly dissipate enough power to warrant the additional solder required for the entire thermal pad. Heck, pocket a fraction of a yuan on ten million boards and you’re livin’ large.

    Scraping the mask off, fluxing everything in sight, and soldering the regulator down probably won’t make any difference:

    Boost Converter - scraped and soldered
    Boost Converter – scraped and soldered

    Yes, The Bigger The Blob, The Better The Job strikes again. It does make me feel better and that’s all that counts.

  • OpenSCAD: Quantized Vertices

    Back when I started fiddling with 3D printed chain mail, the whole process from model to plastic worked wonderfully well. That continued with the larger sheets, but now, occasionally, the OpenSCAD model would produce weirdly sliced links. Depending on nothing repeatable, some links wouldn’t bridge correctly: the thread paths in the bottom layer across the gap would mysteriously stop just short of one pillar, return to the start, and leave an unsupported shelf that would, of course, fall into the gap.

    Shortly before Christmas, I managed to get a consistent failure that manifested differently: upon loading the STL file, Slic3r would quietly perform dozens of automatic corrections that (sometimes!) produced bizarrely distorted results. Feeding a failing model into Meshlab showed an irregular assortment of “self intersecting faces”, highlighted in red:

    Chain Mail Square Armor - open - 2x2 - Meshlab self-intersecting faces
    Chain Mail Square Armor – open – 2×2 – Meshlab self-intersecting faces

    Although all four outer links in that image come from the same OpenSCAD module with identical sizes, they don’t all exhibit the same problem in the (nominally identical) faces on each of their four corners. In fact, those faces come from the intersection of two square slabs, carefully sized and positioned to avoid creating coincident planes:

    Chain Mail Link - Outer shape
    Chain Mail Link – Outer shape

    The central opening comes from a similar, slightly smaller, intersected-squares shape, but all four interior corner faces in each link show that they’re self-intersecting.

    The STL looked fine in Meshlab, except for the highlit self-intersecting faces, so the geometry seemed OK.

    When Slic3r autocorrected the “problems”, it apparently removed one vertex on the bottom surface of each bar, deleted the triangles connected to that vertex, then repaired the mesh to produce a delightfully symmetric pattern:

    Chain Mail Square Armor - open - 2x2 - Slic3r corrections
    Chain Mail Square Armor – open – 2×2 – Slic3r corrections

    Although the links are resolutely symmetric, Slic3r seemed happy with the identical vertices at the other end of the bar.

    Unfortunately, the resulting G-Code won’t produce good links:

    Chain Mail Square Armor - open - 2x2 - first layer G-code visualization
    Chain Mail Square Armor – open – 2×2 – first layer G-code visualization

    So, shortly before Christmas, I filed an issue on OpenSCAD’s Github repository.

    The ensuing discussion showed that Meshlab flags faces as “self intersecting” when they have different vertices, even if their values are numerically equal, as well as vertices that differ by teeny amounts. Slic3r applies slightly different criteria to vertices & faces when it automagically corrects “problems” in the STL file, so that Meshlab may:

    • Highlight faces that don’t bother Slic3r
    • Apply the same highlight to faces that cause horrible problems

    I don’t profess to understand much of that and may have the details wrong, but, apparently, OpenSCAD formerly used quantized coordinates that ensured all vertices within a tiny volume would have the same numeric value. In particular, all three faces that meet at a common point would, in fact, have numerically equal coordinate values for that point. The STL file format consists of a list of separate triangles, each with three coordinates for each of the three axes, and (without quantization) it was entirely possible for each of the three triangles with a common point to have three very slightly different positions for that point.

    In theoretic terms, quantized coordinates cause horrible problems during geometric manipulation, because numeric values that aren’t exact can make repeated transformations come out wrong; running an object through a transformation and it’s inverse might not yield an object identical to the original one.

    In practical terms, it seems that slicers and STL repair algorithms can reach incorrect conclusions based on minute differences produced by floating-point operations and numeric-to-text conversions. Those differences depend on slight changes in position, rotation, and size, so doing anything to the model produces completely different results.

    That notwithstanding, the day after Christmas brought a new OpenSCAD version that uses quantized coordinates. A bit of rummaging in the source shows that the 3D grid (defined in src/grid.h) isn’t all that coarse:

    const double GRID_FINE   = 0.00000095367431640625;
    

    STL files don’t carry units, so that could be in either millimeters (the Slic3r / RepRap convention) or inches (Sketchup, but we won’t go there). It’s exactly 1/10242, in case you were wondering, which produces a 5% speedup in the geometry engine compared to the more human-readable 1/10002.

    With that commit in hand, all the chain mail links slice perfectly again.

    A very nice Christmas present, indeed!

    Thanks, Marius…

  • Improved Pilot InstaBoost Jumpstarter Clamps

    The Sienna now spends all its time sitting outdoors in an apartment parking lot and gets even less driving (hence, battery-charging) time than we used to give it. Fortunately, Santa being my kind of guy, our Larval Engineer received a Pilot InstaBoost jumpstarter, which is basically a 10 A·h / 40 W·h lithium battery with husky plug & socket connectors, a pair of 10 AWG wires, and big alligator clamps. The package claims a 400 A peak discharge rate, but the tiny inscription on the back of the case reports 200 A; either of those seems mmmm somewhat optimistic to me.

    The customer reviews suggest that the plastic battery clamp handles feature a crappy hinge joint which disintegrates under moderate stress on a cold winter night, firing the spring into the nearest snowbank and rendering the clamp completely useless. The joint consists of a plastic post on each side of the inner handle that protrudes into a hole in the outer handle:

    Battery Clamp - original joint
    Battery Clamp – original joint

    I assigned her some Mandatory Quality Shop Time to improve the joint. She found some brass tubing that fit the existing hole and cut two pieces to length:

    Battery Clamp - cutting brass tube
    Battery Clamp – cutting brass tube

    A 1 inch stainless screw was just barely long enough (that’s Loctite Red in the nut), but the end result certainly looks durable enough:

    Battery Clamp - improved joint
    Battery Clamp – improved joint

    It’s along the same lines as the improvement I applied to my old Park Tool MTB-7 Rescue Tool.

    Apart from that, the clamps look pretty good. There’s even a husky braid between the two jaw pads, ensuring at least one reasonably low resistance joint to the battery post:

    Battery Clamp - jaw strap
    Battery Clamp – jaw strap

    With a bit of luck, we’ll never know how well it works as a jumpstarter. She can use the USB port to keep her phone charged, which may provide enough motivation to keep the thing topped up and ready for use…

    [Update: two days after this post went live, someone found it by searching for:

    how to repair clamps pilot instaboost 400

    You have been warned!]

  • Kenmore 158: Recalibrated Optoisolator Drive

    Because the motor will draw more current during pulsed operation, the ET227 needs more base drive. The existing circuit topped out around 2.5 A, so I reduced the current sampling resistor by a bit:

    Optoisolator Driver
    Optoisolator Driver

    If you care about the exact current, you’d use a 1% resistor, but if you care about the current, you’ll be doing closed-loop feedback to compensate for the transistor gain variations. Compared to those, the resistor doesn’t matter.

    Running the MCP4725 DAC through its range produces a nice graph:

    Current Calibrate - DAC - 270k Hall 2.7k opto
    Current Calibrate – DAC – 270k Hall 2.7k opto

    The X axis comes from the Tek Hall-effect current probe, so the numbers don’t depend on the ferrite toroid & differential amp calibration. They do, of course, require a bit of eyeballometric calibration to extract the flat top from the waveform, as shown by this old waveform:

    Motor current - ADC sample timing
    Motor current – ADC sample timing

    Ya gotta start somewhere.

    The linear fit to those dots gives the DAC value required to produce the observed current, at least for these particular transistors at whatever temperature they’re at in a rather chilly Basement Laboratory.

    Of course, the observed current tops out at 1.2 A: the motor’s peak current during normal linear operation. The line looks so pretty that I’ll assume it continues upward to the maximum 12-bit DAC value of 4095 and the corresponding ET227 current. Working backwards, that will be 3.1 A and should suffice for all but the highest peaks at high line voltage.

  • Kenmore 158: Recalibrated Hall Effect Sensor Amp

    Reducing the differential amp gain fits a higher current into the Arduino’s fixed 5 V ADC range:

    Hall Sensor Differential Amp
    Hall Sensor Differential Amp

    Those are 1% resistors, chosen from the heap for being pretty close to what I needed. Given that it’s an LM324 op amp, we’re not talking instrumentation grade results here.

    The same calibration run that produced the DAC plot gave these values:

    Current Calibrate - ADC - 270k Hall 2.7k opto
    Current Calibrate – ADC – 270k Hall 2.7k opto

    The linear fit gives the actual current, as seen by the Tek probe, for a given ADC reading.

    The trimpot controls the offset voltage at zero current; working backwards, ADC = 0 corresponds to 140 mV, a bit higher than the actual 90 mV. Close enough, at least for a linear fit to eyeballed data, sez I.

    Working forward, the maximum ADC value of 1023 corresponds to 4 A, which should suffice.

  • Kenmore 158: Motor Flyback Diode

    Although small power diodes make fine flyback diodes for relays, the motor can draw several amps during the startup pulse, which will be a bit out of spec for the usual 1N4007-class diodes. Pressing an old 5 A / 200 V stud diode into service produces the ungainly black-and-blue lump eating the end of the green wire:

    Motor flyback diode - installed
    Motor flyback diode – installed

    For completeness, here’s the entire AC line interface part of the schematic:

    AC Power Interface
    AC Power Interface

    The diode’s 200 V limit should suffice, even for cold starts at high line peaks, but, when you build this with new parts, get something rated a bit higher, OK?

    The four NTC power thermistors lie just to the right of the relay, before the bridge rectifier.