Snippets

John Peck Continuously write timestamped data to a file

Created by John Peck
#!/opt/ActiveTcl-8.6/bin/tclsh
# Hey Emacs, use -*- Tcl -*- mode

set scriptname [file rootname $argv0]

package require cmdline
set usage "usage: $scriptname \[options] filename"
set options {
    {o.arg "makedata" "Output file name root (no extension)"}
}

try {
    array set params [::cmdline::getoptions argv $options $usage]
} trap {CMDLINE USAGE} {message optdict} {
    # Trap the usage signal, print the message, and exit the application.
    # Note: Other errors are not caught and passed through to higher levels!
    puts $message
    exit 1
}

# Archive datafile -- where all the data goes
set archive_datafile "$params(o)_archive.csv"

# Data sampling period in milliseconds
set sample_period_ms 100

proc pi {} {return 3.1415926535897931}

proc iterint {start points} {
    # Return a list of increasing integers starting with start with
    # length points
    set count 0
    set intlist [list]
    while {$count < $points} {
	lappend intlist [expr $start + $count]
	incr count
    }
    return $intlist
}

proc write_archive {time_offset_s} {
    # Write a datafile with time,data format
    #
    # Arguments:
    #   time_offset_s -- Unix time stamp from the beginning of execution
    global params
    global archive_datafile
    global sample_period_ms
    try {
	set fid [open $archive_datafile a+]
    } trap {} {message optdict} {
	puts $message
	exit
    }
    set frequency_hz 0.1
    set time_now_ms [clock milliseconds]
    set time_now_s [expr double($time_now_ms)/1000]
    # time_delta_s is a millisecond-resolution stopwatch started at
    # script execution.  The number is in floating-point seconds.
    set time_delta_s [expr $time_now_s - $time_offset_s]
    set ms_remainder [expr int($time_delta_s * 1000 - int($time_delta_s) * 1000)]
    set data [expr sin(2 * [pi] * $frequency_hz * $time_delta_s)]
    # Gnuplot can plot timestamps with ms resolution, but not if
    # they're formatted as unix time stamps.  We have to make a
    # timestamp like:
    # 2019-06-29 18:18:15.891
    # ... by tacking milliseconds onto a conventional clock format.
    set time_string [format "%s.%03d" [clock format [expr int($time_now_s)] -format \
					   "%Y-%m-%d %H:%M:%S"] $ms_remainder]
    puts $fid "$time_string, $data"
    close $fid
    after $sample_period_ms [list write_archive $time_offset_s]
}

try {
    file delete -force $archive_datafile
} trap {} {message optdict} {
    puts $message
    exit
}

set time_offset_s [clock seconds]
after $sample_period_ms [list write_archive $time_offset_s]
vwait forever

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.