Programming the TFD 500


(Thanks to Vincenz Dreger for reverse engineering and sending me the protocol.)

Caveat: please note that there seems to be no official documentation about the used protocol (but see “S” command below), and everything described here is the result of snooping the USB bus and analyzing the data when controlling the logger via the Windows software. So, the information here might be (partially) wrong and/or incomplete. Use at your own risk.

The built-in USB-Chip is a CP2102 from Silicon Laboratories (SiLabs).

ELV has changed the VID/PID to 18EF/E032. If you’re running on older Linux kernel, you might therefore need to use an updated kernel driver (cp201x) provided with the script on GitHub. Use lsusb to check if the TFD500 is known.

The serial interface parameters are 115200,8N1. The protocol is simple: the PC sends a command sequence to the logger and the logger answers with an appropriate message. All data transfers are in ASCII format with the exception of the actual data points, which will be sent in binary format.

The command sequences are case sensitive. Commands themselves are single characters and — depending on the command — may be followed by parameters. All parameters must be specified immediately after the command (no space between command and parameter, but there may be spaces between individual parameters). The response always starts with repeating the command character, eventually followed by the actual value of the response. The protocol does not use a start or stop byte.

The data logger can be read out during a recording but configuration can only be changed when the recording was stopped.

Known query command sequences

Command: v
Parameters: <none>
Response: v<Major.Minor.Revision><cr><lf>
Example: v1.0.005
Description:Get version number as a string.

Command: a
Parameters: <none>
Response: a<value>
Example: a0
Description:Check whether or not the logger is currently recording. <value> is either 0 (not recording) or 1 (recording in progress)

Command: o
Parameters: <none>
Response: oC<value> I<value> T<> <HH:MM:SS>
Example: oC1 I2 T20.07.15 12:34:56
Description:C=recording mode (0: Temp, 1: Temp+Humidity); I=recording interval (0: 10sec, 1: 1min, 2: 5min); T=Current date (day.month.year) and current time (hour:minutes:seconds)

Command: d
Parameters: <none>
Response: d<numrecords> <> <HH:MM:SS>
Example: d000010 20.07.15 11:44:56
Description:Get number of records and start date/time. <numrecords> is a 6-digit number with leading zeroes. During recording, the record number changes only when a complete data block (256 bytes) has been written to the flash memory.

Command: F
Parameters: <recordnum>
Response: F<thi tlo ... (256 Bytes)> or F<thi tlo hum ...(256 Bytes)>
Example: F0000
Description:Read a binary data block of 256 bytes from flash memory. Parameter is the 4-digit record number (with leading zeroes) to read. Block counting starts at zero (i.e. 0000). Depending on the logging mode, either two or three bytes per data point will be sent. The temperature values are to be interpreted as 16bit values (MSB first) with 1/10°C resolution. The humidity value can be taken directly. Because the USB protocol is block oriented, the last data block may contain more data points than available. These excess points have to be ignored. In addition, for data blocks containing humidity values, only the first 255 bytes are used.

In addition to the above query commands, there’s another method to read the data records: if you send an “S” character, the logger immediately starts printing data records (as text using “OpenFormat”) until either the end or you send an “E” character. The following is an example output:

$N$;TFD500: 0xD762D0175B4F0F30
$C$;Temperatur[°C,T];rel. Huminity[%];abs. Huminity[g/m^3];Dew Point[°C,DP]
$+28.6; 50;+14.05;17.2
$+28.7; 50;+14.12;17.2
$+28.6; 50;+14.05;17.2
$+28.7; 50;+14.12;17.2
$+28.7; 51;+14.41;17.6
$+28.7; 50;+14.12;17.2
$+28.7; 50;+14.12;17.2

And yes, as of version v01.00.05, there are spelling errors in the output (still not corrected in v01.00.06, a.k.a. v1.1.000).

As far as I know, LogView can be used to read this format. The python script does not use it (but it can also calculate approximate values for absolute humidity and the dew point).

Known configure command sequences

Command: T
Parameters: HH:MM:SS
Response: T
Example: T20.07.15 12:34:56
Description:Set the internal realtime clock.

Command: C
Parameters: <mode>
Response: C
Example: C1
Description:Set the recording mode. 0 = temperature only, 1 = temperature and humidity

Command: I
Parameters: 0 = 10 seconds interval, 1 = 1 minute interval, 2 = 5 minutes interval
Response: I
Example: I0
Description:Set the recording interval.

Command: R
Parameters: <none>
Response: R
Example: R
Description:Clear the flash memory. Apart from the data record, this - unfortunately - also resets the internal clock and deletes the last used configuration.

Command: X
Parameters: <none>
Response: X
Example: X
Description:Factory reset. Restore all factory defaults, set clock to 01.01.00 00:00:00 and reboot.

Command: !
Parameters: <none>
Example: !
Description:Upon receiving this command, the logger enters bootloader mode.