I've been trying to figure out a good way to plot some sensor data as it comes in, and I needed a way to simulate that data. I ultimately wanted to get timestamped data into gnuplot, and I knew gnuplot would take time data formatted as Unix Timestamps. I thought, maybe I can use Unix Timestamps with millisecond precision and avoid all the Day/Month/Year formatting. I found out it wasn't going to be that easy.
Gnuplot can accept floating point seconds, but only with the right formatting
Gnuplot won't accept Unix Timestamps with millisecond precision -- the number has to come in as an integer. But it will accept times formatted as %H:%M:%S with floating point seconds. So then I needed to create these millisecond precision stamps. Tcl will give you the milliseconds since 1970, but its clock format command will neither consume this number directly, nor will it consume this number in floating point seconds. The fix, as pointed out by Donal Fellows, is to bolt the seconds and milliseconds together with a format string.
Fakestream creates these stamps to simulate real-time data
I wrote fakestream to continuously write data stamped with these millisecond-precision stamps to a file. The plot below shows gnuplot periodically scanning this file and updating a plot.
The fakestream repository has the Tcl source for this script as well as single file executables for easy distribution. These Starkits and Starpacks are what keep me coming back to Tcl.
I do electronic design for a living, and the CAD package I use
determines the operating system I spend most of my time in. This
means Windows during the day, and Linux at home. Using
Emacs on both platforms gives
me a consistent look and feel. And
is a very nice command shell for Windows.
I also need Tcl on both platforms, and
Emacs gives me a nice way to set the
variable. This tells Tcl where to look for packages you bring in with
package require. The TCLLIBPATH variable is a list of paths, and
Tcl needs to be able to make a list variable out of whatever it finds
in TCLLIBPATH. A space-separated list works very nicely. I have this in my .emacs:
;; Get extra emacs packages -- including some useful
;; string-manipulating functions like string-join
;; Add my local package directory to auto_path. This will be a Tcl
;; list, so the entries should be separated by spaces.
;; Get tklib from https://github.com/tcltk/tklib
Why do I need to (require 'subr-x)? The string-join command is
supposed to be part of Emacs 25, but my Emacs 25.2.2 still chokes on
it at startup without the subr-x package. After evaluating .emacs with M-x eval-buffer:
...you can see that the TCLLIBPATH variable is set, and that Tcl uses it in its auto_path list. I originally installed Tcl using ActiveState's installer, which makes its own changes to auto_path.
I have the very interesting Gub package saved here:
and I can now require it with
...to show that auto_path allowed Tcl to find the local package.
I've been working on a PCB for a small loudspeaker project called
Amey. I showed a
the bare PCB a few weeks before I sent the design to Slingshot
Assembly in Denver. I got the assembled PCBs today:
They installed the snap-in standoffs at each corner on the component
side, which helps to protect the other components during shipping.
That was a nice touch.
Update -- oops, the ADC doesn't have a clock
I made a showstopper mistake with the rev A boards -- I didn't provide
a clock to the I2S ADC. The
PCM1802 ADC from TI can
be an I2S master, but it has no way of generating its own timebase.
The fix is to figure out how to get a clock to the PCM1802. I made a
second PCB to hold the
16.9344 MHz oscillator and its bypass capacitor. You can see the second PCB below.
I carefully wired up the little PCB, and now I see the correct clocks:
The Bus Pirate is a
cheap way to talk to I2C (and a lot of other serial protocol) devices
from your laptop. I use it to bring up new boards -- making sure
everything works before they get integrated into a bigger platform.
Specifically, I've been using the Bus Pirate version 4
Dangerous Prototypes has built
the Bus Pirate's API into the hardware with its binary
firmware mode. This is great, since it means you don't need a
separate piece of software running on your laptop to run the API --
you can use whatever scripting language you want.
Connecting to the BPv4 is just like connecting to any other USB CDC
(ACM) device. The
version 3 Bus Pirate has an FTDI device to handle the communication,
while the BPv4 moves the USB stack into a Microchip PIC. You'll have
the usual first-time problems: Windows wants an INF file, and Ubuntu
wants your user to be in the same group as the device node. I linked
the INF file I used below.
Once those basics are in place, the details of communicating over the
channel are determined by your choice of scripting language. I use
Tcl for things like this, so I need to use commands like chan
configure. The debug log
shown below shows the script doing a brute-force search of all
I'll go into what this potset script is later. For right now,
notice that the script identified two potential device nodes:
ttyACM0 and ttyACM1. The script will connect with the first
device that reponds to a carriage return with HiZ>. The
busbridge repository shows
how I did things. The BPv4 actually has an eeprom that could be used
to "tag" different Bus Pirates if you wanted to work with more than
one at once.
The next step is to activate the BPv4's API to set up SPI or I2C
communication. I'll talk about that later.
The input file is simply Tcl, and is sourced by the main program.
Starting the program with no inputs will create an example.tbi
file in an input directory. This is just some basic organization
-- the program doesn't care about the input file location or its extension.
The seconds_per_inch variable controls how large timeslices will be
relative to their labels. If your timeslice labels don't fit, try
reducing this number.
The timeslice::timeslice function creates a timeslice. For example:
set mario_airborne [timeslice::timeslice 100e-3 red "Mario has jumped"]
...creates a 100ms-long red timeslice with a label. Recognized colors
are black, blue, green, cyan, red, magenta, yellow, and
Creating reference lines (timestamps)
The timeslice::reference function creates a reference line. For
set mario_lands [timeslice::reference "Mario lands on goomba"]
...creates a reference line with a label. The program will assign a
timestamp to the reference line depending on where it lands in its
The timeline::timeline function assembles lists of timeslices into a
timeline. For example:
set mario_list [list $mario_airborne $mario_lands $mario_recovers]
set mario_timeline [timeline::timeline "Mario" $mario_list]
...creates the mario_timeline timeline. Notice that the
mario_lands reference line is in the list of timeslices along with
Processing the input file
I have a history of creating Tcl software used by manufacturing
technicians. These people usually use Windows machines, and they like
being able to choose which version they can run. My executables thus
have their version numbers in their filenames. Use the -h option to
see the usage:
~/projects/eventual/timebars/starpacks $ ./timebars-1.0.2-win32-ix86.exe -h
timebars usage: timebars [options] filename
-d value Minimum depth <50>
-o value Output file name <timebars.fig>
-- Forcibly stop option processing
-help Print this message
-? Print this message
If you don't specify an input file (call the script with no
arguemnts), the script will generate an input directory and an
example file in that directory.
The "minimum depth" parameter is for Xfig. If you already have
graphics drawn in Xfig and you want to add this figure, you'll need to
make sure the depths cooperate to make overlapping elements visible.
I needed to add an array of 0603 LEDs to a loudspeaker drawing (shown below).
Since I've done some scripting for xfig
files before, I thought I'd try that again.
You can see the tiny green LEDs distributed over the big middle
driver. You can find the
script here. You'll
need Tcl and Tcl's cmdline package to run it. Once you've got
things set up, you can see the usage with
~/p/eventual/scripts/boxarc λ tclsh boxarc.tcl -h
boxarc usage: boxarc [options]
-l value Box length (mils) <100>
-w value Box width (mils) <100>
-d value Minimum depth <50>
-r value Arc radius (mils) <1000>
-s value Start angle (degrees) <0>
-e value End angle (degrees) <90>
-n value Number of boxes <10>
-o value Output file name <none>
-- Forcibly stop option processing
-help Print this message
-? Print this message
...and you can get the LEDs shown in the above image with
Xfig is still a very convenient tool for
me, and I need it to work under Cygwin. I've tried to document how
I've been able to get it to work. You will, of course, need to start
by installing Cygwin.
Download the 32-bit (or 64-bit if you're feeling lucky) setup.exe from
cygwin.com. I like to copy it to
my Windows desktop so I can easily run it again when I need to add
packages. The 64-bit version seemed to be missing a few packages the
last time I tried it, and I haven't tried it since then.
Run the installer
Select install from internet. The default installation directory
(C:\cygwin) works for me. I also like to store package information
to C:\cygstore, but this isn't important. After selecting file
locations, you can use the
mirror sites page to find a local
Choose these packages for installation:
...and then Cygwin will decide which dependencies will also need to be
installed. The initial installation takes me about 15 minutes.
Start the Cygwin Terminal
This creates your home directory and some useful configuration files.
Start the X server
Starting the X server with
...will let you keep using the same terminal after the server starts.
I've had some strange problems with this sequence of commands -- it
works for me on a host OS, but it failed at first on a VirtualBox
Windows 7 guest. The fix was to start the XWin Server via the start
menu instead of the command line. After I did that, the command line
started working. Maybe a config file got written? Anyway, now X is
Start xfig to see the problem
I've got xfig 3.2 patchlevel 5c. I add some text to the canvas, then
zoom in. The error message is:
Font size 17 not found, using smaller 12 point
...and the glyphs don't scale with the rest of the canvas -- extremely
Install some font tools
I needed to install the:
...packages via the cygwin installer.
Download ghostscript fonts
I'm not sure where the fonts should be archived, but the file you want
is ghostscript-fonts-std-8.11.tar.gz. It looks like it's hosted
at SourceForge. I make the directory ~/fonts and unpack the file
there. This will make its own fonts directory. Descend into this
Add this new fonts directory to the list known by X
With the X server running,
xset fp+ ~/fonts/fonts
...and you won't see any output.
Test the fix
Fire up xfig again and type some text. Enjoy the nice scaling glyphs
when you change the zoom factor!
You'll probably want to add the export DISPLAY=:0 line to your
.bash_profile or your .bashrc file. Unfortunately, the xset
command won't work until X is actually running. You could add that
line to your .bashrc, but you'd have to make sure you started
X via the start menu before you started the Cygwin Terminal. You
could also simply type bash after starting X to re-run the .bashrc
commands. And there are probably many better ways of doing all this.
...and that's success! Of course, you can make your life easier by
adding the PATH command to your .bashrc or .bash_profile script.
Edit on Saturday, September 24, 2016
I could not install ActiveTcl in a way that allowed an ordinary
user to use teacup. I tried installing everything into
/home/john/opt instead of /opt, but teacup then created a
~/.teapot directory owned by root. So I guess users of "locked
down" systems will need to find another way to get the packages they