Sena PS410 Serial Server: socat and minicom

Per the socat man page:  “Socat … establishes two bidirectional byte streams and transfers data between them”. Using it to connect minicom to the HP Z3801 (PDF user manual) GPS receiver’s serial port on the PS410 serial server goes like this:

socat pty,link=/tmp/z3801 tcp: &

The 7003 designates the network port corresponding to serial port 3 on the PS410. The PS410 lets you give its ports any numbers you like, but that way lies madness.

You may want to run socat in a separate terminal window for easy monitoring (use -d -d for more details) and restarting. The PS410 closes all its network connections when updating any configuration values, pushing any ongoing conversations off the rails. Of course, one doesn’t update the configuration very often after getting it right.

It produces a device with permissions just for you:

lrwxrwxrwx 1 ed ed 10 Mar 17 18:45 z3801 -> /dev/pts/2

Whereupon you aim minicom (or whatever you like) at the device:

minicom -D /tmp/z3801

And It Just Works.

The PS410 serial port configuration:

Port 3 - Z3801 serial config
Port 3 – Z3801 serial config

The default Z3801 serial port setup seems to be 19200, 7 data, odd parity. I vaguely recall some serial port hackage a long time ago, with the details buried in my paper (!) notes.

Leaving the Inter Character Timeout at the default 0 creates a blizzard of network activity. Setting it to 10 ms produces slight delays during the full-screen (on an 80 character x 24 line green screen monitor, anyway) status display:

Z3801 system status
Z3801 system status

I inadvertently turned off the UPS powering the thing and the double-oven clock oscillator takes days to restabilize; the Holdover Uncertainty has been dropping slowly ever since.

Verily, it is written that a man with two clocks never knows what time it is. When one of them is a Z3801, the man has no doubt which clock is correct.

MPCNC: USB Camera Alignment

Adding a lock screw to the camera mount stabilized the camera-to-spindle offset enough to make calibration meaningful. Mark the spot directly under the camera:

bCNC - Camera - hot glue align
bCNC – Camera – hot glue align

Then mark the spot directly under the spindle, perhaps by poking a small cutter into the tape, measure the XY distances between the two center points, and use bCNC’s camera registration process to set the camera offset.

With those numbers in place, switching to the tool view (the green button with the end mill to the right in the ribbon bar) puts the camera at the spindle location:

bCNC - Spindle - hot glue align
bCNC – Spindle – hot glue align

The view from outside shows the relation between those two pieces of tape:

MPCNC - USB camera-to-spindle alignment
MPCNC – USB camera-to-spindle alignment

Now I can align the camera view to a fixture position and be (reasonably) sure the spindle will automagically align to the same XY coordinate when I switch to the “tool” view. Seems to work well in preliminary tests, anyhow.

MPCNC: USB Camera Mount With Lock Screw

It turned out the previous version of the USB camera mount lacked sufficient griptivity to hold the ball’s position against even moderate bumps, so the upper “half” is now tall enough to hold a lock screw directly over the ball:

MPCNC - USB Camera mount - lock screw - Slic3r
MPCNC – USB Camera mount – lock screw – Slic3r

It doesn’t look much different:

MPCNC - USB Camera Mount - lock screw
MPCNC – USB Camera Mount – lock screw

A view from the other side:

USB Camera - lock screw mount
USB Camera – lock screw mount

The previous iterations used Genuine 3M foam tape, which seemed too flexy for comfort. This one sits on a bed of hot melt glue and is absolutely rigid. We’ll see how long it survives.

Tightening the cap screw requires needle-nose pliers, because the whole affair has no room for a hex key.

The OpenSCAD source code as a GitHub Gist:

