By turns: tinker, engineer, husband, author, amateur raconteur, recumbent cyclist, father, ham radio geek. So many projects, so little time!

Homepage: http://softsolder.com

American Standard Elite Kitchen Faucet: Hot Limit Safety Stop FAIL

During an evening KP session, the kitchen faucet handle jammed at the clockwise (hottest) end of its travel and refused to turn; it continued to move vertically and I turned off the water. This had happened before, so I knew roughly what to expect:

Am Std Elite Faucet - misaligned hot limit stop

The pointer on the red hot limit safety stop ring should be aimed just right of the front screw, at the 0 position producing maximum hotness. The scale reads backwards, perhaps in units of increasing safety.

In that position, the ring prevents the valve core from turning counterclockwise, which explains the symptoms. With the water turned off (at the ball valves in the basement) and the valve stub tilted vertically, the ring popped loose (it shouldn’t move on its own) and exposed the problem:

Am Std Elite Faucet - wrecked hot limit splines - as found
Am Std Elite Faucet – wrecked hot limit splines – as found

Neither Mary nor I recall applying that much force to the handle, but ya never know.

The flanges protruding from the stem prevent you from removing the ring, but a pair of small diagonal cutters will chop right through the plastic. If you’re one of the six people depending on the limit stop to keep the water temperature under control, you probably don’t want to cut the ring out; I have no suggestions on how to repair it.

It’s obvious the splines won’t ever be the same again:

Am Std Elite Faucet - wrecked hot limit splines - detail 1
Am Std Elite Faucet – wrecked hot limit splines – detail 1

The ring has two sets of splines and they’re both wrecked:

Am Std Elite Faucet - wrecked hot limit splines - detail 2
Am Std Elite Faucet – wrecked hot limit splines – detail 2

With the ring out of the way, it’s easy to see the trunnion shaft has moved leftward:

Am Std Elite Faucet - misaligned pivot shaft
Am Std Elite Faucet – misaligned pivot shaft

There’s essentially no clearance between the shaft and the ring, so it was rubbing against the ring, as evidenced by the red debris left behind when I tapped it to the far end of its travel:

Reassemble in reverse order and it works fine again.

I expect the shaft will resume moving leftward and eventually jam in the notch, probably after abrading the white plastic, but I don’t see how to lock it in place.


1 Comment

Windows-free BIOS Update

A new-to-me Dell Optiplex 9020 needed a BIOS update, which, as always, arrives in a Windows / DOS EXE file. Because I’d already swapped in an SSD and installed Manjaro, I had to (re-)discover how to put the EXE file on a bootable DOS USB stick.

The least horrible way seemed to be perverting a known-good FreeDOS installation image:

sha256sum FD12FULL.zip 
fd353f20f509722e8b73686918995db2cd03637fa68c32e30caaca70ff94c6d2  FD12FULL.zip

Unzip it to get the USB image file, then find the partition offset:

fdisk -l FD12FULL.img
Disk FD12FULL.img: 512 MiB, 536870912 bytes, 1048576 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device        Boot Start     End Sectors   Size Id Type
FD12FULL.img1 *       63 1048319 1048257 511.9M  6 FAT16

Mount the partition as a loop device:

sudo mount -o loop,offset=$((63*512)),uid=ed FD12FULL.img /mnt/loop

See how much space is left:

df -h /mnt/loop
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0      512M  425M   87M  84% /mnt/loop

The image file is 512 MB and has 87 MB available. The BIOS file is 9.5 MB, so copy the file to the “drive”:

cp O9020A25.exe /mnt/loop

Which knocks the available space down by about what you’d expect:

df -h /mnt/loop
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0      512M  435M   78M  85% /mnt/loop

Unmount the image “drive”:

sudo umount /mnt/loop

Copy the image file to a USB stick:

sudo dcfldd status=progress bs=1M if=FD12FULL.img of=/dev/sdg
512 blocks (512Mb) written.
512+0 records in
512+0 records out

Pop the USB stick in the Optiplex, set the BIOS to boot from “Legacy” ROMs, whack F12 during the reboot, pick the USB stick from the list, and It Just Works™:

BIOS Update screen
BIOS Update screen

We have a couple of other 9020s around that need the same treatment, so the effort won’t go to waste.



GCMC: Circular Slide Rule Scales

The Tektronix Circuit Computer, being a specialized circular slide rule, requires logarithmic scales bent around arcs:

Scale Tick Layout - Bottom Deck
Scale Tick Layout – Bottom Deck

