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 so that the original SiLabs driver does not work without a modification. (VID:18EF, PID:E032) As of kernel version 4.12.5, the logger will therefore not be recognized by the linux driver (cp201x). A kernel patch has been sent and accepted, but it will probably not be part of the official Linux kernel until 4.15. Until then, you can use the updated kernel driver provided with the script on Github.

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 are 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 spaced 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. The records are a 6-digit number with leading zero. 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 unit. The humidity value can be taken directly. Because the protocol is block oriented, the data record 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, it’s really incorrectly spelled “Huminity” and “Temperatur” is lacking the final “e”.

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.