Mini-Lathe Tailstock Way Repair

After the faceplant caused by the crappy compound way finishing, I decided to try repairing the tailstock ways as a means of gaining experience before tackling the real problem. The general idea is to see whether filling the gouges with epoxy will suffice.

I’m using good ol’ JB Weld steel-filled epoxy, rather than graphite / molybdenum disulfide loaded epoxy, mostly because:

  • I have it on the shelf
  • This is a non-sliding joint
  • My technique needs polishing, too

The key point: the tailstock is (astonishingly) well aligned and, if I can manage to not change how it sits on the lathe bed, this should be a zero-impact operation. Scraping / filing / fiddling with the high spots will change the alignment; I expect I must eventually do such things; this represents a first pass at the problem.

Applying a fat blue Sharpie to the tailstock ways:

Tailstock way repair - blue Sharpie
Tailstock way repair – blue Sharpie

After sliding the tailstock back and forth a few times, the remaining blue shows where the ways did not make contact. Those shiny and silvery spots rubbed against the lathe bed ways.

The flat way looked like this:

Tailstock way repair - flat contacts
Tailstock way repair – flat contacts

The patch along the upper-left edge and the small dot near the upper-right corner are the only contact points across the entire flat.

The outside of the V groove:

Tailstock way repair - outer V contacts
Tailstock way repair – outer V contacts

As nearly as I can tell, that’s actually a reasonably flat and well-aligned surface, with small contact points scattered all over. Granted, there’s a larger contact patch to the left and less to the right.

The inside of the V groove:

Tailstock way repair - inner V contacts
Tailstock way repair – inner V contacts

There’s a single point near the top left, another over on the right, and that’s about it.

I cleaned the tailstock ways with acetone to get rid of the Sharpie / grease / oil / whatever. Under normal circumstances you’d roughen the surface to give the epoxy something to grip, which definitely seemed akin to perfuming a lily.

To prevent permanently affixing the tailstock to the lathe, some folks put a generous layer of oil / graphite / soot / release agent on the lathe bed ways. I used some 3 mil = 0.08 mm Kapton tape, figuring an impervious layer would pretty much guarantee I could get the tailstock off again, no matter what.

So, we begin.

Butter up the tailstock ways with epoxy and smoosh into place atop the Kapton:

Tailstock way repair - V groove on tape
Tailstock way repair – V groove on tape

Make sure the tailstock remains well-seated where it should be:

Tailstock way repair - weights
Tailstock way repair – weights

Do other things for 24 hours while the epoxy cures, pry the tailstock loose by hammering The Giant Prying Screwdriver between the lathe bed and the underside of the tailstock (just right of the V-groove, where nothing slides on the bed, but I did use a bit of plastic as a shield), chip off excess epoxy, clean things up, etc, etc.

This time, I applied Sharpie to the lathe bed, then slid the tailstock back & forth a few times. As a result, the blue areas now show the contact patches and the gray areas just slid by without touching.

The flat way looks pretty good:

Tailstock way repair - flat epoxy blued
Tailstock way repair – flat epoxy blued

That round dot over on the right seems to be a steel protrusion; I think it’s part of the same lump appearing in the “before” picture above. That rather sharp point seems to have indented the tape and produced a low area in the epoxy around it, which may not matter much: it was the only contact point before I did this.

The V groove isn’t anywhere near perfect:

Tailstock way repair - V groove epoxy blued
Tailstock way repair – V groove epoxy blued

On the upside, the ways have much, much larger contact patches spread across nearly their entire lengths, which isn’t to be sniffed at.

While reassembling the tailstock, I added a pair of M6 washers above the clamp plate so it cleared the bed with the screw tightened into the cam-lock post:

Tailstock clamp plate - washers
Tailstock clamp plate – washers

Which definitely calls for a small bushing, of course. If you put a lockwasher under the screw head, it won’t clear the end of the bed casting. So it goes.

Another washer under the ram lock screw changed the phase enough to keep the knob out of the way in both the fully locked and unlocked positions:

Tailstock ram lock - added washer
Tailstock ram lock – added washer

