Monthly Science: Inchworms

A Rudbeckia Black-eyed-susan coneflower from the garden carried a passenger to our patio table:

Inchworm - linear
Inchworm – linear

Even linearized, the inchworm was barely 20 mm long; it’s the thought that counts.

The stamens mature in concentric rings, each stamen topped by a pollen grain. Apparently, those grains are just about the most wonderful food ever, as the inchworm made its way around the ring eating each grain in succession:

Inchworm - feeding
Inchworm – feeding

Of course, what goes in must come out:

Inchworm - excreting
Inchworm – excreting

I had to brush off the table before washing it; the pellets are dry, but smear when you get them wet.

Another flower in the vase held a 10 mm inchworm with plenty of upside potential:

Inchworm - junior edition
Inchworm – junior edition

After nearly a week, the flowers were done and the inchworms had moved on. We wish them well, although we likely won’t recognize them in the future.

LTSpice Diode Models Sorted By Forward Voltage

LTSpice includes a bunch of LEDs I’ll never own, so finding a tabulation of their forward voltages helped match them against various LEDs on hand. The table was sorted by the forward voltage at the diode’s rated average current, which wasn’t helpful for my simple needs, so I re-sorted it on the Vf @ If = 20 mA column over on the right:

Part #       Mfg             Is         N      Iavg Vf@Iavg  Vd@If
QTLP690C     Fairchild    1.00E-22    1.500    0.16   1.90    1.82
PT-121-B     Luminous     4.35E-07    8.370   20.00   3.84    2.34
LUW-W5AP     OSRAM        6.57E-08    7.267    2.00   3.26    2.39
LXHL-BW02    Lumileds     4.50E-20    2.600    0.40   2.95    2.75
W5AP-LZMZ-5K Lumileds     3.50E-17    3.120    2.00   3.13    2.76
LXK2-PW14    Lumileds     3.50E-17    3.120    1.60   3.11    2.76
AOT-2015     AOT          5.96E-10    6.222    0.18   3.16    2.80
NSSW008CT-P  Nichia       2.30E-16    3.430    0.04   2.92    2.86
NSSWS108T    Nichia       1.13E-18    3.020    0.04   2.99    2.94
NSPW500BS    Nichia       2.70E-10    6.790    0.03   3.27    3.20
NSCW100      Nichia       1.69E-08    9.626    0.03   3.60    3.50

The currents come from plugging the various constants into the Schockley Diode Equation and turning the crank.

One could, of course, measure the constants for the diodes on hand to generate a proper Spice model, but that seems like a lot of work for what’s basically a blinking LED.

Cheap LED Assortment: Forward Voltage

Starting with a box of cheap LEDs from halfway around the planet:

LED kit - case
LED kit – case

Measuring the forward voltages didn’t take much effort:

5mm 3mm LED kit - Vf tests
5mm 3mm LED kit – Vf tests

The top array fed the LEDs from a bench power supply through a 470 Ω resistor, with the voltage adjusted to make the current come out right. The bottom array came from the Siglent SDM3045 multimeter’s diode test function, which goes up to 4 V while applying about 400 µA to the diode (the 20 µA header is wrong).

These numbers come into play when blinking an LED from a battery, because a battery voltage much below the Vf value won’t produce much light. It’s a happy coincidence that a single lithium cell can light a white or blue LED …

For comparison, the forward voltages from another batch of LEDs:

ROYGBUIW - LED Color vs Vf
ROYGBUIW – LED Color vs Vf

Those all look a bit higher at 20 mA, but everything about the measurements is different, so who knows?

Power Outage

Just before Tropical Storm Isaias rolled through, my hygrometer reached a new high:

Pre-Isaias humidity
Pre-Isaias humidity

The National Weather Service reported 99% at the airport a few miles away, so the meter’s calibration seems about right.

Shortly thereafter, the humidity dropped to the mid-70s as the wind picked up and, over the next few hours, falling branches took out vast swaths of Central Hudson’s electrical infrastructure. My little generator saved our refrigerator & freezer during 15 hours of outage; three days later, thousands of folks around us still have no power.

A confluence of other events, none nearly so dramatic, will throttle my posting over the next two weeks.

