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: Electronics Workbench

Electrical & Electronic gadgets

  • Hall Effect LED Current Control: Switched MOSFET Gates

    The rise and fall times for the LEDs on the over-the-top blinky taillight left a bit to be desired, at least if you were interested in short pulses:

    VG 1193 mV - ID 50 mA-div - 1 ms PWM filter - overview
    VG 1193 mV – ID 50 mA-div – 1 ms PWM filter – overview

    So I spliced an analog switch between the PWM filter and the gate, with inputs selecting ground and the PWM drive voltage:

    Switched MOSFET gate - analog switch schematic
    Switched MOSFET gate – analog switch schematic

    This being a prototype, that involved epoxying a SOT23-6 package atop the MOSFET, with flying wires all over the PCB:

    Hall Effect PCB - MOSFET gate switch
    Hall Effect PCB – MOSFET gate switch

    It works pretty well:

    VDS ILED 50 mA div - 200 50 150 25 mA
    VDS ILED 50 mA div – 200 50 150 25 mA

    The top trace is the drain voltage and the bottom trace is the LED current at 50 mA/div.

    The current transitions come out vertical at any sweep speed, even through the Tek Hall effect current probe. The pulses would be rectangular if I weren’t changing the current for each one.

    The current feedback loop closes through the Arduino’s main loop, which includes a 1 ms delay after each PWM output change before measuring the LED current. As a result, each loop takes just under 2 ms, but, fortunately, ramping from 25 mA (in the last pulse) to 200 mA (in the first pulse) requires less than 10 PWM increments; you can see the stairsteps if you squint.

    Next up: bump the PWM to 64 kHz (from 32 kHz) and rip out the pull-down resistor that used to hold the gate near ground when the output floated as an input. That should improve the output ripple caused by the MOSFET’s bias as a perfectly serviceable linear amplifier.

    The control loop now fetches durations & currents from an array-of-structs, so I can customize each pulse. An obvious enhancement: remember the gate drive that produced a given current, then restore the corresponding value as the starting PWM setting for each pulse, so the loop begins closer to reality. The gate drive varies with temperature and suchlike, so it can’t be a compile-time constant, but maybe the startup routine could preload the array / list / cache with values taken from a “lamp test”.

    Four close-together flashes repeating at about 2 Hz, even with two runt pulses, turn the LEDs into a real eye magnet…

  • 3D Printed Things I’ve Designed: Brag Sheets

    The whole reason I got a 3D printer in the first place was to make things that would otherwise be too difficult or tedious by hand or on a CNC mill. Most of the things I make look like brackets and I don’t do sculptures … this stuff solves problems!

    Being able to go from “I need a part shaped like that” to holding the thing in my hand a few hours (or, for complex designs, days) later is empowering. Being able to adjust a dimension by changing the source code and “recompiling” to get a new part is wonderful.

    These five slides from the presentation show my answers to the question “Why would anyone want a 3D printer?” Clicky for more dots.

    Things I Designed - 1
    Things I Designed – 1
    Things I Designed - 2
    Things I Designed – 2
    Things I Designed - 3
    Things I Designed – 3
    Things I Designed - 4
    Things I Designed – 4
    Things I Designed - 5
    Things I Designed – 5

    You can find those and more by searching for OpenSCAD source code.

    They go along with the sheets of solid models.

  • Headband Magnifier: Lamp Switch

    One of my headband magnifiers has a headlight above the brim, an incandescent flashlight bulb powered by a pair of AAA alkaline cells, that hasn’t worked well since the day I bought it. This being a time of finishing small projects, I finally tore it apart and discovered that the cells and contacts were in fine shape (!), the bulb (remember bulbs?) worked, the wiring was OK, but the switch was bad.

    Magnifying headband - lamp switch
    Magnifying headband – lamp switch

    The switch body seems to be firmly anchored in place, so I pried that red base plate off in situ, un-bent the silver-plated (!) spring-contact-actuator, and reassembled it in reverse order. No pictures, as it took less time to do than to tell, but it now works perfectly… most likely, for the first time ever.

    Stop squirming! This can be much more painful…

    Magnifying headband - in action
    Magnifying headband – in action

    I’m mildly tempted to hotwire the guts of a white LED flashlight into the thing, but that would require either another AA cell or a booster circuit and I’m not ready for that just yet.

  • Water Heater Anode Rod Status

    The Whirlpool water heater anode rod is corroding nicely:

    Whirlpool anode rod - 2014-04
    Whirlpool anode rod – 2014-04

    The new GE water heater anode rod seems to be passivating:

    GE anode rod - coated - 2014-04
    GE anode rod – coated – 2014-04

    There’s some corrosion up near the bolt head, so it’s not entirely asleep:

    GE anode rod - bolt - 2014-04
    GE anode rod – bolt – 2014-04

    I hammered the coating off the rod, scuffed the shiny parts with coarse sandpaper, wiped off the dust, and stuck it back in its socket. We’ll see what it looks like next year.

    Both tanks flushed nicely without too much sediment.

    Searching for “water heater” will turn up other posts…

  • Incandescent Bulb Lifetime

    Two 40 W incandescent bulbs in the front bathroom burned out within a few days of each other. Being that type of guy, I know that I installed this bulb nine years ago:

    Bulb base - install date
    Bulb base – install date

    The date is easier to read with the bulb in hand: 13 Feb 05. The (5 yrs) indicates the previous bulb in that socket lasted five years.

    The other bulb date went in during March 09, so it survived only five years; the previous bulb lasted 6 years.

    Even though 40 W incandescent bulbs are history, maybe I have enough spares on the shelf that the next owner can replace ’em with cheap LEDs.

    This may not be science, but it does have numbers…
  • Arduino Knockoff: Cold Solder Joints!

    The knockoff Arduino Pro Mini I used for the strobe photography controller ran the default Blink sketch perfectly, but didn’t respond to its own Reset pushbutton. Probing the Reset line at pin 29 on the microcontroller showed that the pushbutton didn’t pull the +5 V line to ground, so the switch was broken, a trace was broken, or …

    Touching the soldering iron to a switch pin caused the whole thing to pop loose. One glance at the pads tells you something’s badly wrong:

    Arduino Pro Mini Knockoff - cold solder joints
    Arduino Pro Mini Knockoff – cold solder joints

    A closeup, rotated a quarter-turn clockwise:

    Arduino Pro Mini Knockoff - cold solder joint - detail
    Arduino Pro Mini Knockoff – cold solder joint – detail

    That’s the nicest picture of cold solder joints you’ve seen in a while, isn’t it?

    Resoldering the switch solved the problem and, while the iron was hot, I touched all the microcontroller pins, too, just in case…

  • Kenmore Model 158 Sewing Machine: Cool White LED Strip Lights

    The reel of cool-white LEDs finally arrived from halfway around the planet and, based on the ahem customer feedback concerning the earlier prototype warm white LED strip lights for Mary’s sewing machine, I went with two parallel strips on each mount:

    Strip Light Mount - 2 wide - build layout
    Strip Light Mount – 2 wide – build layout

    Natural PLA provides a nice, crystalline appearance:

    Kenmore 158 Sewing Machine - Cool white LEDs - rear no flash
    Kenmore 158 Sewing Machine – Cool white LEDs – rear no flash

    Cool white LEDs have somewhat higher lumen/watt efficiency, but the real gain came from doubling the number of LEDs:

    Kenmore 158 Sewing Machine - Cool white LEDs - front flash
    Kenmore 158 Sewing Machine – Cool white LEDs – front flash

    I overvolted the warm white LEDs to 14 V to get closer to 20 mA/segment, but the cool white ones run pretty close to 20 mA at 12 V, so I didn’t bother.

    That black Gorilla Tape remains butt-ugly:

    Kenmore 158 Sewing Machine - Cool white LEDs - rear flash
    Kenmore 158 Sewing Machine – Cool white LEDs – rear flash

    Obviously, I must find some white duct tape…

    Commercial versions of this hack secure the wiring with little white clips and foam tape, so I should conjure up something like that. Mary specifically did not want the lights affixed under the arm, though, so those things weren’t even in the running.

    The OpenSCAD source code widens the mount and moves the wiring conduit a little bit, to simplify the connections to both strips, but is otherwise identical to the earlier version:

    // LED Strip Lighting Brackets for Kenmore Model 158 Sewing Machine
    // Ed Nisley - KE4ZNU - March 2014
    
    Layout = "Build";			// Build Show Channels Strip
    
    //- Extrusion parameters must match reality!
    //  Print with 2 shells and 3 solid layers
    
    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
    
    inch = 25.4;
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //----------------------
    // Dimensions
    
    Segment = [25.0,10.0,3.0];		//  size of each LED segment
    SEGLENGTH = 0;
    SEGWIDTH = 1;
    SEGHEIGHT = 2;
    
    WireChannel = 3.0;				// wire routing channel
    
    StripHeight = 12.0;				// sticky tape width
    StripSides = 8*4;
    
    DefaultLayout = [1,2,"Wire","NoWire"];
    NUMSEGS = 0;
    NUMSTRIPS = 1;
    WIRELEFT = 2;
    WIRERIGHT = 3;
    
    EndCapSides = StripSides;
    
    CapSpace = 2.0;						// build spacing for endcaps
    BuildSpace = 3.0;					// spacing between objects on platform
    
    //----------------------
    // 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);
    
    }
    
    //-- The negative space used to thread wires into the endcap
    
    module MakeWireChannel(Layout = DefaultLayout,Which = "Left") {
    	
    	EndCap = [(2*WireChannel + 1.0),Layout[NUMSTRIPS]*Segment[SEGWIDTH],StripHeight];	// radii of end cap spheroid
    	
    	HalfSpace = EndCap[0] * ((Which == "Left") ? 1 : -1);
    	
    	render(convexity=2)
    	translate([0,Segment[SEGWIDTH]/2,0])
    		intersection() {
    			union() {
    				cube([2*WireChannel,WireChannel,EndCap[2]],center=true);
    				translate([-2*EndCap[0],0,EndCap[2]/2])
    					rotate([0,90,0]) rotate(180/6)
    						PolyCyl(WireChannel,4*EndCap[0],6);
    			}
    			translate([HalfSpace,0,(EndCap[2] - Protrusion)]) {
    				cube(2*EndCap,center=true);
    			}
    		}
    }
    
    //-- The whole strip, minus wiring channels
    
    module MakeStrip(Layout = DefaultLayout) {
    	
    	EndCap = [(2*WireChannel + 1.0),Layout[NUMSTRIPS]*Segment[SEGWIDTH],StripHeight];	// radii of end cap spheroid
    
    	BarLength = Layout[NUMSEGS] * Segment[SEGLENGTH];				// central bar length
    
    	hull()
    		difference() {
    			for (x = [-1,1])						// endcaps as spheroids
    				translate([x*BarLength/2,0,0])
    					resize(2*EndCap) rotate([0,90,0]) sphere(1.0,$fn=EndCapSides);
    			translate([0,0,-EndCap[2]])
    				cube([2*BarLength,3*EndCap[1],2*EndCap[2]],center=true);
    			translate([0,-EndCap[1],0])
    				cube([2*BarLength,2*EndCap[1],3*EndCap[2]],center=true);
    		}
    
    }
    
    //-- Cut wiring channels out of strip
    
    module MakeMount(Layout = DefaultLayout) {
    	
    	BarLength = Layout[NUMSEGS] * Segment[SEGLENGTH];
    	
    	difference() {
    		MakeStrip(Layout);
    		if (Layout[WIRELEFT] == "Wire")
    			translate([BarLength/2,0,0])
    				MakeWireChannel(Layout,"Left");
    		if (Layout[WIRERIGHT] == "Wire")
    			translate([-BarLength/2,0,0])
    				MakeWireChannel(Layout,"Right");
    	}
    }
    
    //- Build it
    
    ShowPegGrid();
    
    if (Layout == "Channels") {
    	translate([ (2*WireChannel + 1.0),0,0]) MakeWireChannel(DefaultLayout,"Left");
    	translate([-(2*WireChannel + 1.0),0,0]) MakeWireChannel(DefaultLayout,"Right");
    }
    
    if (Layout == "Strip") {
    	MakeStrip(DefaultLayout);
    }
    	
    if (Layout == "Show") {
    	MakeMount(DefaultLayout);
    }
    
    if (Layout == "Build") {
    
    	translate([0,(3*Segment[SEGWIDTH]),0]) MakeMount([1,2,"Wire","Wire"]);		// rear left side, vertical
    	translate([0,0,0]) MakeMount([5,2,"Wire","NoWire"]);				// rear top, across arm
    	translate([0,-(3*Segment[SEGWIDTH]),0]) MakeMount([6,2,"NoWire","Wire"]);	// front top, across arm
    }