Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.
In 1991 we lived in Tolland CT, where I took one picture of a maple twig every week:
This slideshow requires JavaScript.
That was with a film camera, of course, with negatives. I assembled the printed images into a poster and eventually (perhaps in 2001) scanned / digitally photographed them four-at-a-time, saved the result as a 330 MB Photoshop file with one 2×2 group in each of 13 layers (there are 50 images, probably because vacations), and burned that to a CD.
All I can say: it must have made sense at the time.
Anyhow, here in the future, I found that CD in a pile destined for the shredder, which shouldn’t ought to happen without some attention.
Here’s how I extracted the separate images from that file into standalone JPEGs, cropped them to a uniform size, and smushed them to suitably low quality:
convert A\ Year\ in\ the\ Life\ of\ Tolland\ CT\ -\ 1991.psd -quality 95 Tolland-1991-%02d.jpg
for f in {01..13} ; do convert Tolland-1991-$f.jpg -crop "1212x1775+0+0" img-$f-0.jpg ; done
for f in {01..13} ; do convert Tolland-1991-$f.jpg -crop "1212x1775+1212+0" img-$f-1.jpg ; done
for f in {01..13} ; do convert Tolland-1991-$f.jpg -crop "1212x1775+0+1775" img-$f-2.jpg ; done
for f in {01..13} ; do convert Tolland-1991-$f.jpg -crop "1212x1775+1212+1775" img-$f-3.jpg ; done
for f in {01..13} ; do for g in {0..3} ; do convert img-$f-$g.jpg -crop "1100x1650+50+50" out-$f-$g.jpg ; done ; done
sn=1 ; for f in {01..13} ; do for g in {0..3} ; do printf -v dn 'Tolland-1991-Maple-%02d.jpg' "$(( sn++ ))" ; convert img-$f-$g.jpg -crop "1100x1650+50+50" +repage -rotate 90 -define jpeg:extent=200KB $dn ; done ; done
Then WordPress assembles the 50 images into a slide show.
Of course, it didn’t go quite as smoothly as all that, but it took maybe half an hour of fiddling to get it right by iterating on the commands until I liked the results. One might tweak the exposures and suchlike, but that’s in the nature of fine tuning.
Although it’s rated to 500 V, it violates the fundamental principle of high-voltage electronics debugging:
Always keep one hand in your pocket!
The scorched and truncated probe tip on the “ground wire” shows Phil slipped at least once:
Beckman DM73 – probe tip
After far too long, I sacrificed a black multimeter probe from the heap, soldered an alligator clip on the end, and, henceforth, will use it appropriately. Mostly, I never do any high-voltage work, but you never know.
I suppose I should splice that nice black probe onto the end of the Beckman wire for low-voltage work…
The Sony HDR-AS30V has extremely high audio gain, which is precisely what you need for the mic on an action camera. It sends that audio, along with the video, through its HDMI output, so when you drive a display from the camera in enclosed space, the audio is REALLY LOUD and causes severe feedback. For obscure reasons, given the staggering cost of the venue’s AV system, there’s no way to mute the audio channel of the video input when you’re also using a mic attached to someone giving a presentation.
The obvious solution, a shorted jumper (formerly an earbud plug) in the external mic jack, looked like this:
Sony HDR-AS30V – Dummy external mic
Contrary to what I expected, the camera doesn’t disable the internal mic with the jumper in place. The amp probably uses an analog multiplexer, rather than a mechanical switch, and even an off-channel isolation of, say, 76 dB (from the MAX4544 spec, for example) isn’t enough to completely mute the mic. You could, given sufficient motivation, measure the actual isolation, but the surviving audio isn’t subtle at all.
The not-obvious solution turned out to be putting the camera into either single or interval photo mode, rather than the movie mode I use for bike rides. It seems that when the video format doesn’t require audio, the camera either disables the audio inputs or (more likely) just doesn’t include audio data in the HDMI output.
Which produces exactly what I want: a video output with no accompanying audio.
Recently, the eye cups became difficult to pull out. The problem seemed to lie in the seal around the exterior of each tube, rather than with the internal mechanism, so I eased the tiniest possible drop of clock oil into each gap, spun the tubes, cycled them in-and-out, and wiped off essentially all of the oil as it spread over the exterior of the tubes.
The eye cups work fine again!
Frankly, I felt a like a Visigoth upgrading the Large Hadron Collider, but I trusted those old-school Leitz engineers would protect their optics from everything happening outside the sealed tubes.
For reasons not relevant here, I need a tripod mount for the Sony AS-30V that’s not quite so constraining as Sony’s Official skeleton mount + right-angle tripod bracket:
Sony HDR-AS30V – skeleton tripod mount
I must run a cable from the micro-HDMI port behind the hatch on the bottom of the camera to a display, but the Sony mount puts the hatch directly over the tripod platform and handle. Reversing the camera points it toward the handle, which then appears in the camera’s not-quite-fisheye view. Flipping the camera upside down sends the cable out the top, where it will put what I consider undue stress on the smallest high-density connector on any of my gadgets.
This Thingiverse model by maxspongebob is called a “Windshield Mount“, but has approximately the right features:
Sony HDR-AS30V holder – on tripod
The weird T-shaped dingus adapts micro- and mini-HDMI sockets to an ordinary HDMI cable (HDMI connector Types D, C, and A, respectively), serving as a placeholder for the yet-to-arrive 15 foot (probably 4.5 meter) cable.
The mount isn’t designed for easy 3D printing, as it includes thin walls with chamfered edges, close tolerances, and aggressive bridging in dimension-critical areas. The first attempt failed when the minimal footprint (you’re looking at it in the picture above) pulled off the platform when the nozzle hit the lower bridge in the battery compartment:
Sony HDR-AS30V holder – failed print
Surrounding the first layer with a 5 mm brim provided enough traction to finish the whole thing:
Sony HDR-AS30V holder – on platform
You can see some droopy threads across the openings; PETG bridges reasonably well, but the chamfers don’t provide good anchors. The opening for the camera hatch (on the far right rear) turned out slightly too short or, perhaps, the camera doesn’t seat quite far enough forward, which required some abrasive adjustment to accommodate the hatch.
For unknown reasons, the top end of the battery compartment has a trapezoidal bridge:
Sony HDR-AS30V holder – trapezoidal bridge – Slic3r preview
Which simply cannot be printed:
Sony HDR-AS30V holder – internal bridge failure
Cutting those threads out with an Xacto knife solved that problem.
The mount attaches to the tripod with a 1/4-20 nut trapped behind the hole next to the battery compartment. I grabbed an ordinary steel nut in a long normally closed tweezers, heated it over a butane lighter flame, threaded it onto a bolt stuck through the hole, and pulled it securely into the trap with exactly zero drama.
It has a very, very snug fit around the camera and battery that’s much better than a loose & floppy fit: there’s no positive retention latch.
This will serve as a prototype to see if the whole project works. If so, I’ll lash something together in OpenSCAD that should print a bit better, even if it looks like my usual brackets…
A trio of N2O cartridges / capsules made their way into the Basement Laboratory and cried out to be fitted with fins:
N2O Capsule Fins – installed
My original model tinkered up a cartridge from solid object primitives, but I’ve since discovered that cheating produces a much better and faster and easier result for cylindrical objects:
N2O Capsule – solid model – bottom view
The trick is getting an image of the original object from the side, taken from far enough away to flatten the perspective:
N2O capsule – side view
Then overlay and scale a grid to match the actual length:
N2O capsule – grid overlay
The grid has 1 mm per minor square, centered along the cartridge’s axis, and zeroed at the tip; I rotated the cartridge image by half a degree to line it up with the grid.
Print it out on actual paper so you can eyeball the measurements and write ’em where you need ’em:
N2O capsule – grid overlay – printed
Which becomes an OpenSCAD polygon definition:
RADIUS = 0; // subscript for radius values
HEIGHT = 1; // ... height above Z=0 at seal flange
//-- N2O 8 g capsule
CartridgeOutline = [ // X values = measured radius, Y as distance from tip
[0.0,0.0], // 0 cartridge seal tip
[2.5,0.1], // 1 seal disk
[3.5,0.5],[4.0,1.0], // 2 tip end
[4.2,2.0],[4.3,3.0], // 4 tip
[4.3,6.0], // 6 chamfer
[4.5,8.0], // 7 taper
[4.9,9.0], // 8
[5.5,10.0], // 9
[6.0,11.0], // 10
[6.7,12.0], // 11
[7.1,13.0], // 12
[7.5,14.0], // 13
[8.0,15.0], // 14
[8.4,16.0], // 15
[8.8,17.0], // 16
[9.0,18.0],[9.0,58.0], // 17 body
[0.0,65.0] // 19 dummy end cone
];
TipLength = CartridgeOutline[6][HEIGHT];
TipOD = 2*CartridgeOutline[5][RADIUS];
BodyOD = 2*CartridgeOutline[17][RADIUS];
BodyOAL = CartridgeOutline[19][HEIGHT];
Because the rounded end of the cartridge doesn’t matter, I turned it into a cone.
Which then punches a matching dent in the fin structure:
Gas Capsule Fins – Slic3r preview
The lead picture doesn’t quite match the Slic3r preview, as I found the single-width diagonal fins weren’t strong enough. Making them two (nominal) threads wide lets Slic3r lay down three thinner threads in the same space:
Gas Capsule Fins – thicker – Slic3r preview
That’s letting Slic3r automagically determine the infill and perimeter thread width to make the answer come out right. As nearly as I can tell, the slicing algorithms have become smart enough to get the right answer nearly all of the time, so I can-and-should relinquish more control over the details.
The OpenSCAD source code:
// CO2 capsule tail fins
// Ed Nisley KE4ZNU - October 2015
Layout = "Build"; // Show Build FinBlock Cartridge Fit
//-------
//- Extrusion parameters must match reality!
// Print with +0 shells and 3 solid layers
ThreadThick = 0.25;
ThreadWidth = 0.40;
HoleWindage = 0.2;
Protrusion = 0.1; // make holes end cleanly
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
//-------
// Capsule dimensions
CartridgeSides = 12*4; // number of sides
RADIUS = 0; // subscript for radius values
HEIGHT = 1; // ... height above Z=0 at seal flange
//-- N2O 8 g capsule
RW = HoleWindage/2; // enlarge radius by just enough
CartridgeOutline = [ // X values = measured radius, Y as distance from tip
[0.0,0.0], // 0 cartridge seal tip
[2.5 + RW,0.1], // 1 seal disk
[3.5 + RW,0.5],[4.0 + RW,1.0], // 2 tip end
[4.2 + RW,2.0],[4.3 + RW,3.0], // 4 tip
[4.3 + RW,6.0], // 6 chamfer
[4.5 + RW,8.0], // 7 taper
[4.9 + RW,9.0], // 8
[5.5 + RW,10.0], // 9
[6.0 + RW,11.0], // 10
[6.7 + RW,12.0], // 11
[7.1 + RW,13.0], // 12
[7.5 + RW,14.0], // 13
[8.0 + RW,15.0], // 14
[8.4 + RW,16.0], // 15
[8.8 + RW,17.0], // 16
[9.0 + RW,18.0],[9.0 + RW,58.0], // 17 body
[0.0,65.0] // 19 dummy end cone
];
TipLength = CartridgeOutline[6][HEIGHT];
TipOD = 2*CartridgeOutline[5][RADIUS];
CylinderBase = CartridgeOutline[17][HEIGHT];
BodyOD = 2*CartridgeOutline[17][RADIUS];
BodyOAL = CartridgeOutline[19][HEIGHT];
//-------
// Fin dimensions
FinThick = 1.5*ThreadWidth; // outer square
StrutThick = 2.0*ThreadWidth; // diagonal struts
FinSquare = 1.25*BodyOD;
FinTaperLength = sqrt(2)*FinSquare/2 - sqrt(2)*FinThick - ThreadWidth;
FinBaseLength = 0.7 * CylinderBase;
FinTop = 0.9*CylinderBase;
//-------
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) {
Range = floor(50 / Space);
for (x=[-Range:Range])
for (y=[-Range:Range])
translate([x*Space,y*Space,Size/2])
%cube(Size,center=true);
}
//-------
// CO2 cartridge outline
module Cartridge() {
rotate_extrude($fn=CartridgeSides)
polygon(points=CartridgeOutline);
}
//-------
// Diagonal fin strut
module FinStrut() {
intersection() {
rotate([90,0,45])
translate([0,0,-StrutThick/2])
linear_extrude(height=StrutThick)
polygon(points=[
[0,0],
[FinTaperLength,0],
[FinTaperLength,FinBaseLength],
[0,(FinBaseLength + FinTaperLength)]
]);
translate([0,0,FinTop/2])
cube([2*FinSquare,2*FinSquare,FinTop], center=true);
}
}
//-------
// Fin outline
module FinBlock() {
$fn=12;
render(convexity = 4)
union() {
translate([0,0,FinBaseLength/2])
difference() {
intersection() {
minkowski() {
cube([FinSquare - 2*ThreadWidth,
FinSquare - 2*ThreadWidth,
FinBaseLength],center=true);
cylinder(r=FinThick,h=Protrusion,$fn=8);
}
cube([2*FinSquare,2*FinSquare,FinBaseLength],center=true);
}
difference() {
cube([(FinSquare - 2*FinThick),
(FinSquare - 2*FinThick),
(FinBaseLength + 2*Protrusion)],center=true);
for (Index = [0:3])
rotate(Index*90)
translate([(FinSquare/2 - FinThick),(FinSquare/2 - FinThick),0])
cylinder(r=2*StrutThick,h=(FinBaseLength + 2*Protrusion),center=true,$fn=16);
}
}
for (Index = [0:3])
rotate(Index*90)
FinStrut();
rotate(180/12)
cylinder(d=IntegerMultiple(TipOD + 6*ThreadWidth,ThreadWidth),h=TipLength);
}
}
//-------
// Fins
module FinAssembly() {
difference() {
FinBlock();
translate([0,0,2*ThreadThick]) // add two layers to close base cylinder
Cartridge();
}
}
module FinFit() {
translate([0,0.75*BodyBaseLength,2*ThreadThick])
rotate([90,0,0])
difference() {
translate([-FinSquare/2,-2*ThreadThick,0])
cube([IntegerMultiple(FinSquare,ThreadWidth),
4*ThreadThick,
1.5*BodyBaseLength]);
translate([0,0,5*ThreadWidth])
Cartridge();
}
}
//-------
// Build it!
ShowPegGrid();
if (Layout == "FinStrut")
FinStrut();
if (Layout == "FinBlock")
FinBlock();
if (Layout == "Cartridge")
Cartridge();
if (Layout == "Show") {
FinAssembly();
color("LightYellow") Cartridge();
}
if (Layout == "Fit")
FinFit();
if (Layout == "Build")
FinAssembly();