We’re OK and hope you’re OK, too …

Monthly Science: Small Praying Mantis

These Praying Mantis nymphs may have emerged from the ootheca I rescued from the grass trimming operation earlier this year:

Praying Mantises in grass - 2020-07-24
Praying Mantises in grass – 2020-07-24

The closest one was about 60 mm long, with plenty of growing ahead in the next few months:

Praying Mantis - 2020-07-24
Praying Mantis – 2020-07-24

A few days later, I spotted a smaller one, maybe 40 mm from eyes to cerci, hiding much deeper in the decorative grass clump. Given their overall ferocity, it was likely hiding from its larger sibs.

They have also been stilting their way across the window glass and screens in search of better hunting grounds. My affixing their oothecae to another bush may have disoriented them at first, but they definitely know where their next meal comes from!

Perhaps as a bonus, a Katydid appeared inside the garage, stuck to the side of a trash can that Came With The House™ long ago:

Katydid
Katydid

I deported it outside, in hopes of increasing the world’s net happiness.

The stickers covering the can say “WPDH: A Decade of Rock ‘n’ Roll”, suggesting they date back to 1986, ten years after (Wikipedia tells me) WPDH switched from country to rock. Neither genre did much for me, so I never noticed.

NPN RGB Astable Multivibrator Timing Adjustment

Back in the beginning of July, I replaced the NP-BX1 battery in the RGB Piranha astable multivibrator with a 18650 lithium cell and a USB charge controller, then watched it blink for the next two weeks on the first charge:

Astable - 10 11 12 uF tweak - 027
Astable – 10 11 12 uF tweak – 027

However, the blinks looked … odd and some poking around with a Tek current probe showed the red and blue astables had locked together, so they blinked in quick succession. Alas, I don’t have a scope shot to prove it.

I built all three astables with the same parts, figuring the normal tolerance of electrolytic caps would make the astables run at slightly different rates, which they did at first.

This being a prototype, I just soldered a 1 µF cap onto the blue channel’s existing 10 µF cap:

Astable - 11 uF cap - detail
Astable – 11 uF cap – detail

You can barely make out the top of the additional 2.2 µF cap on the red channel, through the maze of components; now, they definitely have different periods.

Aaaand the scope shot to prove it:

Astable NPN - 10 11 12 uF tweak - 10 mA-div
Astable NPN – 10 11 12 uF tweak – 10 mA-div

The bottom trace shows the battery current at 10 mA/div. The first pulse, over on the left, has the red and blue LEDs firing in quick succession with some overlap, but they separate cleanly for their next pulses.

You don’t want to build a battery-powered astable from NPN transistors, because the 8 mA current between blinks is murderously high. In round numbers, each of the three LEDs blinks twice a second for 30 ms at 20 mA, so they average 3.6 mA, less than half the current required to keep the astables running between blinks. Over the course of 14 days, the circuit drew 11.6 mA × 336 hr = 3900 mA·h until the protection circuit shut it down.

The lead photo shows a harvested 18650 cell, but I started with a known-good Samsung 18650 cell rated at 2600 mA·h at a 0.2C = 520 mA rate to 2.75 V. It’s comforting to see more energy trickling out at a 0.005C rate!

I must conjure a holder with contacts for an 18650 cell, support for a trio of 2N7000 MOSFET astables, and some kind of weird spider with the RGB Piranha LED on the top. Even a harvested 18650 cell should last a couple of months with a much longer blink period (500 ms is much too fast), less LED current (this one is shatteringly bright), and a lower average current.

And, yeah, I’ve been misspelling “Piranha” for a while.

Quilting Hexagon Template Generator

Mary took on the task of finishing a hexagonal quilt from pieced strips, only to discover she’ll need several more strips and the myriad triangles required to turn hexagons into strips. The as-built strips do not match any of the standard pattern sizes, which meant ordinary templates were unavailing. I offered to build a template matching the (average) as-built hexagons, plus a triangle template based on those dimensions.

Wikipedia has useful summaries of hexagon and equilateral triangle geometry and equations.

Quilters measure hexes based on their finished side length, so a “1 inch hex” has sides measuring 1 inch, with the seam allowance extending ¼ inch beyond the sides. It’s difficult to measure finished sides with sufficient accuracy, so we averaged the side-to-side distance across several hexes.

