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: Science

If you measure something often enough, it becomes science

  • Makergear M2 vs. LinuxCNC: Project Overview

    M2 - cushwa Owl - half scale
    M2 – cushwa Owl – half scale

    During the course of my Makerbot Thing-O-Matic experience, I concluded:

    • Enthusiasm may get a product out, but engineering makes it work
    • Plywood and plastic do not produce a stable 3D printer
    • Measurements matter
    • 8-bit microcontrollers belong in the dustbin of history

    With that in mind, I’ve long thought that LinuxCNC (formerly EMC2) would provide a much better basis for the control software required for a 3D printer than the current crop of Arduino-based microcontrollers. LinuxCNC provides:

    • Hard real time motion control with proven performance
    • A robust, well-defined hardware interface layer
    • Ladder-logic machine control
    • Isolated userspace programming
    • Access to a complete Linux distro’s wealth of programs / utilities
    • Access to an x86 PC’s wealth of hardware gadgetry

    Rather than (try to) force-fit new functions in an Arduino microcontroller, I decided it would be interesting to retrofit a DIY 3D printer with a LinuxCNC controller, improve the basic hardware control and sensing, instrument the extruder, then take measurements that might shed some light on DIY 3D printing’s current shortcomings.

    The overall plan looks like this:

    • Start with a Makergear M2
    • See what the stock hardware can do
    • Replace the RAMBo controller with LinuxCNC
    • See what the hardware can do with better drivers
    • Adapt the G-Code / M-Code processing to use more-or-less stock Marlin G-Code
    • Add useful controllers along the lines of the Joggy Thing
    • Improve the platform height / level sensing
    • Rebuild the extruder with temperature and force sensors
    • Start taking measurements!

    My reasons for choosing the Makergear M2 as the basis for this project should be obvious:

    • All metal: no plywood, no acrylic (albeit a plastic filament drive)
    • Decent stepper motors (with one notable exception)
    • Reasonable hot end design
    • Good reputation

    The first step of the overall plan included a meticulously documented M2 build that I figured would take a month or two, what with the usual snafus and gotchas that accompany building any complex mechanism. Quite by coincidence, a huge box arrived on my birthday (the Thing-O-Matic arrived on Christmas Eve, so perhaps this is a tradition), the day when I learned that Mad Phil had entered his final weeks of life.

    As the Yiddish proverb puts it: If you wish to hear G*d laugh, tell him of your plans.

    So I converted a box of parts into a functional M2 3D printer over the course of four intense days, alternating between our living room floor and a card table in Phil’s home office, showing him how things worked, getting his advice & suggestions, and swapping “Do you remember when?” stories. Another few days sufficed for software installation, configuration, and basic tuneup; I managed to show him some shiny plastic doodads just before he departed consensus reality; as nearly as I can tell, we both benefited from the distractions.

    Which means I don’t have many pictures or much documentation of the in-process tweakage that produced a functional printer. The next week or so of posts should cover the key points in enough detail to be useful.

    Not to spoil the plot or anything: a stock M2 works wonderfully well.

    Owl - half size - left
    Owl – half size – left

    For example, a half-scale cushwa owl printed in PLA at 165 °C with no bed cooling and these Slic3r parameters:

    • 500 mm/s move
    • 300 mm/s infill
    • 200 mm/s solid infill
    • 100 mm/s internal perimeter
    • 50 mm/s bottom layer
    • 30 mm/s external perimeter
    • 1 mm retract @ 300 mm/s

    The beak came out slightly droopy and each downward-pointing feather dangles a glittery drop. There’s room for improvement, but that’s pretty good a week after opening a box o’ parts…

  • LED Forward Voltages vs. Color

    Running a random set of colored LEDs from the Basement Laboratory Parts Warehouse Wing through the LED Curve Tracer produced this pleasant plot:

    ROYGBUIW

    The white LED doesn’t match up with either the blue or the UV LED. Perhaps the blue LED uses a completely different chemistry that shoves further to the right than seems proper? I suppose I should run a handful of white, blue, and UV LEDs through the thing just to see what’s going on…

    The Bash / Gnuplot source code:

    #!/bin/sh
    numLEDs=8
    #-- overhead
    export GDFONTPATH="/usr/share/fonts/truetype/"
    base="${1%.*}"
    echo Base name: ${base}
    ofile=${base}.png
    echo Input file: $1
    echo Output file: ${ofile}
    #-- do it
    gnuplot << EOF
    #set term x11
    set term png font "arialbd.ttf" 18 size 950,600
    set output "${ofile}"
    set title "${base}"
    set key noautotitles
    unset mouse
    set bmargin 4
    set grid xtics ytics
    set xlabel "Forward Voltage - V"
    set format x "%4.1f"
    set xrange [0.5:4.5]
    #set xtics 0,5
    set mxtics 2
    #set logscale y
    #set ytics nomirror autofreq
    set ylabel "Current - mA"
    set format y "%3.0f"
    set yrange [0:35]
    set mytics 2
    #set y2label "right side variable"
    #set y2tics nomirror autofreq 2
    #set format y2 "%3.0f"
    #set y2range [0:200]
    #set y2tics 32
    #set rmargin 9
    set datafile separator whitespace
    set label 1 "IR" at 1.32,32 center
    set label 2 "R"  at 1.79,32 center
    set label 3 "O"  at 2.10,32 center
    set label 4 "Y"  at 2.65,32 center
    set label 5 "G"  at 2.42,32 center
    set label 6 "B"  at 4.05,32 center
    set label 7 "UV" at 3.90,32 center
    set label 8 "W"  at 3.25,32 center
    #set arrow from 2.100,32 to 2.125,31 lt 1 lw 2 lc 0
    plot \
     "$1" index 0 using (\$5/1000):(\$2/1000) with linespoints pt 1 lw 2 lc rgb "red" ,\
     "$1" index 1 using (\$5/1000):(\$2/1000) with linespoints pt 1 lw 2 lc rgb "orange" ,\
     "$1" index 2 using (\$5/1000):(\$2/1000) with linespoints pt 1 lw 2 lc rgb "dark-yellow" ,\
     "$1" index 3 using (\$5/1000):(\$2/1000) with linespoints pt 1 lw 2 lc rgb "green" ,\
     "$1" index 4 using (\$5/1000):(\$2/1000) with linespoints pt 1 lw 2 lc rgb "blue" ,\
     "$1" index 5 using (\$5/1000):(\$2/1000) with linespoints pt 1 lw 2 lc rgb "purple" ,\
     "$1" index 6 using (\$5/1000):(\$2/1000) with linespoints pt 1 lw 2 lc rgb "magenta" ,\
     "$1" index 7 using (\$5/1000):(\$2/1000) with linespoints pt 1 lw 2 lc rgb "dark-gray"
    EOF
    

    And the raw data file:

    # LED Curve Tracer
    # Ed Nisley - KE4ZNU - March 2013
    # VCC at LED: 4897 mV
    # Bandgap reference voltage: 1041 mV
    
    # Insert LED, press button 1 to start...
    # INOM	ILED		VccLED	VD	VLED		VG	VS	VGS VDS <--- LED 1
    0	0	4892		3889		1002		0	0	0	3889
    5	4613		4892		3264		1627		1990		48	1942		3216
    10	10148	4892		3216		1675		2092		106 1985		3109
    15	15223	4892		3182		1709		2199		159 2039		3022
    20	19836	4892		3148		1743		2271		208 2063		2940
    25	24910	4897		3129		1767		2354		261 2092		2867
    30	30446	4897		3104		1792		2431		319 2111		2785
    
    # Insert LED, press button 1 to start...
    # INOM	ILED		VccLED	VD	VLED		VG	VS	VGS VDS <--- LED 2
    0	0	4892		3884		1007		0	0	0	3884
    5	4613		4892		3124		1767		1985		48	1937		3075
    10	9687		4897		3037		1860		2111		101 2010		2935
    15	14761	4897		2964		1932		2189		155 2034		2809
    20	19836	4897		2906		1990		2271		208 2063		2697
    25	24910	4897		2848		2048		2349		261 2087		2586
    30	30446	4892		2794		2097		2431		319 2111		2475
    
    # Insert LED, press button 1 to start...
    # INOM	ILED		VccLED	VD	VLED		VG	VS	VGS VDS <--- LED 3
    0	0	4892		3826		1065		0	0	0	3826
    5	4613		4897		2862		2034		1990		48	1942		2814
    10	10148	4897		2688		2208		2097		106 1990		2581
    15	15223	4897		2552		2344		2194		159 2034		2392
    20	19836	4892		2436		2455		2276		208 2068		2228
    25	24910	4897		2349		2547		2354		261 2092		2087
    30	29985	4897		2257		2639		2426		314 2111		1942
    
    # Insert LED, press button 1 to start...
    # INOM	ILED		VccLED	VD	VLED		VG	VS	VGS VDS <--- LED 4
    0	0	4892		3734		1157		0	0	0	3734
    5	5074		4892		2935		1956		1976		53	1922		2882
    10	10148	4897		2823		2073		2102		106 1995		2717
    15	15223	4892		2722		2170		2199		159 2039		2562
    20	20297	4897		2649		2247		2276		213 2063		2436
    25	24910	4897		2567		2329		2349		261 2087		2305
    30	29985	4897		2489		2407		2426		314 2111		2174
    
    # Insert LED, press button 1 to start...
    # INOM	ILED		VccLED	VD	VLED		VG	VS	VGS VDS <--- LED 5
    0	0	4892		4485		406 0	0	0	4485
    5	4613		4897		1724		3172		1990		48	1942		1675
    10	10148	4892		1443		3448		2097		106 1990		1336
    15	15223	4897		1249		3647		2199		159 2039		1089
    20	19836	4892		1099		3792		2276		208 2068		891
    25	24910	4897		983 3913		2354		261 2092		721
    30	29985	4892		862 4030		2426		314 2111		547
    
    # Insert LED, press button 1 to start...
    # INOM	ILED		VccLED	VD	VLED		VG	VS	VGS VDS <--- LED 6
    0	0	4892		4165		726 0	0	0	4165
    5	5074		4892		1448		3443		1985		53	1932		1395
    10	10148	4897		1322		3574		2102		106 1995		1215
    15	15223	4892		1220		3671		2194		159 2034		1060
    20	20297	4892		1147		3744		2276		213 2063		934
    25	25372	4892		1075		3816		2354		266 2087		808
    30	29985	4892		1002		3889		2426		314 2111		687
    
    # Insert LED, press button 1 to start...
    # INOM	ILED		VccLED	VD	VLED		VG	VS	VGS VDS <--- LED 7
    0	0	4892		4247		644 0	0	0	4247
    5	5074		4892		3647		1244		1981		53	1927		3594
    10	10148	4892		3618		1273		2107		106 2000		3511
    15	14761	4892		3603		1288		2170		155 2015		3448
    20	20297	4892		3584		1307		2271		213 2058		3371
    25	25372	4892		3574		1317		2354		266 2087		3308
    30	29523	4892		3565		1327		2412		310 2102		3255
    
    # Insert LED, press button 1 to start...
    # INOM	ILED		VccLED	VD	VLED		VG	VS	VGS VDS <--- LED 8
    0	0	4892		4945		-53 0	0	0	4945
    5	5074		4892		2160		2731		1985		53	1932		2107
    10	10148	4892		2034		2857		2097		106 1990		1927
    15	15223	4897		1927		2969		2194		159 2034		1767
    20	19836	4892		1826		3066		2271		208 2063		1617
    25	25372	4897		1734		3162		2349		266 2082		1467
    30	29523	4892		1666		3225		2412		310 2102		1356
    
    # Insert LED, press button 1 to start...
    
  • Stepper Motor Thermal Coefficient vs. Thermal Compound and Forced Air

    Prompted by that comment, a bit more data emerges.

    This unsteady ziggurat barely supports the aluminum CPU heatsink atop a PC CPU exhaust duct; the two came from different PCs and have no relation to each other.  The vise in the background keeps the whole affair from falling over. The fan sucks air through the heatsink and exhausts it out the front.

    NEMA 17 Stepper - Heatsink with Fan
    NEMA 17 Stepper – Heatsink with Fan

    Throughout all this, the stepper driver runs at a bit over 10 k step/sec, tuned to avoid the howling mechanical resonances in that stack. At 1/8 microstepping, that’s 6.25 rev/s = 375 RPM, which would drive the Thing-O-Matic at 210 mm/s and the M2 at 225 mm/s. Your speed will vary, of course, depending on the pulley diameter / number of teeth / belt pitch, etc.

    Under the same conditions as before (i.e., no thermal compound, fan off), the stepper stabilized at 143 °F = 62 °C in the 57 °F = 14 °C Basement Laboratory ambient, with 1.91 A peak current (I don’t believe that second decimal place, either) and a 6.6 °C/W case-to-ambient coefficient. That’s close enough to the 63 °C and 6.7 °C/W coefficient from the earlier test, so the conditions seem roughly the same.

    Smoothing a thin layer of heatsink compound on the butt of the motor, then squishing it firmly atop the heatsink, cut the temperature to 130 °F = 53 °C without the fan. That suggests the case-to-ambient coefficient is now 5.3 °C/W: the thermal compound helps by 1.3 °C/W.

    Turning on the fan drops the case temperature to 84 °F = 29 °C, which works out to a coefficient of 2.1 °C/W. Obviously, moving air over that heatsink helps the cooling a lot: the heatsink felt cold to the touch and the motor case was barely warm.

    Increasing the current to 2.37 A dissipates 11.2 W, which would be scary without the heatsink and air flow. The temperature stabilized at 91 °F = 33 °C, for a coefficient of 1.7 °C/W.

    At 2.83 A = 16 W, the temperature rises to 100 °F = 38 °C, with a coefficient of 1.5 °C/W. While it’s not unstoppable with that much current, the motor has plenty of torque! The motor becomes pleasantly warm, the heatsink stays just above cool, and all seems right with the world. I suspect the windings get a bit toasty in there, but they can’t possibly be worse off than inside a case at boiling-water temperatures.

    Using the original insulated-motor coefficient of 19 °C/W, 16 W would cook the motor at 320 °C. Perhaps the case would make a nice extruder heater after it stopped being a motor?

    [Update: See the comments for the results of just blowing air over the motor case.]

  • Stepper Motor Thermal Coefficient

    You’ve probably seen this exchange on whatever DIY 3D printing forum you monitor:

    1. My stepper motors get scorching hot, what should I do?
    2. Turn down the current!
    3. That worked great, but …
    4. … now all my objects have a shift in the middle.
    5. Your motor is losing steps: turn up the current!
    6. Uh, right.
    NEMA 17 Stepper on cloth
    NEMA 17 Stepper on cloth

    So, with that setup on the bench, I ran a simple experiment with current, temperature, and heat transfer. Most DIY 3D printers have stepper motors attached to a plywood chassis or plastic holder, so the first data point comes from a motor with no mechanical thermal path to the outside world (which is the Basement Laboratory at 14 °C ambient).

    Running at about 1200 step/s with a winding current of 1 A peak from a 24 A supply, the motor stabilized at 52 °C = 125 °F after half an hour.

    Both windings have a 2 Ω resistance and carry 1 A peak = 0.7 A rms, so the total power dissipation is:

    2 × [(1 A / √2)2 × 2 Ω] = 2 W

    That’s the same power produced with the motor stopped at a full step position, where the peak current flows in a single winding and the other winding carries zero current:

    (1 A)2 × 2 Ω = 2 W

    The temperature rise suggests a thermal coefficient of about 19 °C/W = (52 °C – 14 °C) / 2 W.

    The next current setting on the driver is 1.46 A, which doubles the power dissipation to 4.3 W. Assuming a large number of linearities, that would cook the motor at 82 °C = 180 °F above ambient. Even though the motor could probably withstand that temperature, for what should be obvious reasons I didn’t go there.

    Instead, I parked the motor atop a big CPU heatsink harvested from an obsolete PC, sans thermal compound, mechanical fitting, and anything more secure than gravity holding it in place:

    NEMA 17 Stepper on Heatsink
    NEMA 17 Stepper on Heatsink

    The results:

    Ambient 14 °C
    Winding 2 ohm
    A pk A rms Power W Case °C °C/W amb °C/W incr
    1.00 0.71 2.0 28 7.0 7.0
    1.46 1.03 4.3 42 6.6 6.2
    1.91 1.35 7.3 63 6.7 6.9

    The thermal coefficients represent the combination of all interfaces from motor case to ambient, but the case and heatsink stabilized to about the same temperature, so the main limit (as always) will be heat transfer to ambient air. Obviously, the heatsink sits in the wrong orientation with little-to-no air flow, not to mention that the butt end of a stepper motor isn’t precisely machined and has plenty of air between the two surfaces. Improving all that would be in the nature of fine tuning and should substantially lower the coefficient.

    What’s of interest: just perching the motor on a big chunk of aluminum dropped the case temperature 24 °C without no further effort.

    Blowing air over the case (probably) won’t be nearly as effective. Epoxy-ing a liquid-cooled cold plate to the end cap would improve the situation beyond all reasonable bounds, plus confer extreme geek cred.

    Hmmm, the Warehouse Wing does have some copper tubing…

  • Monthly Science: Patio Ground Temperature

    The patio at the rear of our house is a six inch concrete slab with a five foot “crawlspace” below it, with a HOBO datalogger pendant in the dirt near the pole at the middle of the I beam supporting the slab. The pendant is very close to the surface, so there’s a big diurnal temperature variation, but it still gives a reasonable picture of seasonal change.

    A configuration setting in Hoboware determines whether it stores / exports dates with years having two digits or four digits. As you might expect, over the course of five years the dates have both formats, but there’s always a blank separating the date and the time:

    grep "/12 " /tmp/data.csv | head -1
    1,11/09/12 08:45:00 ,49.050,,,,
    grep "/2012 " /tmp/data.csv | head -1
    2235,01/01/2012 00:00:00,44.560,0.0,,,,
    

    This burst of sed regex line noise normalizes all years to four digits:

    sed 's/\/\([0-9][0-9]\) /\/20\1 /' whatever.csv
    

    The parenthesized subexpression matches the digits of a two digit year preceding a blank, then the \1 plugs it into the right spot in the output. This suffers from the usual failure when the century rolls over, but frankly, my dear readers, I don’t give a damn. The backslashes escape forward slashes and parentheses, in addition to making the regex pretty much write-only.

    The plot shows the expected annual variation:

    Under patio - Ground - Center
    Under patio – Ground – Center

    The periodic upward spikes happen when I carry the logger to the Token Windows Laptop and read it out; the air temperature upstairs is always warmer than the dirt under the patio.

    The Bash and gnuplot script that produced the graph:

    #!/bin/sh
    #-- overhead
    export GDFONTPATH="/usr/share/fonts/truetype/"
    base="${1%.*}"
    echo Base name: ${base}
    ofile=${base}.png
    tfile=$(tempfile)
    echo Input file: $1
    echo Temporary file: ${tfile}
    echo Output file: ${ofile}
    #-- prepare csv Hobo logger file
    sed 's/^\"/#&/' "$1" | sed 's/^.*Logged/#&/' | sed 's/ ,/,/' | sed 's/\/\([0-9][0-9]\) /\/20\1 /' > ${tfile}
    #-- do it
    gnuplot << EOF
    #set term x11
    set term png font "arialbd.ttf" 18 size 950,600
    set output "${ofile}"
    set title "${base}"
    set key noautotitles
    unset mouse
    set bmargin 4
    set grid xtics ytics
    set timefmt "%m/%d/%Y %H:%M:%S"
    set xdata time
    set xlabel "Date"
    set format x "%Y-%m"
    #set xrange [1.8:2.2]
    set xtics font "arial,12"
    #set mxtics 2
    #set logscale y
    #set ytics nomirror autofreq
    set ylabel "Temperature - F"
    #set format y "%4.0f"
    #set yrange [30:90]
    #set mytics 2
    #set y2label "right side variable"
    #set y2tics nomirror autofreq 2
    #set format y2 "%3.0f"
    #set y2range [0:200]
    #set y2tics 32
    #set rmargin 9
    set datafile separator ","
    #set label 1 "label text" at 2.100,110 right font "arialbd,18"
    #set arrow from 2.100,110 to 2.105,103 lt 1 lw 2 lc 0
    plot	\
        "${tfile}" using 2:3 with lines lt 3
    EOF
    
  • Xubuntu 12.10 vs. Dual Monitors: Regression

    It used to be that using two monitors with two separate X sessions in Linux actually worked. Then they improved things so it stopped working out of the box, but you could force it to work with a bit of effort. Further improvements made the workarounds more difficult. Now, with Xubuntu 12.10, it seems impossible.

    This. Is. Not. Progress.

    Experimenting will require considerable restarting of the X server, which nowadays requires, by default, rebooting the box. In the Bad Old Days, you could hit Ctrl-Alt-Backspace to restart the X server (and, en passant, blow away all unsaved data in your session). My suggestions about re-enabling it no longer work and, worse, the suggestions there about:

    • Pressing Right-Alt + Sysreq + K
    • Enabling DontZap

    do not work, either. I’m no longer surprised by any of this.

    Fortunately, as suggested at the same spot, this works:

    • Create if missing: ~/.xprofile
    • Add: setxkbmap -option terminate:ctrl_alt_bksp
    • Make it executable: chmod u+x .xprofile

    But it’s per-user, so it works only while you’re logged in, which means you can’t restart X from the login screen. This is marginally OK.

    So. We begin.

    This box (an off-lease Dell Optiplex 780, Core 2 Duo E8400 3.0 GHz) now has a Jaton GeForce GT430 nVidia video card with two DVI outputs.

    In order to get decent performance, you must use the nVidia proprietary driver. Installing the nvidia-current package pulls in, as of this writing, 304. The nVidia driver now ignores the rotate option and the randrrotation option in xorg.conf. Adding the {Rotation=Left} meta-option to the portrait monitor or enabling Xinerama kills xrandr.

    Not having xrandr used to not be fatal, but now OpenSCAD (among others) requires xrandr to be both present and active. Any solution that doesn’t allow xrandr isn’t feasible.

    Despite notes suggesting that nVidia’s TwinView kills xrandr, it doesn’t (perversely, Xinerama should allow it and doesn’t; perhaps I misunderstand what’s going on). Add another line to .xprofile:
    xrandr --output DVI-I-3 --rotate left
    You discover which output to use by parsing the output of xrandr without any parameters:

    $ xrandr
    Screen 0: minimum 8 x 8, current 2650 x 1680, maximum 16384 x 16384
    DVI-I-0 disconnected (normal left inverted right x axis y axis)
    DVI-I-1 disconnected (normal left inverted right x axis y axis)
    DVI-I-2 connected 1600x1200+0+0 (normal left inverted right x axis y axis) 367mm x 275mm
       1600x1200      60.0*+
       1280x1024      75.0     60.0
       1152x864       75.0
       1024x768       75.0     60.0
       800x600        75.0     60.3
       640x480        75.0     59.9
    DVI-I-3 connected 1050x1680+1600+0 left (normal left inverted right x axis y axis) 434mm x 270mm
       1680x1050      59.9*+
       1280x1024      75.0     60.0
       1152x864       75.0
       1024x768       75.0     60.0
       800x600        75.0     60.3
       640x480        75.0     59.9
    HDMI-0 disconnected (normal left inverted right x axis y axis)
    

    Why DVI-I-0 and DVI-I-1 are disconnected is not explained. There is an HDMI jack that I’m not using, so that one does make sense. The output shows the portrait monitor on DVI-I-3 as rotated.

    This is a single X session, so the two monitors show sections of a larger workspace. The cursor moves freely across the junction, it doesn’t vanish below the landscape montitor, and windows maximize properly to fill the single monitor they start in.

    This is not what I want, because I cannot independently flip the workspaces on the two monitors. It’s possible to force one of the windows on the portrait monitor to “always on top”, but that means I have only one program accessible on that monitor, which isn’t usually the case.

    This. Is. Not. Progress.

    But it seems to be as good as it gets these days…

  • Monthly Science: Data Logging

    Starting in late 2006, I’ve have several Hobo dataloggers recording the temperature / humidity / light at various locations, under the principle that if you observe something long enough, it turns into science. Regrettably, logging the data is one thing, actually processing it into usable information is entirely another; there’s never a good time for the latter. Perhaps if I break it down into monthly chunks, I can actually make some progress on getting it done.

    The first problem is that the Hobo dataloggers lack a convenient user interface: the only way to extract data is through the Hoboware graphical program. Unfortunately, Hoboware stores the extracted data in their proprietary format, locked away from any other program. I eventually discovered the configuration setting that automatically saves the data in CSV format, but I didn’t find that until rather late in the game, didn’t always set it with new versions, and it seems their CSV format has changed slightly over the years. Thus, one of my to-do items is to manually process the remaining Hoboware files to produce the corresponding CSV files, then convert those into a standard format that’s useful with, say, Gnuplot.

    The intent is that I can simply concatenate all the CSV data files for a given sensor, run them through a Bash script to sanitize the data, plot what emerges, and then maybe slice-and-dice the data a few different ways. The less manual processing this requires, the more it will get done…

    But the first step is to show that something emerges from the data, so here’s the last year of data (recorded in 2012, which includes a bit of 2011 and not quite up to the end of 2012) from the logger that’s been monitoring the air temperature of the Basement Laboratory and the temperature at the house water inlet. I assume the minimum water temperature on the pipe at the basement wall tracks the ground temperature four or five feet down from the surface; more on the hardware behind the data in a while.

    Town_Water_Inlet
    Town_Water_Inlet

    The fuzz on the purple trace shows the relatively rapid temperature variation as we draw water from the supply: it falls as water moves into the house and rises as still water warms. The inlet always remains cooler than the air temperature, because it’s cemented to the wall, but a closer look (again, in a while) shows a nice exponential curve. The thin straight-line sections show gaps in the data record: sometimes I forget to do my monthly science for a few days or weeks.

    An extract from the CSV files, including some data not plotted above:

    "Plot Title: Town Water Inlet "
    "#","Time, GMT-04:00","Temp, °F","RH, %","Temp, °F","Host Connected","Stopped","End Of File"
    1,09/25/2012 09:20:00,66.344,58.707,64.632,,,
    2,09/25/2012 09:25:00,66.173,57.579,64.459,,,
    -- snippage --
    12962,11/09/2012 09:25:00,60.174,54.301,56.685,,,
    12963,11/09/2012 09:28:48,,,,Logged,,
    12964,11/09/2012 09:28:55,,,,,Logged,Logged
    -- snippage --
    "Plot Title: Town Water Inlet "
    "#","Time, GMT-05:00","Temp, °F()","RH, %()","Temp, °F()","End Of File()"
    1,11/09/12 08:35:00 ,64.247,52.282,56.728,
    2,11/09/12 08:40:00 ,63.304,51.465,56.728,
    -- snippage --
    14473,12/29/12 14:35:00 ,56.599,51.454,48.895,
    14474,12/29/12 14:40:00 ,56.599,51.485,49.116,Logged
    

    A touch of sed can handle the reformatting I’ve seen so far:

    • Convert headers to comments: sed 's/^\"/#&/'
    • Convert non-data events to comments: sed 's/^.*Logged/#&/'
    • Remove spurious trailing blanks in data fields: sed 's/ ,/,/'

    Here’s the Bash and Gnuplot source code that produced the graph, complete with cruft that may come in handy later:

    #!/bin/sh
    #-- overhead
    export GDFONTPATH="/usr/share/fonts/truetype/"
    base="${1%.*}"
    echo Base name: ${base}
    tfile1=$(tempfile)
    tfile2=$(tempfile)
    ofile=${base}.png
    echo Input file: $1
    echo Temporary files: ${tfile1} ${tfile2}
    echo Output file: ${ofile}
    #-- prepare csv Hobo logger file
    sed 's/^\"/#&/' $1 > ${tfile1}
    sed 's/^.*Logged/#&/' ${tfile1} > ${tfile2}
    #-- do it
    gnuplot << EOF
    #set term x11
    set term png font "arialbd.ttf" 18 size 950,600
    set output "${ofile}"
    set title "${base}"
    set key noautotitles
    unset mouse
    set bmargin 4
    set grid xtics ytics
    set timefmt "%m/%d/%Y %H:%M:%S"
    set xdata time
    set xlabel "Week of Year"
    set format x "%W"
    #set xrange [1.8:2.2]
    #set xtics 0,5
    #set mxtics 2
    #set logscale y
    #set ytics nomirror autofreq
    set ylabel "Temperature - F"
    #set format y "%4.0f"
    set yrange [30:90]
    #set mytics 2
    #set y2label "right side variable"
    #set y2tics nomirror autofreq 2
    #set format y2 "%3.0f"
    #set y2range [0:200]
    #set y2tics 32
    #set rmargin 9
    set datafile separator ","
    #set label 1 "label text" at 2.100,110 right font "arialbd,18"
    #set arrow from 2.100,110 to 2.105,103 lt 1 lw 2 lc 0
    plot	\
        "${tfile2}" using 2:3 with lines lt 3 title "Air", \
        "${tfile2}" using 2:5 with lines lt 4 title "Water"
    EOF