I slobbered some Mobil Vactra #2 Sticky Way Oil (thanks, Eks!) on the bed ways, snuggled the tailstock in place, and wow does that thing move! Verily, it slides smoothly and clamps solidly in place: a tremendous improvement over the status quo ante.

Some observations…

  • The tape (perhaps the adhesive layer) produces a slightly textured epoxy surface
  • The tailstock way’s small contact points indented the tape, even though it’s only 3 mil thick
  • Filling the low areas in the way works well
  • The high areas may not have enough epoxy for good durability
  • I expect the epoxy will wear faster than steel, so contact should improve with time
  • This is not a permanent fix

What I’ll do differently next time…

  • Apply more epoxy to avoid those small gaps along the edges
  • Use a real release agent: smoothed in place, it might provide a better finish. Might not matter
  • Verify a good prying spot before epoxying, say, the compound

All in all, though, this worked much better than I expected!

Raspberry Pi 3: Disabling the Build-In WiFi

streaming media player in the Basement Laboratory Warehouse Wing has a concrete block wall between it and the WiFi router, so that even high(er)-gain USB antennas can’t grab enough signal for reliable streaming. After some fiddling, I snaked a cable from a hub, along the floor joints, to the Pi and declared victory. It turned out the Pi, an old Pi 1 Model B, had some trouble keeping up with the times, and I eventually swapped it for a Pi 3.

Forcing a static address for the wired port followed the now-standard recipe, with eth0 instead of wlan0 in /etc/dhcpcd.conf.

However, plugging a network cable into the Pi 3 then produces two network connections: the wired one I wanted and the aforementioned unreliable WiFi link through the built-in hardware. The only reliable way to turn off the WiFi connection seems to require applying The BFH through a line in /etc/rc.local:

sudo ifconfig wlan0 down

Removing my WiFi credentials from /etc/wpa_supplicant/wpa_supplicant.conf prevents the hardware from connecting before the hammer comes down.

And then it streams perfectly…

Rail Trail Blockage

This big branch must have landed with a mighty thump across the Maloney Road entrance to the Dutchess Rail Trail:

DCRT - Maloney Rd - tree down - 2017-02-20
DCRT – Maloney Rd – tree down – 2017-02-20

Yeah, some jerk ran a snowmobile up the slope around the tree, leaving a pile of dirt on the ramp. So it goes.

We took an alternate route, I emailed The Right Folks, and (most of) the tree vanished two days later; evidently, the property owner gets to deal with everything to the left of the line of trees.

Cheap WS2812 LEDs: Test Fixture Current

With the WS2812 test fixture neatly mounted, I plugged it into a six-port USB charger allegedly capable of supplying 2.4 A per port and captured a trace with nearly all 28 LEDs displaying full white:

WS2812 4x7 array - 200 mA VCC - all on
WS2812 4×7 array – 200 mA VCC – all on

At 200 mA/div, the top trace shows a bit under 1.2 A, a bit under the 1.68 A = 28 × 60 mA you’d expect; in round numbers, each RGB pixel draws 43 mA. Actually, the WS2812 specs don’t specify the maximum / typical LED current and, on belief and evidence, I doubt these units meet any particular specs you’d care to cite.

Also, the supply voltage (measured across the LED array “bus bar” wires) hits 3.37 V, well under the 5 V you’d expect from a USB charger and less than the 3.5 V called for by the WS2812 specs. Although the WS2812 nominally limits the LED current, there’s no telling how it varies with supply voltage.

A cheap USB 1 A wall-wart charger produced far more hash:

WS2812 4x7 array - 200 mA VCC - all on - cheap 1A wart - 20 uF
WS2812 4×7 array – 200 mA VCC – all on – cheap 1A wart – 20 uF

That’s with an additional 20 µF of tantalum capacitance across the power bus bars. The peak current looks like 1.4 A, with marginally more supply voltage at 3.56 V.

Bumping the trace speed shows the wall wart produces nasty current spikes, at what must be the poor thing’s switching speed, as it desperately tries to produce enough juice for the LEDs:

WS2812 4x7 array - 200 mA VCC 50 us - all on - cheap 1A wart - 20 uF
WS2812 4×7 array – 200 mA VCC 50 us – all on – cheap 1A wart – 20 uF

The step over on the right looks like a single RGB LED going dark, as it’s about 50 mA tall.

The output voltage doesn’t show the same spikes, so the LED array acts like a constant-voltage load. Given that the WS2812 probably connects all the LEDs pretty much straight across the supply, that’s not far from the truth: we’re looking at the forward drop of those blue LEDs.

Now, to let it cook away in the cool and the dark of the Basement Laboratory…

Cheap WS2812 LEDs: Test Fixture Mount

Mounting the ungainly WS2812 LED test fixture seemed like a Good Idea to keep the electricity out of the usual conductive litter:

WS2812 array test fixture - rear
WS2812 array test fixture – rear

The solid model shows more details:

LED Test Fixture - solid model
LED Test Fixture – solid model

The power wires along the array edges slide into the rear (thinner) slot, with enough friction from a few gentle bends to hold the whole mess in place.

The knockoff Arduino Nano rests on the recessed ledge in the pit, with M2 screws and washers at the corners holding it down (the PCB’s built-in holes might work with 1 mm or 0-90 screws, but that’s just crazy talk). I soldered the power wires directly to the coaxial jack pins under the PCB; they snake out to the LEDs through the little trench. There should be another cutout around the USB connector for in-situ programming, although the existing code works fine.

The front (wider) slot holds a piece of translucent white acrylic to diffuse the light:

WS2812 array test fixture - front flash
WS2812 array test fixture – front flash

It’s painfully bright: a few layers of neutral density filter would be appropriate for a desk toy.

The array runs hot enough at MaxPWM = 255 to produce a gentle upward breeze.

It looks even better without the flash:

WS2812 array test fixture - front dark
WS2812 array test fixture – front dark

You’ll find many easier ways to get RGB LED panels, but that’s not the point here; I’m waiting for these things to die an unnatural death.

The OpenSCAD source code as a GitHub Gist:

// LED Test Fixture
// Ed Nisley KE4ZNU - February 2017
ClampFlange = true;
Channel = false;
//- Extrusion parameters - must match reality!
ThreadThick = 0.25;
ThreadWidth = 0.40;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
Protrusion = 0.1;
HoleWindage = 0.2;
//- Screw sizes
ID = 0;
OD = 1;
Insert = [2.8,3.5,4.0]; // M2 threaded insert
ScrewOD = 2.0;
WasherOD = 5.0;
//- Component sizes
PCBSize = [18.0,43.5,1.6]; // microcontroller PCB
PCBClear = 2*[ThreadWidth,ThreadWidth,0]; // clearance around board
PCBShelf = [ThreadWidth,ThreadWidth,0]; // shelf under perimeter
PCBCavity = PCBSize - PCBShelf + [0,0,2.5]; // support shelf around bottom parts
LEDPanel = [70,40,4.0]; // lying flat, LEDs upward
LEDWire = [LEDPanel[0],LEDPanel[1] + 2*5.0,2.0]; // power wires along sides
Diffuser = [LEDPanel[0],LEDPanel[1] + 2*4.0,3.5];
echo(str("Diffuser panel: ",Diffuser));
WallThick = 8.0;
BaseThick = 3*ThreadThick + Insert[LENGTH] + PCBCavity[2];
Block = [3*WallThick + PCBSize[0] + LEDPanel[2] + Diffuser[2],
2*WallThick + IntegerMultiple(max(PCBSize[1],LEDWire[1]),5),
BaseThick + LEDPanel[0]];
echo(str("Block: ",Block));
CornerRadius = 5.0;
NumSides = 4*5;
//- 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);
//- Build it
difference() {
hull() // main block with rounded corners
for (i=[-1,1], j=[-1,1])
translate([i*(Block[0]/2 - CornerRadius),j*(Block[1]/2 - CornerRadius),,0])
translate([2*WallThick + PCBSize[0] - Block[0],
(Block[2]/2 + BaseThick)])
cube(Block + [0,2*Protrusion,0],center=true); // cut out over PCB
translate([WallThick + (PCBSize + PCBClear)[0]/2 - Block[0]/2,
0]) {
translate([0,0,(BaseThick + (Protrusion - PCBSize[2])/2)])
cube(PCBSize + PCBClear + [0,0,Protrusion],center=true); // PCB recess
translate([0,0,(BaseThick + (Protrusion - PCBCavity[2])/2)])
cube(PCBCavity + [0,0,Protrusion],center=true); // cavity under PCB
translate([PCBSize[0]/2 + WallThick/2 - Protrusion/2,PCBSize[1]/2 - 15/2,BaseThick - PCBCavity[2]/2 + Protrusion/2])
cube([WallThick + PCBShelf[0] + Protrusion,
15,PCBCavity[2] + Protrusion],center=true); // wiring cutout
for (i=[-1,1], j=[-1,1]) // screw inserts
translate([i*(PCBSize[0] + ScrewOD)/2,j*(PCBSize[1] + ScrewOD)/2,-Protrusion])
PolyCyl(Insert[OD],BaseThick + 2*Protrusion,6);
resize([2*Block[0],0,LEDPanel[0] + Protrusion]) // LED panel outline
translate([(LEDPanel[0] + Protrusion)/2,0,0])
cube(LEDPanel + [Protrusion,0,0],center=true);
translate([-Block[0]/2 + 2*WallThick + PCBSize[0] + LEDWire[2]/2 + 5*ThreadWidth,
0,BaseThick]) // LED wiring recess
translate([(LEDWire[0] + Protrusion)/2,0,0])
cube(LEDWire + [Protrusion,0,0],center=true);
translate([Block[0]/2 - Diffuser[2]/2 - 5*ThreadWidth,0,BaseThick]) // diffuser
translate([(Diffuser[0] + Protrusion)/2,0,0])
cube(Diffuser + [Protrusion,0,0],center=true);

Cheap WS2812 LEDs: Test Fixture

Given that I no longer trust any of the knockoff Neopixels, I wired the remaining PCB panel into a single hellish test fixture:

WS2812 4x7 LED test fixture - wiring
WS2812 4×7 LED test fixture – wiring

The 22 AWG wires deliver +5 V and Common, with good old-school Wire-Wrap wire passing to the four LEDs betweem them. The data daisy chain snakes through the entire array.

It seems only fitting to use a knockoff Arduino Nano as the controller:

WS2812 4x7 LED test fixture - front
WS2812 4×7 LED test fixture – front

The code descends from an early version of the vacuum tube lights, gutted of all the randomizing and fancy features. It updates the LEDs every 20 ms and, with only 100 points per cycle, the colors tick along fast enough reassure you (well, me) that the thing is doing something: the pattern takes about 20 seconds from one end of the string to the other.

At full throttle the whole array draws 1.68 A = 60 mA × 28 with all LEDs at full white, which happens only during the initial lamp test and browns out the supply (literally: the blue LEDs fade out first and produce an amber glow). The cheap 5 V 500 mA power supply definitely can’t power the entire array at full brightness.

The power supply current waveform looks fairly choppy, with peaks at the 400 Hz PWM frequency:

WS2812 4x7 array - 200 mA VCC
WS2812 4×7 array – 200 mA VCC

With the Tek current probe set at 200 mA/div, the upper trace shows 290 mA RMS. That’s at MaxPWM = 127, which reduces the average current but doesn’t affect the peaks. At full brightness the average current should be around 600 mA, a tad more than the supply can provide, but maybe it’ll survive; the bottom trace shows a nice average, but the minimum hits 4.6 V during peak current.

Assuming that perversity will be conserved as usual, none of the LEDs will fail for as long as I’m willing to let them cook.

The Arduino source code as a GitHub Gist:

// WS2812 LED array exerciser
// Ed Nisley - KE4ANU - February 2017
#include <Adafruit_NeoPixel.h>
// Pin assignments
const byte PIN_NEO = A3; // DO - data out to first Neopixel
const byte PIN_HEARTBEAT = 13; // DO - Arduino LED
// Constants
const unsigned long UpdateMS = UPDATEINTERVAL - 1ul; // update LEDs only this many ms apart minus loop() overhead
// number of steps per cycle, before applying prime factors
#define RESOLUTION 100
// phase difference between LEDs for slowest color
#define BASEPHASE (PI/16.0)
// LEDs in each row
#define NUMCOLS 4
// number of rows
#define NUMROWS 7
#define PINDEX(row,col) (row*NUMCOLS + col)
// Globals
// instantiate the Neopixel buffer array
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN_NEO, NEO_GRB + NEO_KHZ800);
uint32_t FullWhite = strip.Color(255,255,255);
uint32_t FullOff = strip.Color(0,0,0);
struct pixcolor_t {
byte Prime;
unsigned int NumSteps;
unsigned int Step;
float StepSize;
float TubePhase;
byte MaxPWM;
// colors in each LED
enum pixcolors {RED, GREEN, BLUE, PIXELSIZE};
struct pixcolor_t Pixels[PIXELSIZE]; // all the data for each pixel color intensity
unsigned long MillisNow;
unsigned long MillisThen;
//-- Figure PWM based on current state
byte StepColor(byte Color, float Phi) {
byte Value;
Value = (Pixels[Color].MaxPWM / 2.0) * (1.0 + sin(Pixels[Color].Step * Pixels[Color].StepSize + Phi));
// Value = (Value) ? Value : Pixels[Color].MaxPWM; // flash at dimmest points
// printf("C: %d Phi: %d Value: %d\r\n",Color,(int)(Phi*180.0/PI),Value);
return Value;
//-- Helper routine for printf()
int s_putc(char c, FILE *t) {
// Set the mood
void setup() {
digitalWrite(PIN_HEARTBEAT,LOW); // show we arrived
fdevopen(&s_putc,0); // set up serial output for printf()
printf("WS2812 array exerciser\r\nEd Nisley - KE4ZNU - February 2017\r\n");
/// set up Neopixels
// lamp test: run a brilliant white dot along the length of the strip
printf("Lamp test: walking white\r\n");
for (int i=1; i<NUMPIXELS; i++) {
strip.setPixelColor(NUMPIXELS - 1,FullOff);;
// fill the array, row by row
printf(" ... fill\r\n");
for (int i=0; i < NUMROWS; i++) { // for each row
for (int j=0; j < NUMCOLS; j++) {
// clear to black, column by column
printf(" ... clear\r\n");
for (int j=NUMCOLS-1; j>=0; j--) { // for each column
for (int i=NUMROWS-1; i>=0; i--) {
// set up the color generators
MillisNow = MillisThen = millis();
printf("First random number: %ld\r\n",random(10));
Pixels[RED].Prime = 11;
Pixels[GREEN].Prime = 7;
Pixels[BLUE].Prime = 5;
printf("Primes: (%d,%d,%d)\r\n",Pixels[RED].Prime,Pixels[GREEN].Prime,Pixels[BLUE].Prime);
unsigned int PixelSteps = (unsigned int) ((BASEPHASE / TWO_PI) *
RESOLUTION * (unsigned int) max(max(Pixels[RED].Prime,Pixels[GREEN].Prime),Pixels[BLUE].Prime));
printf("Pixel phase offset: %d deg = %d steps\r\n",(int)(BASEPHASE*(360.0/TWO_PI)),PixelSteps);
Pixels[RED].MaxPWM = 127;
Pixels[GREEN].MaxPWM = 127;
Pixels[BLUE].MaxPWM = 127;
for (byte c=0; c < PIXELSIZE; c++) {
Pixels[c].NumSteps = RESOLUTION * (unsigned int) Pixels[c].Prime;
Pixels[c].Step = (3*Pixels[c].NumSteps)/4;
Pixels[c].StepSize = TWO_PI / Pixels[c].NumSteps; // in radians per step
Pixels[c].TubePhase = PixelSteps * Pixels[c].StepSize; // radians per tube
printf("c: %d Steps: %5d Init: %5d",c,Pixels[c].NumSteps,Pixels[c].Step);
printf(" PWM: %3d Phi %3d deg\r\n",Pixels[c].MaxPWM,(int)(Pixels[c].TubePhase*(360.0/TWO_PI)));
// Run the mood
void loop() {
MillisNow = millis();
if ((MillisNow - MillisThen) > UpdateMS) {
unsigned int AllSteps = 0;
for (byte c=0; c < PIXELSIZE; c++) { // step to next increment in each color
if (++Pixels[c].Step >= Pixels[c].NumSteps) {
Pixels[c].Step = 0;
printf("Color %d steps %5d at %8ld delta %ld ms\r\n",c,Pixels[c].NumSteps,MillisNow,(MillisNow - MillisThen));
AllSteps += Pixels[c].Step; // will be zero only when all wrap at once
if (0 == AllSteps) {
printf("Grand cycle at: %ld\r\n",MillisNow);
for (int k=0; k < NUMPIXELS; k++) { // for each pixel
byte Value[PIXELSIZE];
for (byte c=0; c < PIXELSIZE; c++) { // ... for each color
Value[c] = StepColor(c,-k*Pixels[c].TubePhase); // figure new PWM value
// Value[c] = (c == RED && Value[c] == 0) ? Pixels[c].MaxPWM : Value[c]; // flash highlight for tracking
uint32_t UniColor = strip.Color(Value[RED],Value[GREEN],Value[BLUE]);
MillisThen = MillisNow;
view raw ArrayTest.ino hosted with ❤ by GitHub

Raspberry Pi Boot vs. Avahi vs. DHCP

Sometimes, one of our homebrew streaming media players will emerge from reset without starting up properly. The system board LEDs blink more-or-less normally, but the WiFi activity monitor seems … odd. This post documents the results of some exploratory surgery hinting at a possible solution.

I set the router’s DHCP server to assign a fixed IP address to each of our homebrew streaming media players based on its MAC address. That seemed less horrible than setting a static IP address in each player’s configuration, although I could see advantages to either approach. For streamer1, the player discussed here, the IP address is; that’s a non-routable address used only on our network behind the router.

During the Raspberry Pi’s boot, the default /etc/rc.local script finds and displays its IP address:

_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"

The /var/log/boot log showed this after one boot:

--- snippage ---
         Starting LSB: Raise network interfaces....
[  OK  ] Started LSB: Raise network interfaces..
         Starting ifup for wlan0...
[  OK  ] Started ifup for wlan0.
[  OK  ] Reached target System Initialization.
[  OK  ] Listening on Avahi mDNS/DNS-SD Stack Activation Socket.
[  OK  ] Reached target Sockets.
[  OK  ] Reached target Basic System.
         Starting Avahi mDNS/DNS-SD Stack...
         Starting Regular background program processing daemon...
[  OK  ] Started Regular background program processing daemon.
         Starting dhcpcd on all interfaces...
[  OK  ] Started Avahi mDNS/DNS-SD Stack.
[  OK  ] Started dhcpcd on all interfaces.
[  OK  ] Reached target Network.
         Starting /etc/rc.local Compatibility...
         Starting Permit User Sessions...
[  OK  ] Reached target Network is Online.
         Starting LSB: Start NTP daemon...
My IP address is
[  OK  ] Started Permit User Sessions.
connect: Network is unreachable
[  OK  ] Started /etc/rc.local Compatibility.
         Starting Terminate Plymouth Boot Screen...
         Starting Hold until boot process finishes up...

That mysterious IP address is a Link-local address, about which Wikipedia says: “If a host on an IEEE 802 (Ethernet) network cannot obtain a network address via DHCP, an address from to may be assigned pseudorandomly.”

So, having the router hand out IP addresses doesn’t quite work the way I expected. The Pi awards itself a link-local IP address before getting one from the DHCP server, presumably because the vast Linux startup Pachinko machine has a race condition. Alas, the pseudorandom LL address doesn’t fit in the network handled by the router: the Pi can’t connect to the network.

My code in /etc/rc.local starts the streaming player immediately after the default code displaying the IP address, thus joining the race condition: if the player starts up before the DCHP server assigns the proper IP address, it can’t connect to the music server out on the Interwebs. My code includes a retry loop with a five second delay which eventually connects, at least most of the time, but sometimes gets wedged.

The most reasonable fix seems to involve forcing a static address on each Raspberry Pi, so it can immediately connect to the network, without any negotiation, and get on with the business at hand.

Rather than configuring that in  /etc/network/interfaces as before, the New Hotness adds a stanza to  /etc/dhcpcd.conf:

interface wlan0
static ip_address=
static routers=
static domain_name_servers=

En passant, I killed off IPV6 with this line in /etc/sysctl.conf:


The router doesn’t support IPV6 and there’s no point in using it. Bonus: less log clutter. Double Bonus: startup happens faster!

All of which may help the NTP client update the system clock sooner, perhaps preventing time jumps like this:

2017-02-14 08:42:24,183 INFO: Player setup for: BR1
2017-02-14 08:42:24,184 INFO: Volume control knob: /dev/input/volume
2017-02-14 08:42:24,225 INFO: Starting mplayer on Ambient ->
2017-02-14 08:42:27,175 INFO: Track name: [Arcticology - Nocturnal Sounds]
2017-02-14 08:42:27,194 INFO: Track unmuted
2017-02-15 04:25:00,386 INFO: Track name: [Oöphoi - Suspended Matter]
2017-02-15 04:25:00,413 INFO: Track unmuted

The timestamps in the first five lines date back to the previous shutdown. The Pi remains plugged in and powered while it’s reset, which apparently preserves the system clock variables, albeit without a hardware clock ticking along: time stands still between shutdown and restart.

In this case, the IP address situation worked itself out before the player started, but the NTP clock reset on the sixth line happened at least three seconds after the log began.

This chunk of /var/log/syslog has more detail:

Feb 14 08:42:24 streamer1 dhcpcd[693]: wlan0: leased for 86400 seconds
Feb 14 08:42:24 streamer1 dhcpcd[693]: wlan0: adding route to
Feb 14 08:42:24 streamer1 dhcpcd[693]: wlan0: adding default route via
Feb 14 08:42:24 streamer1 avahi-daemon[387]: Registering new address record for on wlan0.IPv4.
Feb 14 08:42:24 streamer1 dhcpcd[693]: wlan0: deleting route to
Feb 14 08:42:24 streamer1 avahi-daemon[387]: Withdrawing address record for on wlan0.
Feb 14 08:42:24 streamer1 avahi-daemon[387]: Leaving mDNS multicast group on interface wlan0.IPv4 with address
Feb 14 08:42:24 streamer1 avahi-daemon[387]: Joining mDNS multicast group on interface wlan0.IPv4 with address
Feb 14 08:42:25 streamer1 dhcpcd[693]: wlan0: no IPv6 Routers available
Feb 14 08:42:25 streamer1 ntpd_intres[728]: DNS ->
Feb 14 08:42:25 streamer1 ntpd_intres[728]: DNS ->
Feb 14 08:42:25 streamer1 ntpd_intres[728]: DNS ->
Feb 14 08:42:25 streamer1 ntpd_intres[728]: DNS ->
Feb 14 08:42:26 streamer1 ntpd[720]: Listen normally on 6 wlan0 UDP 123
Feb 14 08:42:26 streamer1 ntpd[720]: Deleting interface #3 wlan0,, interface stats: received=0, sent=0, dropped=4, active_time=3 secs
Feb 14 08:42:26 streamer1 ntpd[720]: interface -> (none)
Feb 14 08:42:26 streamer1 ntpd[720]: interface -> (none)
Feb 14 08:42:26 streamer1 ntpd[720]: interface -> (none)
Feb 14 08:42:26 streamer1 ntpd[720]: interface -> (none)
Feb 14 08:42:26 streamer1 ntpd[720]: peers refreshed
Feb 15 04:20:10 streamer1 systemd[1]: Time has been changed

Given the timestamp resolution, NTP (or systemd) apparently resets the clock three seconds after the IP address changes. That may be as good as it gets, if only because the NTP daemon must find its servers, evaluate their status, then whack the local clock.

After forcing the static address, things look better, but it’s too soon to be sure. Many things can clobber streaming, not all of which happen on this side of our router.