Each decade spans 18°, except for the FL scale’s 36° span to extract the square root of the LC product:

FL = 1 / (2π · sqrt(LC))

The tick marks can point inward or outward from their baseline radius, with corresponding scale labels reading either inward or outward.

There being no (easy) way to algorithmically set the tick lengths, I used a (pair of) tables (a.k.a. vector lists):

TickScaleNarrow = {
… and so on …

The first number in each vector is the tick value in the decade, the log of which corresponds to its angular position. The second gives its length, with three constants matching up to the actual lengths on the Tek scales.

The Circuit Computer labels only three ticks within each decade in the familiar (to EE bears, anyhow) 1, 2, 5 sequence. Their logs are 0.0, 0.3, and 0.7, spacing them neatly at the 1/3 decade points.

Pop quiz: If you wanted to label two evenly spaced ticks per decade, you’d mark 1 and …

Generating the L (inductance) scale on the bottom deck goes like this:

  Radius = DeckRad - ScaleSpace;

  MinLog = -9;
  MaxLog = 6;
  Arc = -ScaleArc;

  dec = 1;
  offset = 0deg;
  for (logval = MinLog; logval < MaxLog; logval++) {
    a = offset + logval * Arc;
    dec = (dec == 100) ? 1 : 10 * dec;

  a = offset + MaxLog * Arc;

The L scale covers 1 nH to 1 MH (!), as set by the MinLog and MaxLog values. Arc sets the angular size of each decade from ScaleArc, with the negative sign indicating the values increase in the clockwise direction.

The first decade starts with a tick labeled 1, so dec = 1. The next decade has dec = 10 and the third has dec = 100. Maybe I should have used the log values 0, 1, and 2, but that seemed too intricate.

The angular offset is zero because this is the outermost scale, so 1.0 H will be at 0° (the picture is rotated about half a turns, so you’ll find it off to the left). All other scales on the deck have a nonzero offset to put their unit tick at the proper angle with respect to this one.

The scales have legends for each group of three decades, positioned in the middle of the group:

  logval = MinLog + 1.5;
  a = offset + logval * Arc;
  ArcLegend("nH - nanohenry  x10^-9",r,a,INWARD);

  logval += 3;
  a = offset + logval * Arc;
  ArcLegend("μH - microhenry  x10^-6",r,a,INWARD);

I wish there were a clean way to draw exponents, as the GCMC Hershey font does not include superscripts, but the characters already live at the small end of what’s do-able with a ballpoint pen cartridge. Engraving will surely work better, but stylin’ exponents are definitely in the nature of fine tuning.

With all that in hand, the scales look just like they should:

Tektronix Circuit Computer - Bottom Deck - scale detail
Tektronix Circuit Computer – Bottom Deck – scale detail

The GCMC source code as a GitHub Gist:



Monthly Science: Vegetable Ice Crystals

Mary made a batch of veggies in tomato sauce and froze meal-size portions as winter treats. The moist air inside the containers froze into delicate ice blades on the zucchini slices:

Veggie ice crystals - overview
Veggie ice crystals – overview

A closer look:

Veggie ice crystals - detail
Veggie ice crystals – detail

The blade cross-sections might be oblong hexagons, but it’s hard to tell with crystals melting almost instantly after the lid comes off. Some of the smaller hair-like blades reminded me of tin whiskers.


Leave a comment

LED Floor Lamp UI Improvement

A new floor lamp arrived with the usual dark-gray-on-black annotations on an absolutely non-tactile pair of capacitive controls. For a device intended for use in a dim room, this makes little sense, unless you’re both trendy and concerned about manufacturing costs.

A strip of 1/4 inch Kapton tape added just enough tactility to find the damn buttons without looking at the lamp head:

Teckin floor lamp - tactile switch tape
Teckin floor lamp – tactile switch tape

The pole’s non-adjustable length put the lamp head well above eye level, so I removed one pole segment. This required cutting the 12 V zipcord and crimping a pair of connectors:

Teckin floor lamp - spliced wire
Teckin floor lamp – spliced wire

I briefly considered conjuring a skinny connector, but came to my senses: there’s plenty of zipcord if I must chop out the connectors, particularly seeing as how shortening the pole added a foot.

The setscrew at the bottom of the gooseneck crunched the zipcord against the metal shell. A polypropylene snippet made me feel better, even if it makes no difference:

Teckin floor lamp - wire clamp pad
Teckin floor lamp – wire clamp pad

After all that, It Just Worked™:

Teckin floor lamp - installed
Teckin floor lamp – installed


Leave a comment

GCMC Radial Text

The Tektronix Circuit Computer needs text along radial lines:

Tek CC - original RC arrow layout
Tek CC – original RC arrow layout

Fortunately, this doesn’t require nearly as much effort as the text-on-arcs code, because GCMC includes functions to rotate paths around the origin:

return rotate_xy(TextPath,Angle) + CenterPt;

The only trick is figuring out how to handle the justification, given the overall path length:

  local pl = TextPath[-1].x;

  local ji = (Justify == TEXT_LEFT)     ? 0mm :
             (Justify == TEXT_CENTERED) ? -pl/2 :
             (Justify == TEXT_RIGHT)    ? -pl :

A testcase showed it worked:

Radial text testcase
Radial text testcase

With that in hand, I took the liberty of slightly simplifying the original Tek layout:

Tek CC - radial text example
Tek CC – radial text example

If lives depended on it, one could duplicate the Tek layout, but they don’t and I didn’t. Fancy typography isn’t a GCMC thing.

And, yeah, laser printing is way crisper than a pen drawing.

The GCMC source code as a GitHub Gist:


Leave a comment

GCMC Text on Arcs: Improved Version

The Tektronix Circuit Computer scale annotations read both inward (from the center) and outward (from the rim):

Text on Arcs - orientation
Text on Arcs – orientation

It’s surprisingly difficult (for me, anyhow) to see the middle FL Scale as reading upside-down, rather than mirror-image backwards.

This turned into a rewrite of the the read-outward annotation code I used for the vacuum tube reflectors. Eventually the justification and orientation options came out right:

Text-on-arcs example
Text-on-arcs example

The text baseline sits at the specified radius from the center point, regardless of its orientation, so you must offset the text path by half its height in the proper direction before handing it to the ArcText function.

The testcase shows the invocation ritual:

    ctr = [0mm,0mm];

    tp = scale(typeset("Right Inward",TextFont),ScaleTextSize);
    tpa = ArcText(tp,ctr,30mm,45deg,TEXT_RIGHT,INWARD);
    tp = scale(typeset("Right Outward",TextFont),ScaleTextSize);
    tpa = ArcText(tp,ctr,30mm,45deg,TEXT_RIGHT,OUTWARD);

    tp = scale(typeset("Center Inward",TextFont),ScaleTextSize);
    tpa = ArcText(tp,ctr,20mm,45deg,TEXT_CENTERED,INWARD);
    tp = scale(typeset("Center Outward",TextFont),ScaleTextSize);
    tpa = ArcText(tp,ctr,20mm,45deg,TEXT_CENTERED,OUTWARD);

    tp = scale(typeset("Left Inward",TextFont),ScaleTextSize);
    tpa = ArcText(tp,ctr,10mm,45deg,TEXT_LEFT,INWARD);
    tp = scale(typeset("Left Outward",TextFont),ScaleTextSize);
    tpa = ArcText(tp,ctr,10mm,45deg,TEXT_LEFT,OUTWARD);


A utility function to draw scale legends stuffs some of that complexity into a bottle:

function ArcLegend(Text,Radius,Angle,Orient) {

  local tp = scale(typeset(Text,TextFont),LegendTextSize);
  local tpa = ArcText(tp,[0mm,0mm],Radius,Angle,TEXT_CENTERED,Orient);


Which means most of the text uses a simpler invocation:

  r = Radius + TickMajor + 2*TickGap + LegendTextSize.y;

  logval = MinLog + 1.5;
  a = offset + logval * Arc;
  ArcLegend("nH - nanohenry  x10^-9",r,a,INWARD);

  logval += 3;
  a = offset + logval * Arc;
  ArcLegend("μH - microhenry  x10^-6",r,a,INWARD);

Arc determines the angular span of each decade, with positive values going counterclockwise. MinLog is the logarithm of the scale endpoint, so adding 1.5 puts the text angle one-and-a-half decades from MinLog and multiplying by Arc moves it in the right direction. The offset angle rotates the entire scale with respect to the 0° reference sticking out the X axis over on the right. The top picture has its 0° reference pointing north-northeast.

The GCMC source code as a GitHub Gist:

GCMC treats variables defined inside a function as local, unless they’re already defined in an enclosing scope, whereupon you overwrite the outer variables. This wasn’t a problem in my earlier programs, but I fired the footgun with nested functions using the same local / temporary variables. Now, I ruthlessly declare truly local variables as local, except when I don’t, for what seem good reasons at the time.


1 Comment