Some thrashing around produced a quick-and-dirty check piece that matched (most of) the stack of un-sewn hexes:

Quilting Hexagon Cutting Template
Quilting Hexagon Cutting Template

That one came from a knockoff of the circle template, after some cleanup & tweakage, but failed user testing for not withstanding the side force from the rotary cutter blade. The inside and outside dimensions were correct, however, so I could proceed with some confidence I understood the geometry.

Both the pattern width (the side-to-side distance across the inside of the hex) and the seam allowance appearing in the Customizer appear in inches, because that’s how things get measured outside the Basement Laboratory & Fabrication Facility:

FinishedWidthInch = 2.75;
FinishedWidth = FinishedWidthInch * inch;

SeamAllowanceInch = 0.25;
SeamAllowance = SeamAllowanceInch * inch;

You feed in one side-to-side measurement and all other hex dimensions get calculated from that number; quilters default to a ¼ inch seam allowance. Remember, standard quilt hexes are measured by their side length, so just buy some standard templates.

This is one of the few times I’ve needed triangle graph paper:

Hex Quilting Template - geometry doodles
Hex Quilting Template – geometry doodles

After I gave up trying to get it right on square-grid paper, of course.

Solidifying those relations:

Quilting Hex Template - build layout
Quilting Hex Template – build layout

Then math got real:

Hex Quilting Templates - on strips
Hex Quilting Templates – on strips

Both templates have non-skid strips to keep the fabric in place while cutting:

Hex Quilting Template - grip strips
Hex Quilting Template – grip strips

I should have embossed the size on each template, but this feels like a one-off project and YAGNI. Of course, that’s how I felt about the circle templates, so maybe next time I’ll get it right.

As it turned out, Mary realized she needed a template for the two half-triangles at the end of each row:

Quilting Hex Template - half-triangle
Quilting Hex Template – half-triangle

It’s half of the finished size of the equilateral triangle on the right, with seam allowance added all around. The test scrap of fabric on the left shows the stitching along the hypotenuse of the half-triangle, where it joins to the end-of-row hexagon. Ideally, you need two half-triangle templates, but Mary says it’s easier to cut the fabric from the back side than to keep track of two templates.

The family portrait now has three members:

Quilting Hex Template - family
Quilting Hex Template – family

The OpenSCAD source code as a GitHub Gist:

