Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.
When we rearranged the kitchen after installing the laminate flooring, I conjured up a countertop to replace the ancient one over a cabinet left standing in one end of the kitchen where the new refrigerator didn’t fit. This was a temporary measure until we built an additional cabinet adjacent to the old one and laid a single countertop over the whole affair. Having several short lengths of generic gray countertop left over from the Black Bathroom, laundry, and the other side of the kitchen, I butt-glued two hunks together with a small block of wood underneath as a support.
Time passes, we never did get around to building the other cabinet, and eventually the weight of the microwave and mixer bowed the poorly supported joint until it broke free and deposited the mixer on the floor.
Both pieces being bowed, I screwed some angle bracket underneath to straighten them out, clamped them together, laid a piece of tape over the joint, and match-marked the dowel locations:
Countertop – match-marked joint
Drilled holes for 1/4 dowel pins that I sliced off a length of aluminum rod (no sissy wood pins for me!):
Countertop – dowel hole jig
Slobbered epoxy over the pins with enough into the holes for good adhesion, then buttered up the joint to fill the voids:
Countertop – underside braces and joint
Put more tape over the countertop, sliced out the gap, and buttered up the top surface to fill the joint:
Countertop – filling joint
That works because JB Industro-Weld Epoxy turns out to be a nearly perfect color match:
Countertop – final joint
Those angle brackets remain in place underneath the surface in the hope they’ll prevent it from bowing again. An aluminum strip (not yet installed in these pix) fills the recess below the backsplash to level it with the underside of the countertop, providing more support over the back of the cabinet case.
The whole affair took a few days, what with curing successive epoxy applications overnight. Got to use some tools that don’t often see the light of day, too, which is always good fun.
Having not yet gotten around to building better taillights for our bikes, we picked up some Planet Bike Superflash lights on sale. I don’t like single-LED lights, because the optics produce a concentrated beam (which is how they get such high lumen ratings) that’s essentially invisible anywhere off-axis; a taillight that requires careful alignment for maximum effect is a Bad Thing. But, eh, they were on sale…
The graceful OEM seatpost mount, done in engineering plastic with smooth curves and something of a reputation for fragility, doesn’t work on a recumbent, so I build a butt-ugly mount that should last forever. It clamps firmly around a length of grippy silicone tape on the top seat frame rail:
Superflash on Tour Easy
The reviews also complain that normal road vibrations transmitted through the somewhat whippy OEM mount pop the case apart, depositing the lens and electronics on the road behind you. Hence the black tape across the case joint.
Here’s the whole affair on the bench:
Superflash on mount
The weird color line comes from white plastic left in the extruder that covers the bottom layer or two of each part. I’m not fussy about the first pass of any new gadget, because I know I’ll build at least one more to get everything right.
This is the first build arrangement; note the huge white teardrop blob at the start of the Skirt outline on the left. Obviously I didn’t have the initial retraction under control:
Superflash mount on build platform
The screw recesses built over the plate and got cute little support spiders to keep their interiors from sagging:
Superflash mount – bolt support
After doing it that way, I flipped the top piece over so it builds with the screw head recesses upward to get a better finish on those nice curves. That means the arch needs support, which almost worked, although some of the fins fell over:
Superflash mount – failed arch support
The solid model now adds a two-layer-thick flat plate joining the fins that should hold them firmly to the build plate.
Clamp Support – Solid Model
I also added an option to build the flash mounting shoe separately:
Superflash mount – solid model
That gives better control over the flange thickness, which turns out to be critical parameter requiring a bit of adjustment with a file in the first version. Of course, the shoe needs an alignment pin and another assembly step to glue it in place:
Superflash mount – gluing shoe
A 4-40 setscrew jams into the latch recess in the Superflash case, thus preventing it from walking off the shoe. You don’t need any particular pressure here, just enough protrusion to engage the case:
Superflash mount – setscrew
The first pass at hex nut recesses were exactly cos(30) too large, as I forgot my Useful Sizes file has the across-the-points diameter, so I added a dab of epoxy to each recess before gluing the halves together with solvent:
Superflash mount – glue clamping
And then it’s all good.
The OpenSCAD source code:
// Planet Bike Superflash mount for Tour Easy seatback
// Ed Nisley KE4ZNU - Dec 2011
Layout = "Show"; // Assembly: Show
// Parts: Clamp Base Shoe Mount
// Build Plate: Build
SeparateShoe = true; // true = print mounting shoe separately
// false = join shoe to Mount block
Support = true; // true = include support
Gap = 8; // between "Show" objects
include </home/ed/Thing-O-Matic/lib/MCAD/units.scad>
include </home/ed/Thing-O-Matic/Useful Sizes.scad>
include </home/ed/Thing-O-Matic/lib/visibone_colors.scad>
//-------
//- Extrusion parameters must match reality!
// Print with +1 shells, 3 solid layers, 0.2 infill
ThreadThick = 0.25;
ThreadWidth = 2.0 * ThreadThick;
HoleFinagle = 0.1;
HoleFudge = 1.00;
function HoleAdjust(Diameter) = HoleFudge*Diameter + HoleFinagle;
Protrusion = 0.1; // make holes end cleanly
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
function IntegerMultipleMin(Size,Unit) = Unit * floor(Size / Unit);
//-------
// Dimensions
BarDia = (5/8) * inch; // seat back rail diameter
BarRad = BarDia/2;
TapeThick = 0.3; // grippy tape around bar
HoleDia = BarDia + 2*TapeThick; // total hole dia
HoleRad = HoleDia/2;
HoleSides = 4*5;
echo("Bar hole dia: ",HoleDia);
TightSpace = 1.0; // space for tightening screws
PlateWidth = 20.0; // mounting plate across flanges
PlateLength = 20.0; // ... parallel to flanges
PlateThick = IntegerMultipleMin(1.96,ThreadThick); // ... thickness
FlangeThick = IntegerMultiple(1.40,ThreadThick); // lamp flange thickness
FlangeWidth = 2.0; // ... width
ShoeThick = PlateThick + FlangeThick; // dingus protruding from main block
ShoeOffset = 1.0; // offset due to end wall
echo("Shoe thickness: ",ShoeThick," = ",PlateThick," + ",FlangeThick);
LockOffset = -5.0; // offset of locking setscrew
TopRoundRad = 1.5*Head10_32/2; // tidy rounding on top edge of clamp
echo("Top rounding radius: ",TopRoundRad);
NutDia = Nut10_32Dia*cos(30); // adjust from across-points to across-flats dia
NutPart = IntegerMultiple(0.5*Nut10_32Thick,ThreadThick); // part of nut in each half
BoltOffset = HoleRad + max(Head10_32,NutDia);
BoltClear = Clear10_32;
BoltHeadDia = Head10_32;
BoltHeadThick = Head10_32Thick;
MountWidth = PlateLength + ShoeOffset; // side-to-side
MountLength = HoleDia + 3.5*max(BoltHeadDia,NutDia);
ClampHeight = TopRoundRad + HoleRad; // includes gap/2 for simplicity
BaseHeight = NutPart + HoleRad; // ... likewise
MountHeight = PlateWidth;
echo("Mount width: ",MountWidth," length: ",MountLength);
echo("Height of clamp: ",ClampHeight," base: ",BaseHeight," mount: ",MountHeight);
echo(" total: ",ClampHeight+BaseHeight+MountHeight);
AlignPegDia = 2.9; // shoe alignment peg
AlignPegLength = ShoeThick;
echo("Alignment peg length: ",AlignPegLength);
//-------
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);
}
module ShowPegGrid(Space = 10.0,Size = 1.0) {
Range = floor(50 / Space);
for (x=[-Range:Range])
for (y=[-Range:Range])
translate([x*Space,y*Space,Size/2])
%cube(Size,center=true);
}
//-------
// Upper clamp half
module Clamp() {
difference() {
translate([0,0,-TightSpace/2]) {
difference() {
translate([0,0,ClampHeight/2]) {
intersection() {
translate([0,0,-TopRoundRad])
minkowski() {
cube([(MountLength - 2*TopRoundRad),
(MountWidth - 2*Protrusion),
ClampHeight],center=true);
rotate([90,0,0])
cylinder(r=TopRoundRad,h=Protrusion,$fn=4*8);
}
cube([MountLength,MountWidth,ClampHeight],center=true);
}
}
translate([0,(MountWidth/2 + Protrusion)])
rotate([90,0,0])
PolyCyl(HoleDia,(MountWidth + 2*Protrusion),HoleSides);
for (Index=[-1,1])
translate([(Index*BoltOffset),0,0]) {
translate([0,0,-Protrusion])
PolyCyl(BoltClear,(ClampHeight + Protrusion));
translate([0,0,(ClampHeight - BoltHeadThick)])
PolyCyl(BoltHeadDia,(BoltHeadThick + Protrusion));
}
}
}
translate([0,0,-TightSpace/2])
cube([(MountLength + 2*Protrusion),
(MountWidth + 2*Protrusion),
TightSpace],center=true);
}
if (Support) // choose support to suit printing orientation
union() {
translate([0,0,1.5*ThreadThick])
cube([0.75*HoleDia,(MountWidth + 2*ThreadWidth),3*ThreadThick],center=true);
intersection() {
for (Index=[-3:3])
translate([0,Index*(MountWidth/6),-TightSpace/2])
rotate([90,0,0])
cylinder(r=(HoleRad - 0.25*ThreadThick),
h=2*ThreadWidth,center=true,$fn=HoleSides);
translate([-HoleRad,-MountWidth,0])
cube([HoleDia,2*MountWidth,HoleRad]);
}
}
}
//-------
// Lower clamp half = base
module Base() {
difference() {
translate([0,0,-TightSpace/2])
difference() {
translate([0,0,BaseHeight/2])
cube([MountLength,MountWidth,BaseHeight],center=true);
translate([0,(MountWidth/2 + Protrusion)])
rotate([90,0,0])
PolyCyl(HoleDia,(MountWidth + 2*Protrusion),HoleSides);
for (Index=[-1,1])
translate([(Index*BoltOffset),0,0]) {
translate([0,0,-Protrusion])
PolyCyl(BoltClear,(BaseHeight + Protrusion));
translate([0,0,(BaseHeight - NutPart)])
rotate(30)
PolyCyl(NutDia,(NutPart + Protrusion),6);
// cylinder(r=NutDia/2,h=(NutPart + Protrusion),$fn=6);
}
}
translate([0,0,-TightSpace/2])
cube([(MountLength + 2*Protrusion),
(MountWidth + 2*Protrusion),
TightSpace],center=true);
}
if (Support)
for (Index=[-1,1]) // support inside nut openings
translate([(Index*BoltOffset),
0,
(BaseHeight - (NutPart - ThreadThick) - TightSpace/2)]) {
translate([0,0,0])
for (Seg=[0:5]) {
rotate(30 + 360*Seg/6)
cube([NutDia/2,2*ThreadWidth,NutPart - ThreadThick],center=false);
}
}
}
//-------
// Superflash mounting shoe
// Offset by -ShoeOffset/2 in Y to align on Mount (half of total offset on each side)
module Shoe() {
difference() {
translate([-ShoeThick/2,-ShoeOffset/2,PlateWidth/2])
if (SeparateShoe)
cube([ShoeThick,PlateLength,PlateWidth],center=true);
else
cube([(ShoeThick + Protrusion),PlateLength,PlateWidth],center=true);
translate([-(FlangeThick - Protrusion),
-(PlateLength/2 + ShoeOffset/2 + Protrusion),
(MountHeight - FlangeWidth)])
cube([FlangeThick,(PlateLength + 2*Protrusion),(FlangeWidth + Protrusion)]);
translate([-(FlangeThick - Protrusion),
-(PlateLength/2 + ShoeOffset/2 + Protrusion),
-Protrusion])
cube([FlangeThick,(PlateLength + 2*Protrusion),(FlangeWidth + Protrusion)]);
translate([-(ShoeThick + Protrusion),LockOffset,MountHeight/2])
rotate([0,90,0])
rotate(0) // align to match Mount hole orientation
PolyCyl(Tap4_40,(ShoeThick + 2*Protrusion));
if (SeparateShoe)
translate([-(ShoeThick - AlignPegLength/2),0,MountHeight/2])
rotate([0,90,0])
PolyCyl(AlignPegDia,AlignPegLength);
}
}
//-------
// Bottom block for Superflash mount
module Mount() {
translate([0,0,MountHeight/2])
union() {
difference() {
union() {
translate([-MountLength/4,0,0])
cube([MountLength/2,MountWidth,MountHeight],center=true);
translate([((MountLength/2 - MountHeight)/2 + Protrusion),0,0])
cube([(MountLength/2 - MountHeight + 2*Protrusion),
MountWidth,
MountHeight],center=true);
translate([(MountLength/2 - MountHeight),0,0])
intersection() {
translate([MountLength/4,0,0])
cube([MountLength/2,MountWidth,MountHeight],center=true);
translate([0,0,MountHeight/2])
rotate([90,0,0])
cylinder(r=MountHeight,h=MountWidth,center=true,$fn=4*16);
}
}
translate([-(MountLength/2 + Protrusion),LockOffset,0])
rotate([0,90,0])
rotate(0) // align through hole sides with point upward
PolyCyl(Clear4_40,(MountLength + 2*Protrusion));
for (Index=[-1,1])
translate([(Index*BoltOffset),0,0]) {
translate([0,0,BaseHeight/2])
PolyCyl(BoltClear,(BaseHeight/2 + Protrusion));
translate([0,0,(BaseHeight - NutPart)])
rotate(30)
PolyCyl(NutDia,(NutPart + Protrusion),6);
}
if (SeparateShoe)
translate([-(MountLength/2 + AlignPegLength/2),0,0])
rotate([0,90,0])
PolyCyl(AlignPegDia,AlignPegLength);
}
if (Support)
for (Index=[-1,1]) // support inside nut openings
translate([(Index*BoltOffset),0,(MountHeight/2 - (NutPart - ThreadThick))]) {
translate([0,0,0])
for (Seg=[0:5]) {
rotate(30 + 360*Seg/6)
cube([NutDia/2,
2*ThreadWidth,
(NutPart - ThreadThick)],center=false);
}
}
if (!SeparateShoe)
translate([-MountLength/2,0,-MountHeight/2])
Shoe();
}
}
//-------
ShowPegGrid();
if (Layout == "Clamp")
Clamp();
if (Layout == "Base")
Base();
if (Layout == "Shoe")
Shoe();
if (Layout == "Mount")
Mount();
if (Layout == "Show") {
translate([0,0,(BaseHeight + MountHeight + Gap)]) {
translate([0,0,TightSpace/2 + Gap])
color(MFG) Clamp();
translate([0,0,-TightSpace/2])
rotate([180,0,0])
color(DHC) Base();
}
translate([0,0,0])
color(LDM) render(convexity=3) Mount();
if (SeparateShoe)
translate([-(MountLength/2 + Gap),0,0])
color(DDM) Shoe();
}
if (Layout == "Build") {
translate([-15,30,(BaseHeight - TightSpace/2)]) rotate([180,0,0])
Base();
translate([-15,00,0]) rotate([0,0,0])
Clamp();
if (SeparateShoe)
translate([20,30,ShoeThick]) rotate([0,-90,180])
Shoe();
if (SeparateShoe)
translate([-15,-30,MountHeight]) rotate([180,0,180])
Mount();
else
translate([-15,-40,MountWidth/2]) rotate([90,0,180])
Mount();
}
The original doodles, done on a retina-burning yellow scratchpad:
The batteries I rebuilt for our much-beloved Sony DSC-F505V camera back in early 2010 have faded away with constant use. Having already sawed the cases open, rebuilding three of them didn’t pose much of a challenge; this time I added a short tab of Kapton tape to help extract them from the camera socket.
Rebuilt NP-FS11 batteries
Three batteries seems to be about the minimax for ordinary use:
One in the camera
One in the carrying case
One in the charger
You (well, we) can’t keep track of more than three: it always seems one battery gets overused and another gets lost in the dark. We’ll see how three works in practice; there’s a set of six more raw cells lying in wait.
The new batteries produced these results on their first two charge-discharge cycles:
Sony NP-FS11 2011 Packs – First Charges
One battery didn’t come up to speed on the first charge, but after that they’re all pretty close.
These were cheap-after-rebate phones with 2/3 AA NiCd cells that lasted nigh onto five years. We rarely talk on the phone and even more rarely use these, so they’re on the dreaded continuous trickle charge and low usage cycle that kills rechargeable batteries. Of course, they’ve been sitting there for five years…
The rebuild was no big deal, although I had to replace the original 360 mAh NiCd cells with 650 mAh NiMH cells (with tabs) because that’s what’s available nowadays. The trickle rate will be even lower relative to the capacity, of course, which may or may not be a Bad Thing.
The packs contained a simple fuse consisting of a thinned section of the usual nickel strap connecting two cells, covered with a fiberglass sleeve under the shrink overwrap. For lack of anything smarter, I harvested the fuse and soldered it in the new pack. although the risk of a catastrophic short seems fairly low:
NiCd pack with thin-wire fuse
The final result looks about as you’d expect, complete with obligatory Kapton tape wrap:
Ativa phone – rebuilt battery
The old pack is kaput and new pack delivers pretty nearly its rated capacity at an arbitrary 550 mA discharge (which is, admittedly, a bit stiff for the old pack):
Ativa phone battery tests
That takes care of one phone… the other one’s probably in the same condition, so I have enough cells to rebuild it, too.
Just fielded a call from Credit Card Services that got all the way to 6:35 before the final disconnection!
Based on the conversation, we have a few more details:
The slimeball outfit identifying itself as Credit Card Services turns out to be a wholesale demon-dialing operation, which leads one to wonder why the FTC can’t figure this out and take some action. I mean, sheesh, CCS must represent a substantial fraction of the total voice phone call traffic; a few honeytrap numbers should be productive.
Anyhow, when you answer the phone and “press 1 to speak with an associate”, CCS farms the call out to a variety of back-end operations that evidently pay for live prospects (i.e., suckers). In this case, I was talking with someone working for “Client Services”; she was remarkably friendly and patient, which suggests she’s very new to this game.
The minimum balance they’re interested in has dropped to $3k. Used to be $4k; must be a sign of the times.
She wasn’t representing a loan operation, but was quite hazy about the details of how her organization would reduce my loan rates, other than that they “worked with the lenders” to that end. I pointed out that, while I wasn’t mad at her, she should understand that I’m reluctant to discuss my financial affairs with someone who really couldn’t describe the proposition in any detail.
She said that she could “do her best” to get me off the Client Services calling list, but that would have no effect on further calls from Credit Card Services, as other companies would be paying for those calls. She had no idea why “pressing 3 to discontinue further calls” didn’t work, of course.
So I asked if she had a supervisor that might be able to explain how the whole operation worked, she said she’d try to find one, and the next minute produced the usual clunks and tinks that presage a dropped call.
Perhaps the pleasant voices are “make money at home” suckers fronting for the loan sharks?
If you have a landline telephone number, you’ve probably been robo-called by “Rachael” from “Credit Card Services” with an offer to lower your credit card rates. She gives you two options:
Press 1 to speak with a live operator
Press 3 (or, sometimes, 2) to prevent further calls
I presume you’ve discovered that pressing 3 has no effect.
We don’t have a pre-existing business relationship with CCS
They use a robo-dialer
Pressing 3 (or whatever) doesn’t discontinue the calls
Their caller ID is spoofed
Rather than get mad, play along. CCS obviously preys on suckers willing to read off their credit card information to total strangers, so you can retaliate by stringing them along as far as possible, thus increasing their cost-per-sucker. Admittedly, their “agents” are (at best) minimum-wage slaves, which means you’re messing with their income stream, but after the first few months it becomes pretty obvious that the calls will never stop and you may as well roll with the punch.
Suggested topics, all presented in a slow monotone with long pauses:
Making sure they’re not associated with any of your credit cards (they aren’t)
Understanding whether they’re offering a loan to pay off your cards (they lie)
Asking for a callback number in case the call gets dropped (it’ll be a junk number)
They expect a minimum $4k account balance with the usual usurious credit card rates. Getting them to admit any of that requires carefully paced inquiry, because their script requires getting my balance before they devote any more time to me. I haven’t fed them any (totally bogus) numbers yet, but that may be the only way to get beyond the preliminaries.
Topics I’ll investigate in upcoming calls:
Their current interest rate
The repayment schedule
What they hold as collateral
How’s the weather where they are (it’ll be terrible here, for sure)
Thus far, I’ve discovered that any mention of these topics produces an instant disconnect:
Why pressing 3 does not discontinue further calls
Inquiring about their company mailing address
Asking to speak with a supervisor
Whether lying to strangers all day affects their personal relationships
My record so far is 3:05 from picking up the phone, which includes the recorded message and a bit of hold music.
Cleaned the gutters a while ago and the shingle fungus is getting worse: more sites and more stains. I sprized some general-purpose fungicide on the area over the kitchen:
Shingle fungus – east slope
And down the valley between the north and east slopes:
Shingle fungus – north and east slopes
We’ll see what happens by next spring; I hope the larger moss clumps will take the hint.
However, that short length of copper wire seems to be improving things. Here’s the before:
Copper effect on roof discoloration
Compared with the current state, from a different spot:
Shingle fungus – below Cu wire
The intense streaks have vanished, leaving a uniform lighter gray layer, and the upper area near the wire looks, mmm, less awful than the lower areas. I think running copper wire or zinc strips (which I have not found at the big box stores) along the ridge vent will do wonders, although I’m not sure how to anchor either one along the hip joints between the other slopes.