// MPCNC USB Camera Mount
// Ed Nisley KE4ZNU - 2018-02-22
Layout = "Build"; // Build, Show
/* [Extrusion] */
ThreadThick = 0.25; // [0.20, 0.25]
ThreadWidth = 0.40; // [0.40]
/* [Hidden] */
Protrusion = 0.1; // [0.01, 0.1]
HoleWindage = 0.2;
inch = 25.4;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
ID = 0;
OD = 1;
//- Adjust hole diameter to make the size come out right
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);
//- Dimensions
WallThick = 3.0; // minimum thickness / width
CameraStalk = [6.0 + 1.0,10.0 + HoleWindage,4.0]; // stalk OD, ball OD, stalk length
CameraAngle = -5; // stalk tilt, negative = downward
Screw = [3.0,7.0,25.0]; // holding it all together, OD = washer
Insert = [3.0,4.4,4.5]; // brass insert
Pusher = Insert[LENGTH] / 2; // plastic locking snippet
UpperThick = IntegerMultiple(CameraStalk[OD]/2 + Insert[LENGTH] + Pusher + WallThick,ThreadThick);
LowerThick = Screw[LENGTH] - UpperThick;
MountBlock = [24.0,20.0,LowerThick + UpperThick];
echo(str("Block: ",MountBlock));
NumSides = 6*4;
// Define shapes
// Camera mount, enlongated for E-Z differencing
// Origin at center of ball, stalk along +X
module Camera() {
union() {
rotate([0,90 - CameraAngle,0])
// Mount block with all the cutouts
// Ball centerline on XY plane = block split line
module Mount(Half="All") {
Rounding = 2.0; // corner radius
ZShift = // block shift to remove unwanted half
(Half == "Upper") ? -MountBlock.z/2 - 0*UpperThick :
(Half == "Lower") ? MountBlock.z/2 + 0*LowerThick :
2*MountBlock.z; // ... want both halves, remove none
difference() {
for (i=[-1,1], j=[-1,1]) {
translate([i*(MountBlock.x/2 - Rounding),j*(MountBlock.y/2 - Rounding),(UpperThick - Rounding)])
translate([i*(MountBlock.x/2 - Rounding),j*(MountBlock.y/2 - Rounding),-(LowerThick - Rounding)])
for (j=[-1,1])
translate([-MountBlock.x/4,j*MountBlock.y/4,-(LowerThick + Protrusion)]) {
PolyCyl(Insert[OD],Insert[LENGTH] + Protrusion,6);
translate([MountBlock.x/2 - (CameraStalk[OD]/2 + CameraStalk[LENGTH]),0,0]) {
translate([0,0,UpperThick - (Insert[LENGTH] + WallThick)])
PolyCyl(Insert[OD],Insert[LENGTH] + WallThick,6);
// Build it
if (Layout == "Show")
if (Layout == "Build") {

MPCNC: Makerbot-style Endstop Switch Spring Constant

Using a lever-arm switch as a tool length probe works surprisingly well:

MPCNC Tool Length Probe - Plotter Pen
MPCNC Tool Length Probe – Plotter Pen

However, probing a pen mounted in a compliant holder means the actual trip point depends on the relative spring constants. Having measured the pen holder’s 100 g/mm spring constant by poking a scale with the pen, I did much the same thing with the endstop Z-axis Autolevel probe:

IMG_20180305_161831 - MPCNC - Z Autolevel probe force.jpg

Which produced a similar graph:

MB Endstop Switch - spring constant
MB Endstop Switch – spring constant

The force increases linearly at 30 g/mm up to the trip point, drops by maybe 16 grams, then increases linearly again.

Obviously, the “constant” applies only to switches on MBI-style endstops in the lot I happen to have, but given the ubiquity of parts from the usual eBay sellers, any identical lever switches may have the same “constant”:

Endstop lever switch - detail
Endstop lever switch – detail

Your mileage will vary, fer shure.

Poking a pen into a similar switch used as a tool setter means the Z-axis coordinate of the trip point will depend on the opposing springs. That’s unlike the situation with a cutter mounted in the DW660 spindle, which (by definition) shouldn’t move in response to the pressure from a little bitty switch.

Eyeballing the graph, the switch travels 2.2 mm to the trip point, where it exerts 64 g of force. The pen holder opposes that force and therefore deflects (64 g) / (100 g/mm) = 0.64 mm just before the switch trips: the trip point will be the same as with a rigid tool, but the tool’s Z axis coordinate will be 0.64 mm lower.

I’d been touching off pens in the springy holder, with enough pressure to draw a decent line. Setting Z=0 with the holder deflected upward by 0.3 mm means the pen first touches the height probe at Z=+0.3 and the switch trips at Z=-0.3 mm (-ish), making the force on the paper 60 g, rather than the 30 g I expected.

I think the pen plots worked out pretty well, despite not getting the numbers and, thus, pen positions, quite right.

Baofeng BL-5 Pack Rebuild

The 18650 cell protection PCBs with 8205 ICs arrived and seemed small enough to simply tuck into the gap between the rounded cells in the second Baofeng BL-5 pack:

Baofeng BL-5 - new protection PCB - wiring 1
Baofeng BL-5 – new protection PCB – wiring 1

For whatever it might be worth, you’re looking at the only Baofeng battery pack containing an actual 10 kΩ thermistor, harvested from the benchtop Tray of Doom:

Baofeng BL-5 pack - thermistor
Baofeng BL-5 pack – thermistor

Unfortunately, the components on the PCB stuck up a bit too far from the cell surface and held the lid just slightly proud of the case. Applying pressure to lithium cells being a Bad Idea, I rearranged the layout by flipping the cells over, tucking the PCB components between the cells, and connecting everything with nickel tape instead of insulated wires:

Baofeng BL-5 - new protection PCB - wiring 2
Baofeng BL-5 – new protection PCB – wiring 2

The snippets of manila paper and Kapton tape hold things apart and together, as needed. Looks ugly, fits better.

Pop it in the charger to reset the protection PCB lockout and it’s all good again.

Baofeng BL-5 Battery Pack Base Dimensions

My original idea for the APRS + voice gadget was a snap-in battery pack replacement holding the circuit boards and connected to an external battery pack. A trio of dead Wouxun radios, plus the ready availability of 18650 lithium cells, suggested putting two cells in the backpack, along with the circuitry, and skipping the external pack.

Here’s the base of a Baofeng BL-5 pack overlaid with a 1 mm grid:

Baofeng BL-5 - Base with mm grid overlay
Baofeng BL-5 – Base with mm grid overlay

The grid is parallel to the case body and centered left-to-right, with a Y grid line set at the front face of the pack, where it’s also flush with the lid surface. You can read off the coordinates of all the points, feed them into your CAD model, and maybe, with a bit of care, get something 3D-print-able.

Haven’t used it yet, but it’s bound to come in handy at some point.