The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Category: Oddities

Who’d’a thunk it?

  • Beckman DM73: Package Armor

    Beckman DM73: Package Armor

    For reasons not relevant here, I sent the Beckman DM73 to a good home in Europe. Having some experience with the brutality applied to innocent packages by various package-delivery organizations, I filled a Priority Mail Flat Rate Small Box with a solid block of corrugated cardboard:

    DM73 - cardboard armor
    DM73 – cardboard armor

    One inner layer has a cutout for the manual:

    DM73 - Operator Manual package
    DM73 – Operator Manual package

    The meter and its leads tuck into form-fitting cutouts:

    Beckman DM73 - cardboard packing
    Beckman DM73 – cardboard packing

    I bandsawed the cutouts from a block with enough layers for some space on the top and bottom:

    DM73 - bandsawing cardboard package
    DM73 – bandsawing cardboard package

    After mulling that layout overnight, I made a similar block with the saw cuts on diagonally opposite corners, so pressure on the center of the edges won’t collapse the unsupported sides. A slightly larger meter cutout allowed a wrap of closed-cell foam sheet that likely doesn’t make any difference at all.

    With everything in place, the box had just enough space for a pair of plastic sheets to better distribute any top & bottom impacts.

    I won’t know how the armor performed for a few weeks, but it’s definitely the best packaging idea I’ve had so far.

    Update: After nearly two weeks, the package arrived undamaged and the meter was in fine shape. Whew!

  • Which Sign Is Not Like The Other Signs?

    Which Sign Is Not Like The Other Signs?

    Spotted on a recent trip past the Capital Region Welcome Center, one of the banners seemed quite unlike the others:

    NY Promotion Banners - Capital Region I-87 Welcome
    NY Promotion Banners – Capital Region I-87 Welcome

    Maybe if we were dog people, it’d be less offputting.

    Puts me in mind of being So Poughkeepsie.

  • Chestnut Parasites

    Chestnut Parasites

    I spotted this little gadget chugging steadily across a table in the living room:

    Chestnut parasite larva - detail
    Chestnut parasite larva – detail

    Nearby, two of its friends / siblings / clones remained near their landing craft:

    Chestnut parasite larvae - overview
    Chestnut parasite larvae – overview

    They’re about 5 mm long and, although there are no larva-size holes visible in the chestnuts tucked inside the burr, that’s definitely where they started their journey.

    A few hours later, the rest of the crew bailed out:

    Chestnut parasite larvae - irruption
    Chestnut parasite larvae – irruption

    The exit hole must be on a nut under the curve of the husk, but they’re sufficiently squishy to wriggle their way out. The little brown dot over on the left belongs to the top larva of a pair queued in the exit corridor:

    Chestnut parasite larvae - exiting husk
    Chestnut parasite larvae – exiting husk

    I lost count at 18. There’s surely more where they came from, so I replaced the plate with a bowl to reduce the quantum tunneling probability.

    In an ideal world, they’d grow up to be chestnut weevils, but I put them out near the suet feeder and, a few hours later, my offering was accepted.

  • Monthly Image: Chestnut Burrs!

    Monthly Image: Chestnut Burrs!

    Much to our utter astonishment, this appeared on the driveway:

    Chestnut burr
    Chestnut burr

    We’ve since found half a dozen chestnut burrs in the yard, which means at least two trees (it takes two to cross-fertilize) are growing in the immediate area.

    We originally thought they were American Chestnuts, but Mary (being a Master Gardener) found enough references including comparative burr pictures to convince us they’re Chinese Chestnuts.

    We’ve seen squirrels carrying the burrs in their mouths from the trees to wherever they bury their food supply, as shown by this gnawed spot on the other side of the burr:

    Chestnut burr - gnawed section
    Chestnut burr – gnawed section

    I regard this as conclusive proof that squirrels either have no sense of pain or no lips, because I can’t imagine carrying that thing in my hand, let alone gnawing through it to extract the nuts inside.

    Each burr contains three nuts, although this empty husk shows some nuts can fail to fill out:

    Chestnut burr - interior with failed nut
    Chestnut burr – interior with failed nut

    We don’t know where the trees are, but the squirrels seem to carry the burrs across our yard from north to south, so they can’t be too far from us or each other.

    Despite our conclusion, it’s faintly possible they’re American Chestnuts, in which case they’re definitely survivors!

  • Raspberry Pi Interrupts vs. Rotary Encoder

    Raspberry Pi Interrupts vs. Rotary Encoder

    Thinking about using a rotary encoder to focus a Raspberry Pi lens led to a testbed:

    RPi knob encoder test setup
    RPi knob encoder test setup

    There’s not much to it, because the RPi can enable pullup resistors on its digital inputs, whereupon the encoder switches its code bits to common. The third oscilloscope probe to the rear syncs on a trigger output from my knob driver.

    I started with the Encoder library from PyPi, but the setup code doesn’t enable the pullup resistors and the interrupt (well, it’s a callback) handler discards the previous encoder state before using it, so the thing can’t work. I kept the overall structure, gutted the code, and rebuilt it around a state table. The code appears at the bottom, but you won’t need it.

    Here’s the problem, all in one image:

    Knob Encoder - ABT - fast - overview
    Knob Encoder – ABT – fast – overview

    The top two traces are the A and B encoder bits. The bottom trace is the trigger output from the interrupt handler, which goes high at the start of the handler and low at the end, with a negative blip in the middle when it detects a “no motion” situation: the encoder output hasn’t changed from the last time it was invoked.

    Over on the left, where the knob is turning relatively slowly, the first two edges have an interrupt apiece. A detailed view shows them in action (the bottom half enlarge the non-shaded part of the top half):

    Knob Encoder - ABT - fast - first IRQs
    Knob Encoder – ABT – fast – first IRQs

    Notice that each interrupt occurs about 5 ms after the edge causing it!

    When the edges occur less than 5 ms apart, the driver can’t keep up. The next four edges produce only three interrupts:

    Knob Encoder - ABT - fast - 4 edges 3 IRQ
    Knob Encoder – ABT – fast – 4 edges 3 IRQ

    A closer look at the three interrupts shows all of them produced the “no motion” pulse, because they all sampled the same (incorrect) input bits:

    Knob Encoder - ABT - fast - 4 edges 3 IRQ - detail
    Knob Encoder – ABT – fast – 4 edges 3 IRQ – detail

    In fact, no matter how many edges occur, you only get three interrupts:

    Knob Encoder - ABT - fast - 9 edges 3 IRQ
    Knob Encoder – ABT – fast – 9 edges 3 IRQ

    The groups of interrupts never occur less than 5 ms apart, no matter how many edges they’ve missed. Casual searching suggests the Linux Completely Fair Scheduler has a minimum timeslice / thread runtime around 5 ms, so the encoder may be running at the fastest possible response for a non-real-time Raspberry Pi kernel, at least with a Python handler.

    If. I. Turn. The. Knob. Slowly. Then. It. Works. Fine. But. That. Is. Not. Practical. For. My. Purposes.

    Nor anybody else’s purposes, really, which leads me to think very few people have ever tried lashing a rotary encoder to a Raspberry Pi.

    So, OK, I’ll go with Nearer and Farther focusing buttons.

    The same casual searching suggested tweaking the Python thread’s priority / niceness could lock it to a different CPU core and, obviously, writing the knob handler in C / C++ / any other language would improve the situation, but IMO the result doesn’t justify the effort.

    It’s worth noting that writing “portable code” involves more than just getting it to run on a different system with different hardware. Rotary encoder handlers are trivial on an Arduino or, as in this case, even an ARM-based Teensy, but “the same logic” doesn’t deliver the same results on an RPi.

    My attempt at a Python encoder driver + simple test program as a GitHub Gist:

    # Rotary encoder test driver
    # Ed Nisley – KE4ZNU
    # Adapted from https://github.com/mivallion/Encoder
    # State table from https://github.com/PaulStoffregen/Encoder
    import RPi.GPIO as GPIO
    class Encoder(object):
    def __init__(self, A, B, T=None, Delay=None):
    GPIO.setmode(GPIO.BCM)
    self.T = T
    if T is not None:
    GPIO.setup(T, GPIO.OUT)
    GPIO.output(T,0)
    GPIO.setup(A, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(B, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    self.delay = Delay
    self.A = A
    self.B = B
    self.pos = 0
    self.state = (GPIO.input(B) << 1) | GPIO.input(A)
    self.edges = (0,1,-1,2,-1,0,-2,1,1,-2,0,-1,2,-1,1,0)
    if self.delay is not None:
    GPIO.add_event_detect(A, GPIO.BOTH, callback=self.__update,
    bouncetime=self.delay)
    GPIO.add_event_detect(B, GPIO.BOTH, callback=self.__update,
    bouncetime=self.delay)
    else:
    GPIO.add_event_detect(A, GPIO.BOTH, callback=self.__update)
    GPIO.add_event_detect(B, GPIO.BOTH, callback=self.__update)
    def __update(self, channel):
    if self.T is not None:
    GPIO.output(self.T,1) # flag entry
    state = (self.state & 0b0011) \
    | (GPIO.input(self.B) << 3) \
    | (GPIO.input(self.A) << 2)
    gflag = '' if self.edges[state] else ' – glitch'
    if (self.T is not None) and not self.edges[state]: # flag no-motion glitch
    GPIO.output(self.T,0)
    GPIO.output(self.T,1)
    self.pos += self.edges[state]
    self.state = state >> 2
    # print(' {} – state: {:04b} pos: {}{}'.format(channel,state,self.pos,gflag))
    if self.T is not None:
    GPIO.output(self.T,0) # flag exit
    def read(self):
    return self.pos
    def read_reset(self):
    rv = self.pos
    self.pos = 0
    return rv
    def write(self,pos):
    self.pos = pos
    if __name__ == "__main__":
    import encoder
    import time
    from gpiozero import Button
    btn = Button(26)
    enc = encoder.Encoder(20, 21,T=16)
    prev = enc.read()
    while not btn.is_held :
    now = enc.read()
    if now != prev:
    print('{:+4d}'.format(now))
    prev = now
    view raw encoder.py hosted with ❤ by GitHub

  • Helicopter Hovering

    Helicopter Hovering

    Spotted on a ride on New Hackensack Road around what’s grandly known as the Hudson Valley Regional Airport:

    Helicopter Hovering Practice 1
    Helicopter Hovering Practice 1

    Indeed, it was.

    I watched a private airshow for a few minutes:

    Helicopter Hovering Practice 2
    Helicopter Hovering Practice 2

    The same helicopter thumped over our house, about two miles from the runway as the chopper flies, while I was getting ready for the ride, and it was hovering as I reached the airport. I think the pilot was practicing, because the chopper made very precise movements across the airport, translated front / back / left / right, and hovered motionless for minutes at a time despite wind gusts.

    Looks like enjoyably intense concentration!

  • Praying Mantis: Ootheca Construction

    Praying Mantis: Ootheca Construction

    After not seeing any Praying Mantis activity in the Butterfly Bush for a few days, I discovered our armored hunter in the nearby decorative grass:

    Praying Mantis - building ootheca
    Praying Mantis – building ootheca

    The appendages at the tip of her abdomen were spread to the sides and her whole body moved in small circles, although I couldn’t get a good view of the proceedings. Building an ootheca apparently requires concerted effort, as she was still hard at work when dusk fell.