Vernier Go Temp USB device in Linux

From Finninday
Revision as of 15:41, 12 January 2008 by Rday (Talk | contribs)

Jump to: navigation, search

I've got a USB thermometer that is recognized by Linux when I plug it in, but I have no idea how to read it. Here is what I know so far.

/proc/bus/usb/devices says this about it:

T:  Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=1.5 MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=08f7 ProdID=0002 Rev= 1.53
S:  Manufacturer=Vernier Software & Technology
S:  Product=Go! Temp ver 1.53
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=00 Prot=00 Driver=ldusb
E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=10ms

So I assume that /proc/bus/usb/002/002 is the file that corresponds to this device since it is bus 2, device 2.

Looking at that file through octaldump, I see this:

root@weasel:/proc/bus/usb/002# od -c 002
0000000 022 001 020 001  \0  \0  \0  \b 367  \b 002  \0   S 001 001 002
0000020  \0 001  \t 002   "  \0 001 001  \0 200   2  \t 004  \0  \0 001
0000040 003  \0  \0  \0  \t   ! 020 001  \0 001   "   2  \0  \a 005 201
0000060 003  \b  \0  \n
0000064

I'd like it if one of those numbers were a temperature, but I doubt it is that easy.

I'd also like it if setting one of those bits were to control the LEDs on the thermometer...

Perhaps I need a USB sniffer. Does such a thing exist?

Also, udev says that it has created a device for the ldusb driver called /dev/ldusb0 here:

crw-rw---- 1 root root 180, 176 2008-01-05 11:17 /dev/ldusb0

That's hopeful, but how do I poke at that device, exactly?

Googling for ldusb0 I found someone who has the same device ( http://www.thok.org/intranet/python/vernier/README.html) and says that this code works to read it:

#!/usr/bin/python
import time
import struct

ldusb = file("/dev/ldusb0")

time.sleep(0.5)

# for n in range(10):
while True:
    # time.sleep(0.5)
    pkt = ldusb.read(8)
    parsed_pkt = list(struct.unpack("<BBHHH", pkt))
    num_samples = parsed_pkt.pop(0)
    seqno = parsed_pkt.pop(0)
    for sample in range(num_samples):
        print seqno+sample, parsed_pkt[sample]/100.0
    # time.sleep(0.5)

But it doesn't work for me. I picked a bad day to not learn python. Perhaps I can grok it enough to write a perl script to do the same thing.

From the above article:

turns out that an 8-byte read (from /dev/ldusb0) gets you a one-byte sample count, 
a one-byte sequence number, and three two-byte little-endian temperature samples 
which appear to be 100ths of a degree celsius. It appears to generate around 2.5 
samples per second, which is probably overkill.

It looks like the perl should be something like this:

my $buf;
open(DEV, "/dev/ldusb0") || die "couldn't open device file";
my $number_read = read(DEV, $buf, 8);
my ($samplecount, $sequence, $temp1, $temp2, $temp3) = unpack("c c s s s", $buf);
print "$samplecount, $sequence, $temp1, $temp2, $temp3\n";

And it works!

3, 127, 2840, 2840, 2840

Now, what are those numbers? Room temperature seems to be from 2400 to 2800. Grabbing the thermometer yields about 4280. Putting it into a hole into our uninsulated wall when it is 8 degrees Celsius outside seems to stabilize about 2000.

Putting the sensor in the heater vent when it blowing shows about 4000.

I've tried telling unpack to treat the value as different values but to no effect.

v (little-endian short)
S (unsigned short)
s (signed short)

All seem to yield the same value after unpacking.