• PoE, dV/dt and ESD

    06/29/2019 at 17:29 0 comments

    Why I don't like USB in the lab

    When lab setups don't fall into disuse and get scrapped, they are usually passed down through generations of PhD students - and there doesn't always seem to be an incentive to spend time to improve a working setup.

    ... and then one ends up with such organically grown USB cancer:

    While USBTMC (USB Test and Measruement Class, [1]) allows ease of use of a subset of lab equipment, one is usually at the mercy of manufacturers to support newer platforms and control software implementations to properly handle USB devices.
    Practically such equipment communication ends up being vulnerable to faults by re-enumeration and broken handles to once-functional virtual COM ports.
    Let's change the requirements too and ask to allow multiple control PCs and setups sharing measurement equipment - and USB stops making so much sense altogether.

    To spice things up, I'm adding transients of 1 .. 20 kA/µs and 10-50 kV/µs into the mix. Under these conditions, and with setups not enclosed in metal test cells, with filters added to all cables crossing the shielding walls, USB struggles through common mode (CM) noise and yet-to-be-identified perturbations.

    On a side note: the only cables we've found to make a difference are "CU-HQ-20". They have honest copper cross-sections, proper shielding braid and ferrite filters on both ends. Expect to play 15€/pc.

    Ethernet and PoE in the lab?

    Ethernet enables multiple pieces of equipment, actuators, sensors, control interfaces and PCs to be connected, both locally and remote, and satisfies the requirements for maximum flexibility with cheap and ubiquitous components.

    Thus we should be looking at the 10BASE-T and 100BASE-TX physical layers in terms of noise immunity and voltage handling capabilites and see how PoE fits into the picture.


    Ethernet has become very popular in industrial applications [2]. As far as noise immunity is concerned, common-mode filters are often part of integrated-magnetics RJ45 connectors (commonly called "MagJack", which happens to be a name trademarked by BEL). Having the filter magnetics right behind the connector pins in a shielded can connected to the enclosure and bypass capacitors right next to the connectors is the a best effort approach to mitigating conducted and radiated emissions into a network enabled device. The PoE lines are commonly outfitted with ferrite beads to block common-mode transients coupling into the DCDC converter circuitry.

    Below two types of MagJack circuits are shown [3]. The right one is outfitted with separate PoE pins which hook up to full bridge rectifiers and an isolation converter that also handles the PoE communication. Power is transmitted courtesy of a common-mode potential difference between differential pairs.

    It is to be expected that the patch cable shield is connected to ground of the switch chassis. We have found our first issue: high frequency CM voltage components drop across the CM filter and to a lesser degree across the signal transformer. Additionally, low frequency and DC components are blocked by the signal transformer alone.

    Are they really being blocked?

    Let's look at the signal transformer:

    These parts tend to be produced as a multifilar toroidal winding, e.g. on a small NiZn ferrite core. The windings have maximized overlap to optimize coupling and to marginalize stray inductance, but then again this also enhances capacitive coupling. This inter-winding capacitance is a low-impedance path for high frequency common-mode noise.

    Faraday shields eliminate inter-winding capacitance. For transformers this requires the addition of one or mulitple shielding foils or wire windings in between primary and secondary sides, along with added insulation. I haven't seen them used in ethernet magnetics though.

    What would be the best effort? Lacking a teardown survey of PoE switches marketed for industrial applications (please contact me if you happen to have a box of interesting stuff...

    Read more »

  • Hack-an-Hour: audio QR codes

    09/11/2018 at 14:44 0 comments

    it's 1am and I feel like I have one hour of juice left in me... let's go. We'll be cooking up a bit of python code for fun and joy, so hang in there :) you'll see where we're going....

    "audio qr code" brings up things quite different from what I'm up to. It's a bit like the Transformer movies made it next to impossible to find technical info on strange types of magnetics once they hit the market.

    1) find a way to produce uncompressed RIFF wave files

    pip3 install wave

    2) we're building a new wave file. The lib is nice to avoid the gory format details. Done that once, no burning thirst to do it many more times.


    ... and I got sidetracked with named tuples... so far:

    import wave
    # create wave_write object
    w = wave.open('code.wav', 'wb')
    # create output
        1, # nchannels.
        2, # sampwidth: in bytes  - 1 channel, 16 bit 
        48000, # framerate: 48kHz sampling rate? 
        1024, # nframes: will be changed as frames are written 
        'NONE', # comptype: only NONE is supported right now
        'NONE', # compname: only NONE is supported right now
    # finish

    Bloody notepad++ broke the hexEditor plugin. Wow, such hate, complemented by

    The bloody thing just died on me to make a point. Also claims there are no plugins installed and none available.
    the .wav looks like this, which is nice. No hex editor :(
    RIFF$   WAVEfmt....

     25 minutes in..

    nframes is pretty much being ignored. We want some nice 10 seconds of annoyance, so let's aim for that, see if we can produce silence to start with.

    3) QR code

    let's use a picture for now, deal with code generation later.


     we can do this!

    turns out,

    pip3 install Pillow

    44 minutes in...

    import PIL.Image
    # load QR code picture
    img = PIL.Image.open('code.png', 'r')
    img_width, img_height = img.size

    learning as a timed challenge. Who came up with this? Not sure whether I like it.

    now we should have image size and data. Quick test?

    print(img.getpixel((1,1))) yields (255, 255, 255)

    we're good. another test at (1000,1): out of range... so we need to do range testing ourselves. Wonderful :) Floating point coordinates are accepted but I haven't read what they do. We'll find out soon enough.

    Scale and range limit the first channel of the pixel

    getpixelcoef = lambda x, y: img.getpixel((x, y))[0]/255 if (0 <= x) and (x < img_width) and (0 <= y) and (y < img_height) else 0

    4) time's up :(

    Here we are right now:

    import wave
    import PIL.Image
    import math
    import numpy as np
    # load QR code picture
    img = PIL.Image.open('code.png', 'r')
    img_width, img_height = img.size
    # create wave_write object
    w = wave.open('code.wav', 'wb')
    # create output
        1, # nchannels.
        2, # sampwidth: in bytes  - 1 channel, 16 bit 
        48000, # framerate: 48kHz sampling rate? 
        0, # nframes: will be changed as frames are written 
        'NONE', # comptype: only NONE is supported right now
        'NONE', # compname: only NONE is supported right now
    dt = 1.0/w.getframerate()
    dt_pixel = 0.1 # 100ms/px
    total_time = 10.0
    fstart = 17000
    fend   = 20000
    fsteps = 100
    freqs  = np.arange(fstart, fend, (fend-fstart)*1.0/fsteps)
    getpixelcoef = lambda x, y : img.getpixel((x, y))[0]/255 if (0 <= x) and (x < img_width) and (0 <= y) and (y < img_height) else 0
    for n in range(0, int(w.getframerate()*total_time)):
        for f in freqs:
    # finish

    We've started spitting out a wave file, managed to load a QR code image and after pip3 install numpy we're good to go with a list of frequencies to process every sample.

    ROUND 2

    Tomorrow will not be such a fine day ;-) What with waking up too late and so forth. We cannot stop now though. We want to hear the darn QR code.

    howto 16bit signed value?


    1h30min: this is the...

    Read more »

  • Generating Nice Threads In OpenSCAD

    05/26/2018 at 23:52 10 comments

    [Hello future reader. This article refers to OpenSCAD 2018.05.05, please check if it still applies later on]

    3D printing internal and external threads is interesting for many reasons.

    Unlike gears that invariably wear rapidly and cannot measure up compared to cast or subtractively machined parts, they are pretty functional and allow the common maker to interface with custom and standardized bolts, pipes, valves, soda bottles and canisters - and that's on top of the liberty to create your own threaded mating components within the confines of your design.

    The generalized approach presented here supports arbitrary thread geometries and numbers of starts.

    Shown below are single start inside and outside threads as well as a swivel nut with a "faster" 3-start thread, all modelled to match commercial water bottles - the small one is "PCO-1881" known from 1.5L soda bottles, the larger one is "48-41" for 3-5L jugs:

    Only right-hand threads are supported but left-handed threads are easy to get by applying mirror([0,1,0]) to the output. That's the OpenSCAD way :)

    While the core idea of a straight thread - the helical profile wrapped onto a cylinder - is rather straight forward, generating nice geometry that does not disintegrate along the way from model rendering thru .stl export to the slicer tool deserves a little bit of attention.

    What do I mean by "nice geometry"?

    • "embossed threads" on a curved surface or
    • manifold additive threads (demonstrated here, imho more universal)
    • regular mesh / regular connectivity of trangles / quadrilaterals (no crazy pointy aspect ratios and cell size changes)
    • low polygon count and accurate / efficient reproduction of the thread profile
    • geometry matched to the rest of the model

    in short, what we don't want is unnecessary structure, gaps, holes and mismatch of resolution of the threads and the rest of the geometry.

    What I'm going to walk you through here is a way to create helical thread forms just like the ones you'd strip when overtightening a bolt:


    Since OpenSCAD is am open source work in progress, users do not necessarily work with a version that has the latest features, documentation may not be up to date and forum posts claiming "it cannot be done" are repeatedly being invalidated by software revisions, adding to the confusion.

    Let's go over what doesn't work (hopefully gaining some insights), then look at my proposed approach. If you just want the answers, please scroll down :)


    As an example: without an operator that creates dedicated helical structures people are using linear_extrude() with twist to get something helical:

    The problem here is that like fanning a deck of cards you'll end up with tucked-in faces and serrated outsides - as seen on Thingiverse:

    And here's another one with a bit of discussion from 2014:



    Unfortunately as of now rotate_extrude() which should be closer to creating helical objects has learned partial rotations (not supported in 2015 builds for Windows) but cannot create helical extrusions. There's also no special treatment for the ends.

    One could create a...

    Read more »