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

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:

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.