// Quilting - Hexagon Templates
// Ed Nisley KE4ZNU - July 2020
// Reverse-engineered to repair a not-quite-standard hexagon quilt
// Useful geometry:
// https://en.wikipedia.org/wiki/Hexagon
/* [Layout Options] */
Layout = "Build"; // [Build, HexBuild, HexPlate, TriBuild, TriPlate, EndBuild, EndPlate]
//-------
//- Extrusion parameters must match reality!
// Print with 2 shells
/* [Hidden] */
ThreadThick = 0.25;
ThreadWidth = 0.40;
HoleFinagle = 0.2;
HoleFudge = 1.00;
function HoleAdjust(Diameter) = HoleFudge*Diameter + HoleFinagle;
Protrusion = 0.1; // make holes end cleanly
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
inch = 25.4;
//-------
// Dimensions
/* [Layout Options] */
FinishedWidthInch = 2.75;
FinishedWidth = FinishedWidthInch * inch;
SeamAllowanceInch = 0.25;
SeamAllowance = SeamAllowanceInch * inch;
TemplateThick = 3.0;
TriKnob = true;
EndKnob = false;
/* [Hidden] */
FinishedSideInch = FinishedWidthInch/sqrt(3);
FinishedSide = FinishedSideInch * inch;
echo(str("Finished side: ",FinishedSideInch," inch"));
CutWidth = FinishedWidth + 2*SeamAllowance;
CutSide = CutWidth/sqrt(3);
echo(str("Cut side: ",CutSide / inch," inch"));
// Make polygon-circles circumscribe the target widths
TemplateID = FinishedWidth / cos(180/6);
TemplateOD = CutWidth / cos(180/6);
/* [Hidden] */
TriRadius = FinishedSide/sqrt(3);
TriPoints = [[TriRadius,0],
[TriRadius*cos(120),TriRadius*sin(120)],
[TriRadius*cos(240),TriRadius*sin(240)]
];
echo(str("TriPoints: ",TriPoints));
EndPoints = [[TriRadius,0],
[TriRadius*cos(120),TriRadius*sin(120)],
[TriRadius*cos(120),0]
];
echo(str("EndPoints: ",EndPoints));
TipCutRadius = 2*(TriRadius + SeamAllowance); // circumscribing radius of tip cutter
TipPoints = [[TipCutRadius,0],
[TipCutRadius*cos(120),TipCutRadius*sin(120)],
[TipCutRadius*cos(240),TipCutRadius*sin(240)]
];
HandleHeight = 1 * inch;
HandleLength = (TemplateID + TemplateOD)/2;
HandleThick = IntegerMultiple(3.0,ThreadWidth);
HandleSides = 12*4;
StringDia = 4.0;
StringHeight = 0.6*HandleHeight;
DentDepth = HandleThick/4;
DentDia = 15 * DentDepth;
DentSphereRadius = (pow(DentDepth,2) + pow(DentDia,2)/4)/(2*DentDepth);
KnobOD = 15.0; // Triangle handle
KnobHeight = 20.0;
//-------
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=HoleAdjust(FixDia)/2,h=Height,$fn=Sides);
}
//-------
// Hex template
module HexPlate() {
difference() {
cylinder(r=TemplateOD/2,h=TemplateThick,$fn=6);
translate([0,0,-Protrusion])
cylinder(r=TemplateID/2,h=(TemplateThick + 2*Protrusion),$fn=6);
}
for (i=[1:6/2])
rotate(i*60)
translate([0,0,TemplateThick/2])
cube([HandleLength,HandleThick,TemplateThick],center=true);
}
module HexHandle() {
difference() {
rotate([90,0,0])
scale([1,HandleHeight/(TemplateOD/2),1])
rotate(180/HandleSides)
cylinder(d=HandleLength,h=HandleThick,center=true,$fn=HandleSides);
translate([0,0,-HandleHeight])
cube([2*TemplateOD,2*TemplateOD,2*HandleHeight],center=true);
translate([0,HandleThick,StringHeight])
rotate([90,090,0])
rotate(180/8)
PolyCyl(StringDia,2*HandleThick,8);
for (j=[-1,1]) {
translate([0,j*(DentSphereRadius + HandleThick/2 - DentDepth),StringHeight])
rotate(180/48)
sphere(r=DentSphereRadius,$fn=48);
}
}
}
module HexTemplate() {
HexPlate();
HexHandle();
}
//-------
// Triangle template
module TriPlate() {
linear_extrude(height=TemplateThick)
intersection() {
offset(delta=SeamAllowance) // basic cutting outline
polygon(points=TriPoints);
rotate(180)
polygon(points=TipPoints);
}
}
module TriTemplate() {
union() {
if (TriKnob)
cylinder(d=KnobOD,h=KnobHeight,$fn=HandleSides);
TriPlate();
}
}
//-------
// End piece template
module EndPlate() {
linear_extrude(height=TemplateThick)
intersection() {
offset(delta=SeamAllowance) // basic cutting outline
polygon(points=EndPoints);
rotate(180)
polygon(points=TipPoints);
}
}
module EndTemplate() {
union() {
if (EndKnob)
translate([0,(TriRadius/2)*sin(30),0])
cylinder(d=KnobOD,h=KnobHeight,$fn=HandleSides);
EndPlate();
}
}
//-------
// Build it!
if (Layout == "HexPlate")
HexPlate();
if (Layout == "HexBuild")
HexTemplate();
if (Layout == "TriPlate")
TriPlate();
if (Layout == "TriBuild")
TriTemplate();
if (Layout == "EndPlate")
EndPlate();
if (Layout == "EndBuild")
EndTemplate();
if (Layout == "Build") {
translate([1.5*TriRadius,-TriRadius,0])
rotate(180/6)
TriTemplate();
translate([-1.5*TriRadius,-TriRadius,0])
rotate(180/6)
EndTemplate();
translate([0,TemplateOD/2,0])
HexTemplate();
}