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: Electronics Workbench

Electrical & Electronic gadgets

  • Mesa 7i76 vs. M542 vs. Stepper Motor Wiring

    Both the Mesa 7i76 and the M542 stepper driver boards use Phoenix-style pluggable screw terminals that simplify the connections: just strip the wires, jam them into the holes, and tighten the screw. That works great in an industrial situation where the equipment gets wired up once and stays that way forever, but I expect that I’ll be doing far too much twiddling… which means the stripped wire ends will fray and shed strands across the boards.

    So, while wiring up a stepper motor, I tried soldering the wires to several different terminals I have lying around, just to see how they work.

    The M542 stepper driver brick shows the assortment:

    M542 Stepper Driver Wiring
    M542 Stepper Driver Wiring

    On the far left, the four stepper wires end in right-angle PCB pins harvested from surplus connectors. This didn’t work nearly as well as I’d like, simply because the pins are entirely too bulky. I’m not sure quite how the bricks will be arranged, but I think a right-angle connection won’t work well at all.

    The field power from the 24 VDC supply arrives on some (cheap) 18 AWG speaker zip cord, terminated in straight-line PCB pins. Those worked better, but they do stick out a goodly amount. Methinks the right thing to do with larger wire is just solder the strands together, clean the end, and not bother with pins. That’s not so good for strain relief (it concentrates at the end of the soldered strands), but, with some tubing added, maybe it’ll be Good Enough.

    The 26 AWG input wires from the 7i76 terminate in turret pins originally intended for PCB terminations or test points, back in the day when you (well, I) could actually see such things; I have a bag of 1000 that I’ve been chewing away at for a while. I think these wires are simply too small for the screw terminals, so they really need a pin of some sort and I like the way the turret pins work. The heatstink tubing provides a bit of strain relief, which always comes in handy.

    The two stray wires will eventually go to the “Enable” input. It turns out that these bricks defaults to Enabled with no input signal, so you cannot depend on a wiring fault disabling the motor: a broken Enable wire enables the drive output. This seems flat-out dumb, but I suppose there’s some planet on which it makes sense.

    I snipped a bunch of 3/8 inch (call it 10 mm) lengths of tubing, but that turns out to be slightly too long for the 7i76 terminal layout:

    Mesa 7i76 Wiring
    Mesa 7i76 Wiring

    So the next iteration must be a bit shorter.

    Yes, you can get commercial crimp pin terminations; search eBay for crimp insulated terminal pins, some of which are curving around the planet even as I type. They won’t fit into the tight confines of the 7i76, but they should be better for the M542 bricks. The smallest size fits 22 through 16 AWG wires, so my tiny cable wires may need some steroids to bulk ’em up.

    On the stepper motor end of the cable, I picked up a bunch of JST connectors and crimp pins. Unfortunately, the proper crimp tool runs into the hundreds of dollars, even from the usual eBay suppliers, and I really don’t have that much need for those pins. So I just soldered wires from the cable to the pins and mashed them down with needle nose pliers:

    Stepper wiring - soldered JST pins
    Stepper wiring – soldered JST pins

    The alert reader will notice an egregious wire color coding faceplant. I made a corresponding blunder on the other end and nobody will ever know. Next time, maybe I’ll get it right.

    That makes for a nice connection at the motor:

    Stepper wiring - connector in place
    Stepper wiring – connector in place

    The thin black cable has nine 26 AWG conductors that I’m doubling up for the motors. In round numbers, 26 AWG stranded has about 120 mΩ/m resistance, so two in parallel work out to 60 mΩ/m. Assuming a meter of cable between the driver and the motor, a 1 A winding current will drop 120 mV along the way and dissipate 1/8 W, which seems defensible. It’s obviously Good Enough for signal wiring.

    It is most definitely not good enough for, say, the heaters.

    The motivation for using that cable: it’s thin and super-flexy, not the rigid cylinder you get with larger conductors. Plus, I have a huge supply of the stuff… it originally served as RS-232 cable, with molded connectors on each end of a 30 foot length, with four such cables assembled into a super-cable with nylon padding yarn laid inside a protective outer sheath. Must have cost a fortune to the original buyer; decades ago I got three or five of the assemblies and have been harvesting cable ever since.

  • LinuxCNC + Mesa 7i76: Solid-state Relay Light

    I intend to use solid-state relays to control things like extruder and platform heaters, so I wired a Fotek SSR-10 DD to the same output bit as the First Light test, with a random 12 V SLA battery providing power for the LED strip:

    Mesa 7i76 with Fotek DC-DC SSR
    Mesa 7i76 with Fotek DC-DC SSR

    Nothing groundbreaking, but it’s always nice to confirm these things.

    Note that the SSR must have a DC output, not the more common AC output, to control DC power. In effect, a DC-DC SSR is just an up-armored power FET with an optically isolated gate terminal.

    Dan reports that the Fotek SSRs have just about exactly the internal build quality you’d expect for a cheap product from halfway around the planet. Although the specs would have you believe they operate from a 5 VDC source, that may not be the case. The 7i76 output pins switch the +24 VDC field power to the SSR, so it’s firmly turned on.

  • USB Current Measurement Taps

    Two quick-and-dirty Arduino Power Current Taps for the Arduino Survival Guide: Workbench Edition class I taught for SqWr a while ago. These give you the current drawn by the entire board + LEDs + whatever, so you can calculate the power dissipation in that poor on-board regulator.

    The USB version:

    USB Current Tap
    USB Current Tap

    The general idea is to cut a USB extension cable (Type A plug on one end, Type A receptacle on the other) in half, splice the two data wires, splice the ground / common wire, but connect the +5 V wires to a dual banana plug that goes into a current meter. The Big Box o’ USB Junk produced a cutoff cable end with a Type A plug and a PC jumper that was supposed to connect an internal USB header to the back panel; the red blob of silicone tape conceals the jumper’s socket strip and a five-pin male header with all the wires soldered to it.

    You could use a Type B plug that would go directly into an Arduino UNO (or similar), but I figured this way everybody can bring whatever cable they need for their particular Arduino, not all of which have bulky Type B receptacles these days.

    The External Power version:

    External Power Current Tap
    External Power Current Tap

    The coaxial power plug goes into the Arduino and whatever you used for power goes into the socket. The Big Box o’ Coaxial Power Stuff actually had a more-or-less properly sized coaxial jack with two wires on it and silicone tape wrapped around it; I regarded that as a Good Omen and pressed it into service as-is.

    These will also replace the horribly rickety collection of alligator clip leads I usually use for such measurements…

  • Mesa 5i25 + 7i76: First Light!

    Rather than start with the stepper, I wired an LED and resistor between output bit 07 and Field Ground at the power supply:

    Mesa 5i26-7i76 with LED
    Mesa 5i26-7i76 with LED

    It’s worth noting that the terminals labeled GND on TB2 and TB3 are isolated from the Field GROUND terminal on TB1. When Mesa says “isolated power supply”, that’s exactly what they mean.

    The digital output bits connect +24 VDC Field Power to the load, which should then connect to Field GROUND. I picked a good-looking 5 V panel LED from the pile, simply because it had wires soldered to it from a previous life, and put a 1 K resistor in series to drop the other 19 V.

    Then you start up HAL, load the Mesa drivers, and twiddle the bit:

    halrun
    halcmd: loadrt threads name1=th period1=1000000
    halcmd: loadrt hostmot2
    halcmd: loadrt hm2_pci
    halcmd: addf hm2_5i25.0.pet_watchdog th
    halcmd: addf hm2_5i25.0.read th
    halcmd: addf hm2_5i25.0.write th
    halcmd: start
    halcmd: setp hm2_5i25.0.7i76.0.0.output-07 true
    halcmd: setp hm2_5i25.0.7i76.0.0.output-07 false
    halcmd: quit
    

    The thread runs with a 1 ms period, mostly because it’s convenient. The .read and .write pins transfer data from and to the 5i25 FPGA each time the thread runs; if you forget those, nothing happens.

    Setting the output bit true activates the output bit, turns on the MOSFET driver, and connects the terminal to Field Power = 24 VDC. The 7i76 outputs do not sink current, they source it.

    A journey of a thousand 3D printed objects starts with a single LED…

    The watchdog timer ought to be connected to something more fragile and UI-related than the main thread, but I haven’t figured out how to do that yet.

  • Arduino Survival Guide: Workbench Edition

    Pullup Voltage Divider
    Pullup Voltage Divider

    Herewith, the slides for the talk + lab session I’m doing today for Squidwrench:

    Arduino Survival Guide – Workbench Edition

    Unlike most Arduino courses, I assume you’re already OK with the programming, but are getting tired of replacing dead Arduinos and want to know how to keep them alive. The course description says it all:

    Learn how to help your Arduino survive its encounter with your project, then live long and prosper. Discover why feeding it the proper voltages, currents, and loads ensures maximum Arduino Love!

    Ed will describe some fundamental electronic concepts, guide you at the workbench while you make vital measurements, then show you how to calculate power dissipation, load current, and more. You’ll understand why Arduinos get hot, what kills output bits, and how you can finally stop buying replacements.

    Among other lab exercises, we’ll measure the value of the ATmega’s internal pullup resistors, which everybody assumes are 20 kΩ, but probably aren’t. Hint: you can apply Ohm’s Law twice to that simple circuit and come up with the right answer, but only if you’ve measured the actual VCC voltage on the board.

    The Mighty Thor will detail how to not prepare Fried Raspberry Pi.

    In the unlikely event you’re in Highland NY, stop by: you’re bound to learn something.

  • Magnetics Overview

    I wound up doing an impromptu magnetics (as it applies to transformers) review during a recent SqWr meeting. This summarizes, re-orders, and maybe expands on some quadrille paper scribbling, so that if I ever do it again I’ll have a better starting point. Searching on the obvious terms will produce a surfeit of links; Wikipedia may be helpful for diagrams.

    Corrections and further points-to-ponder will be gratefully received…

    Magnetizing force H comes from amp-turns (amps I, turns N) around the core, which produces flux phi = Φ = NI. Edit: that’s not quite right. Thanks to Martin Bosch for catching the units mismatch!

    Magnetomotive force ℱ comes from ampere-turns (amps I, turns N) around the core: mmf = ℱ = NI.

    The magnetizing force H is the mmf per unit length of the solenoid or core: H = ℱ / L.

    Flux density B comes from permeability (mu = μ) times H, which is a DC relationship that doesn’t care about frequency in the least: B = μH. For an air-core inductor or transformer, μ is the mu-sub-zero = μ0 of free space, but if there’s a core involved, then you use the permeability of the material near the conductor, which will be the material’s dimensionless relative permeability μR times μ0.

    Total flux Φ is the integral of flux density B over all the little areas covering the surface you’re interested in, oriented in a consistent manner using the right-hand rule.

    If you have an iron(-like) core inside the coil, then essentially all the flux is in the core, so the integral reduces to B times the area (call it a) of the core at right angles to the flux: Φ = Ba = μaH. In this case, μ is the relative permeability of the core times μ0 of free space.

    You can plot BH curves (B for various H values) using a straightforward circuit and an oscilloscope. The X axis voltage is proportional to the winding current I and the Y axis voltage is proportional to Φ. The trick is the integrator on the secondary that converts EMF = dΦ / dt into a voltage directly proportional to Φ. The same trick works on inductors if you add a few turns to act as a secondary.

    All that’s true for DC as well as AC, but transformers only work on AC, as summarized by Lenz.

    The induced EMF is proportional to flux change through the secondary windings, which number n turns: EMF = – n dΦ / dt. That’s obviously proportional to frequency: higher frequency = higher EMF. Flux is all in the transformer core, so it’s still μaH. Note that these are secondary turns, so it’s n rather than N. Air-core transformers exist, but coupling the flux poses a problem; looking up variometer or variocoupler may be instructive.

    The negative sign says the induced EMF creates a current that creates a magnetic field that points the other way, so as to oppose the original field change. In effect, the induced EMF works to cancel out the field you’re creating.

    Knowing how much EMF you need in the secondary for the purposes of your circuit, you know the product of five things:

    • n – secondary turns
    • μ – (relative) core permeability
    • a – area
    • f – frequency
    • H – from primary

    Now you get to pick what’s important, but they all have gotchas:

    The ratio n:N seems easy to control, but it tops out at a few hundred. If you care about the voltage ratio, then that fixes the turns ratio.

    Choose different core material to increase μ, but then you hit core saturation in B as H increases. Practical core materials may give you permeability over two or three orders of magnitude, but with significant side effects.

    Reduce B for a given Φ by using a larger core area a, which obviously requires a bigger core that may not fit the application.

    Increase frequency f to get more EMF and thus H, but it may be limited by your application and other losses and effects. Higher frequency = more traverses of that BH curve with hysteresis = more core losses = can’t use lossy metals.

    Increase primary H, but again you hit core saturation in B.

    The circuit driving the primary must be able to handle the total load, which means it must be able to drive the impedance presented by the transformer + secondary load. That determines the primary inductance (to get the reactance high enough that the transformer presents the secondary load to the primary circuit), which determines the core + turns at the operating frequency.

    The core must support the flux required to drive the load without saturation, which constrains the material and the area. For heavy loads (i.e., “power” transformers), output power also constrains the secondary turns and wire size, which constrains the minimum core opening and thus overall size.

  • TC4Server: Eagle HAL Device

    Dan Newman’s TC4Server turns the TC4 thermocouple board into a USB HID input device that’s compatible with HAL’s hal_input module:

    TC4 on ProtoScrewShield on Leonardo
    TC4 on ProtoScrewShield on Leonardo

    For simplicity (i.e., to avoid writing a special driver), TC4Server misrepresents itself as a nine-axis joystick-like device suited for RC airplane control:

    halrun
    halcmd: loadusr -W hal_input +A Leonardo
    halcmd: show
    ... snippage ...
    Component Pins:
    Owner   Type  Dir         Value  Name
         5  s32   OUT          2941  input.0.abs-rudder-counts
         5  s32   IN           4095  input.0.abs-rudder-flat
         5  s32   IN            255  input.0.abs-rudder-fuzz
         5  bit   OUT          TRUE  input.0.abs-rudder-is-neg
         5  bit   OUT         FALSE  input.0.abs-rudder-is-pos
         5  float IN        32767.5  input.0.abs-rudder-offset
         5  float OUT    -0.9102464  input.0.abs-rudder-position
         5  float IN        32767.5  input.0.abs-rudder-scale
         5  s32   OUT          2947  input.0.abs-rx-counts
         5  s32   IN           4095  input.0.abs-rx-flat
         5  s32   IN            255  input.0.abs-rx-fuzz
         5  bit   OUT          TRUE  input.0.abs-rx-is-neg
         5  bit   OUT         FALSE  input.0.abs-rx-is-pos
         5  float IN        32767.5  input.0.abs-rx-offset
         5  float OUT    -0.9100633  input.0.abs-rx-position
         5  float IN        32767.5  input.0.abs-rx-scale
         5  s32   OUT         65535  input.0.abs-ry-counts
         5  s32   IN           4095  input.0.abs-ry-flat
         5  s32   IN            255  input.0.abs-ry-fuzz
         5  bit   OUT         FALSE  input.0.abs-ry-is-neg
         5  bit   OUT          TRUE  input.0.abs-ry-is-pos
         5  float IN        32767.5  input.0.abs-ry-offset
         5  float OUT             1  input.0.abs-ry-position
         5  float IN        32767.5  input.0.abs-ry-scale
         5  s32   OUT         65535  input.0.abs-rz-counts
         5  s32   IN           4095  input.0.abs-rz-flat
         5  s32   IN            255  input.0.abs-rz-fuzz
         5  bit   OUT         FALSE  input.0.abs-rz-is-neg
         5  bit   OUT          TRUE  input.0.abs-rz-is-pos
         5  float IN        32767.5  input.0.abs-rz-offset
         5  float OUT             1  input.0.abs-rz-position
         5  float IN        32767.5  input.0.abs-rz-scale
         5  s32   OUT         65535  input.0.abs-throttle-counts
         5  s32   IN           4095  input.0.abs-throttle-flat
         5  s32   IN            255  input.0.abs-throttle-fuzz
         5  bit   OUT         FALSE  input.0.abs-throttle-is-neg
         5  bit   OUT          TRUE  input.0.abs-throttle-is-pos
         5  float IN        32767.5  input.0.abs-throttle-offset
         5  float OUT             1  input.0.abs-throttle-position
         5  float IN        32767.5  input.0.abs-throttle-scale
         5  s32   OUT          2957  input.0.abs-wheel-counts
         5  s32   IN           4095  input.0.abs-wheel-flat
         5  s32   IN            255  input.0.abs-wheel-fuzz
         5  bit   OUT          TRUE  input.0.abs-wheel-is-neg
         5  bit   OUT         FALSE  input.0.abs-wheel-is-pos
         5  float IN        32767.5  input.0.abs-wheel-offset
         5  float OUT    -0.9097581  input.0.abs-wheel-position
         5  float IN        32767.5  input.0.abs-wheel-scale
         5  s32   OUT          2942  input.0.abs-x-counts
         5  s32   IN           4095  input.0.abs-x-flat
         5  s32   IN            255  input.0.abs-x-fuzz
         5  bit   OUT          TRUE  input.0.abs-x-is-neg
         5  bit   OUT         FALSE  input.0.abs-x-is-pos
         5  float IN        32767.5  input.0.abs-x-offset
         5  float OUT    -0.9102159  input.0.abs-x-position
         5  float IN        32767.5  input.0.abs-x-scale
         5  s32   OUT          2942  input.0.abs-y-counts
         5  s32   IN           4095  input.0.abs-y-flat
         5  s32   IN            255  input.0.abs-y-fuzz
         5  bit   OUT          TRUE  input.0.abs-y-is-neg
         5  bit   OUT         FALSE  input.0.abs-y-is-pos
         5  float IN        32767.5  input.0.abs-y-offset
         5  float OUT    -0.9102159  input.0.abs-y-position
         5  float IN        32767.5  input.0.abs-y-scale
         5  s32   OUT          2940  input.0.abs-z-counts
         5  s32   IN           4095  input.0.abs-z-flat
         5  s32   IN            255  input.0.abs-z-fuzz
         5  bit   OUT          TRUE  input.0.abs-z-is-neg
         5  bit   OUT         FALSE  input.0.abs-z-is-pos
         5  float IN        32767.5  input.0.abs-z-offset
         5  float OUT     -0.910277  input.0.abs-z-position
         5  float IN        32767.5  input.0.abs-z-scale
         5  s32   OUT          2941  input.1.abs-rudder-counts
         5  s32   IN           4095  input.1.abs-rudder-flat
         5  s32   IN            255  input.1.abs-rudder-fuzz
         5  bit   OUT          TRUE  input.1.abs-rudder-is-neg
         5  bit   OUT         FALSE  input.1.abs-rudder-is-pos
         5  float IN        32767.5  input.1.abs-rudder-offset
         5  float OUT    -0.9102464  input.1.abs-rudder-position
         5  float IN        32767.5  input.1.abs-rudder-scale
         5  s32   OUT          2947  input.1.abs-rx-counts
         5  s32   IN           4095  input.1.abs-rx-flat
         5  s32   IN            255  input.1.abs-rx-fuzz
         5  bit   OUT          TRUE  input.1.abs-rx-is-neg
         5  bit   OUT         FALSE  input.1.abs-rx-is-pos
         5  float IN        32767.5  input.1.abs-rx-offset
         5  float OUT    -0.9100633  input.1.abs-rx-position
         5  float IN        32767.5  input.1.abs-rx-scale
         5  s32   OUT         65535  input.1.abs-ry-counts
         5  s32   IN           4095  input.1.abs-ry-flat
         5  s32   IN            255  input.1.abs-ry-fuzz
         5  bit   OUT         FALSE  input.1.abs-ry-is-neg
         5  bit   OUT          TRUE  input.1.abs-ry-is-pos
         5  float IN        32767.5  input.1.abs-ry-offset
         5  float OUT             1  input.1.abs-ry-position
         5  float IN        32767.5  input.1.abs-ry-scale
         5  s32   OUT         65535  input.1.abs-rz-counts
         5  s32   IN           4095  input.1.abs-rz-flat
         5  s32   IN            255  input.1.abs-rz-fuzz
         5  bit   OUT         FALSE  input.1.abs-rz-is-neg
         5  bit   OUT          TRUE  input.1.abs-rz-is-pos
         5  float IN        32767.5  input.1.abs-rz-offset
         5  float OUT             1  input.1.abs-rz-position
         5  float IN        32767.5  input.1.abs-rz-scale
         5  s32   OUT         65535  input.1.abs-throttle-counts
         5  s32   IN           4095  input.1.abs-throttle-flat
         5  s32   IN            255  input.1.abs-throttle-fuzz
         5  bit   OUT         FALSE  input.1.abs-throttle-is-neg
         5  bit   OUT          TRUE  input.1.abs-throttle-is-pos
         5  float IN        32767.5  input.1.abs-throttle-offset
         5  float OUT             1  input.1.abs-throttle-position
         5  float IN        32767.5  input.1.abs-throttle-scale
         5  s32   OUT          2957  input.1.abs-wheel-counts
         5  s32   IN           4095  input.1.abs-wheel-flat
         5  s32   IN            255  input.1.abs-wheel-fuzz
         5  bit   OUT          TRUE  input.1.abs-wheel-is-neg
         5  bit   OUT         FALSE  input.1.abs-wheel-is-pos
         5  float IN        32767.5  input.1.abs-wheel-offset
         5  float OUT    -0.9097581  input.1.abs-wheel-position
         5  float IN        32767.5  input.1.abs-wheel-scale
         5  s32   OUT          2942  input.1.abs-x-counts
         5  s32   IN           4095  input.1.abs-x-flat
         5  s32   IN            255  input.1.abs-x-fuzz
         5  bit   OUT          TRUE  input.1.abs-x-is-neg
         5  bit   OUT         FALSE  input.1.abs-x-is-pos
         5  float IN        32767.5  input.1.abs-x-offset
         5  float OUT    -0.9102159  input.1.abs-x-position
         5  float IN        32767.5  input.1.abs-x-scale
         5  s32   OUT          2942  input.1.abs-y-counts
         5  s32   IN           4095  input.1.abs-y-flat
         5  s32   IN            255  input.1.abs-y-fuzz
         5  bit   OUT          TRUE  input.1.abs-y-is-neg
         5  bit   OUT         FALSE  input.1.abs-y-is-pos
         5  float IN        32767.5  input.1.abs-y-offset
         5  float OUT    -0.9102159  input.1.abs-y-position
         5  float IN        32767.5  input.1.abs-y-scale
         5  s32   OUT          2940  input.1.abs-z-counts
         5  s32   IN           4095  input.1.abs-z-flat
         5  s32   IN            255  input.1.abs-z-fuzz
         5  bit   OUT          TRUE  input.1.abs-z-is-neg
         5  bit   OUT         FALSE  input.1.abs-z-is-pos
         5  float IN        32767.5  input.1.abs-z-offset
         5  float OUT     -0.910277  input.1.abs-z-position
         5  float IN        32767.5  input.1.abs-z-scale
    
    ... snippage ...
    Parameters:
    Owner   Type  Dir         Value  Name
         5  s32   RO          65535  input.0.abs-rudder-max
         5  s32   RO              0  input.0.abs-rudder-min
         5  s32   RO          65535  input.0.abs-rx-max
         5  s32   RO              0  input.0.abs-rx-min
         5  s32   RO          65535  input.0.abs-ry-max
         5  s32   RO              0  input.0.abs-ry-min
         5  s32   RO          65535  input.0.abs-rz-max
         5  s32   RO              0  input.0.abs-rz-min
         5  s32   RO          65535  input.0.abs-throttle-max
         5  s32   RO              0  input.0.abs-throttle-min
         5  s32   RO          65535  input.0.abs-wheel-max
         5  s32   RO              0  input.0.abs-wheel-min
         5  s32   RO          65535  input.0.abs-x-max
         5  s32   RO              0  input.0.abs-x-min
         5  s32   RO          65535  input.0.abs-y-max
         5  s32   RO              0  input.0.abs-y-min
         5  s32   RO          65535  input.0.abs-z-max
         5  s32   RO              0  input.0.abs-z-min
         5  s32   RO          65535  input.1.abs-rudder-max
         5  s32   RO              0  input.1.abs-rudder-min
         5  s32   RO          65535  input.1.abs-rx-max
         5  s32   RO              0  input.1.abs-rx-min
         5  s32   RO          65535  input.1.abs-ry-max
         5  s32   RO              0  input.1.abs-ry-min
         5  s32   RO          65535  input.1.abs-rz-max
         5  s32   RO              0  input.1.abs-rz-min
         5  s32   RO          65535  input.1.abs-throttle-max
         5  s32   RO              0  input.1.abs-throttle-min
         5  s32   RO          65535  input.1.abs-wheel-max
         5  s32   RO              0  input.1.abs-wheel-min
         5  s32   RO          65535  input.1.abs-x-max
         5  s32   RO              0  input.1.abs-x-min
         5  s32   RO          65535  input.1.abs-y-max
         5  s32   RO              0  input.1.abs-y-min
         5  s32   RO          65535  input.1.abs-z-max
         5  s32   RO              0  input.1.abs-z-min
    ... snippage ...
    

    Dan’s program assigns the outputs thusly:

    • Wheel – ambient temperature as measured on TC4 board
    • X Y Z Rudder – thermocouples – channels 1 through 4
    • RX RY RZ  Throttle – thermistors – channels 5 through 8

    I created a huge Eagle device that encapsulates the whole thing. A simple demo schematic includes the constants that make the temperatures come out in °C:

    TC4Server - Eagle Schematic
    TC4Server – Eagle Schematic

    That picture produces this HAL file:

    # HAL config file automatically generated by Eagle-CAD ULP:
    # [/mnt/bulkdata/Project Files/eagle/ulp/hal-write-2.5.ulp]
    # (C) Martin Schoeneck.de 2008
    # Charalampos Alexopoulos 2011
    # Mods Ed Nisley KE4ZNU 2010 2013
    # Path        [/mnt/bulkdata/Project Files/eagle/projects/LinuxCNC for M2/]
    # ProjectName [LinuxCNC M2 - TC4Server Test]
    # File name   [/mnt/bulkdata/Project Files/eagle/projects/LinuxCNC for M2/TC4Server.hal]
    # Created     [20:03:16 03-Jun-2013]
    
    ####################################################
    # Load realtime and userspace modules
    loadusr -W hal_input -A +Leonardo
    loadrt threads name1=servo-thread period1=1000000
    loadrt constant        count=4
    loadrt conv_float_s32        count=2
    
    ####################################################
    # Hook functions into threads
    addf constant.0        servo-thread
    addf constant.1        servo-thread
    addf constant.2        servo-thread
    addf constant.3        servo-thread
    addf conv-float-s32.0        servo-thread
    addf conv-float-s32.1        servo-thread
    
    ####################################################
    # Set parameters
    
    ####################################################
    # Set constants
    setp constant.0.value    10
    setp constant.1.value    2732
    setp constant.2.value    0
    setp constant.3.value    0
    
    ####################################################
    # Connect Modules with nets
    net n_2 constant.2.out conv-float-s32.1.in
    net n_3 constant.3.out conv-float-s32.0.in
    net tc4-ambient input.0.abs-wheel-position
    net tc4-flat input.0.abs-wheel-flat input.0.abs-x-flat input.0.abs-y-flat input.0.abs-z-flat input.0.abs-rudder-flat input.0.abs-rx-flat input.0.abs-ry-flat input.0.abs-rz-flat input.0.abs-throttle-flat conv-float-s32.1.out
    net tc4-fuzz input.0.abs-throttle-fuzz input.0.abs-rz-fuzz input.0.abs-ry-fuzz input.0.abs-rx-fuzz input.0.abs-rudder-fuzz input.0.abs-z-fuzz input.0.abs-y-fuzz input.0.abs-x-fuzz input.0.abs-wheel-fuzz conv-float-s32.0.out
    net tc4-offset input.0.abs-wheel-offset input.0.abs-x-offset input.0.abs-y-offset input.0.abs-z-offset input.0.abs-rudder-offset input.0.abs-rx-offset input.0.abs-ry-offset input.0.abs-rz-offset input.0.abs-throttle-offset constant.1.out
    net tc4-scale input.0.abs-wheel-scale input.0.abs-x-scale input.0.abs-y-scale input.0.abs-z-scale input.0.abs-rudder-scale input.0.abs-rx-scale input.0.abs-ry-scale input.0.abs-rz-scale input.0.abs-throttle-scale constant.0.out
    net tcouple-1 input.0.abs-x-position
    net tcouple-2 input.0.abs-y-position
    net tcouple-3 input.0.abs-z-position
    net tcouple-4 input.0.abs-rudder-position
    net tmistor-5 input.0.abs-rx-position
    net tmistor-6 input.0.abs-ry-position
    net tmistor-7 input.0.abs-rz-position
    net tmistor-8 input.0.abs-throttle-position
    

    Fire it up with halrun to see the temperatures (alphabetically by the pin name):

    halrun -I -f TC4Server.hal
    halcmd: start
    halcmd: show pin *position
    Component Pins:
    Owner   Type  Dir         Value  Name
         5  float OUT          20.9  input.0.abs-rudder-position ==> tcouple-4
         5  float OUT          21.5  input.0.abs-rx-position ==> tmistor-5
         5  float OUT        6280.3  input.0.abs-ry-position ==> tmistor-6
         5  float OUT        6280.3  input.0.abs-rz-position ==> tmistor-7
         5  float OUT        6280.3  input.0.abs-throttle-position ==> tmistor-8
         5  float OUT          22.5  input.0.abs-wheel-position ==> tc4-ambient
         5  float OUT            21  input.0.abs-x-position ==> tcouple-1
         5  float OUT            21  input.0.abs-y-position ==> tcouple-2
         5  float OUT          20.8  input.0.abs-z-position ==> tcouple-3
    

    The sensors do not correspond to the picture at the top: only the first thermocouple and first thermistor are connected ; the ADC returns bogus data for disconnected inputs, which means you must be careful about tightening the wires and checking the result. Dan’s firmware has the ability to disable unused sensors, in which case you get a huge value; when used for heater control, a sensor failing high means the heater will turn off, but, should you use this gadget in a freezer, you might want them to fail low (so modify the code for your own use).

    The ambient temperature reported for the board runs 1 or 2 °C higher than the actual ambient air temperature, probably because of all those components doing useful things up close to the sensor chip. That particular ambient temperature serves as the cold junction reference for the thermocouples; the other temperatures don’t change very much as the board warms up, so it’s all good.

    Remember to issue the start command in halrun, because otherwise nothing changes.

    Also remember that you must configure TC4Server with the thermistor characteristics before you use it as a hal_input device.