unreliable USBTMC driver with Tektronix TDS1012B

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I was testing the usbtmc driver with a number of Tektronix TD1012B
oscilloscopes that I could get my hands on in our lab.
It works to a certain degree, but is very unreliable. Since I couldn't
find a whole lot of documentation on how to interface it, I tried
similar things what Agilent wrote up [1] - though I know that driver
must be different from the current one that I use in 2.6.30.5. The
method is basically using the normal file handling routines on the
device file (e.g. /dev/usbtmc0):


1)
The simplest one is something like this:
echo *IDN?>/dev/usbtmc0
cat /dev/usbtmc0

The output of this is these two lines:
TEKTRONIX,TDS 1012B,C010499,CF:91.1CT FV:v22.01
cat: /dev/usbtmc0: Connection timed out

Also in the logs:
kernel: usbtmc 3-2:1.0: Unable to read data, error -110
kernel: usbtmc 3-2:1.0: usb_control_msg returned -110

The usbmon output of the above echo/cat is:
f54cd080 2498021285 S Bo:3:113:6 -115 20 = 0128d700 06000000 01000000
2a49444e 3f0a0000
f54cd080 2498022379 C Bo:3:113:6 0 20 >
f672ae00 2503540783 S Bo:3:113:6 -115 12 = 0229d600 e2070000 000a0000
f672ae00 2503542459 C Bo:3:113:6 0 12 >
f672ae00 2503542516 S Bi:3:113:5 -115 2048 <
f672ae00 2503549464 C Bi:3:113:5 0 60 = 0229d600 30000000 01000000
54454b54 524f4e49 582c5444 53203130 3132422c
f672ae00 2503553031 S Bo:3:113:6 -115 12 = 022ad500 e2070000 000a0000
f672ae00 2503553463 C Bo:3:113:6 0 12 >
f672ae00 2503553537 S Bi:3:113:5 -115 2048 <
f672ae00 2503563456 C Bi:3:113:5 -2 0
f672ae00 2503575589 S Ci:3:113:0 s a2 03 002b 0085 0002 2 <
f672ae00 2503583450 C Ci:3:113:0 -2 0

Isn't the expected behaviour just a single line of the ID string?
TEKTRONIX,TDS 1012B,C010499,CF:91.1CT FV:v22.01


2)
Some of these messages can be avoided if I use code to read only a
single line (since the end of line terminator is used by the scope),
but it does not work well, either:
Consider a small python script:

#!/usr/bin/env python
import os
from time import sleep
scopedev = "/dev/usbtmc0"
scope = open(scopedev, "r+")
scope.write("*IDN?\n")
id = scope.readline().strip()
print "ID: %s" %(id)
sleep(0.1)
scope.write("CH1:SCALE?\n")
scale = scope.readline().strip()
print "Scale: %s" %(scale)
scope.close()

This reads the device ID string, and asks for the current scale
setting on Channel1.
Expect: just works, returns the ID and scale values.

What actually happens: when the /dev/usbtmc0 is empty (e.g. after a
`cat /dev/usbtmc0`), the script fails with timeout at reading the
response to "*IDN?". If I now run again, then it succeeds, but all
responses are off by one: ID: will be the response returned to the
query in  the first (failed) run, and "Scale:" will be the same
string, now as a response to the query in the second run:
ID: TEKTRONIX,TDS 1012B,C010499,CF:91.1CT FV:v22.01
Scale: TEKTRONIX,TDS 1012B,C010499,CF:91.1CT FV:v22.01

In the third run, it's responding to the previous run:
ID: 1.0E0
Scale: TEKTRONIX,TDS 1012B,C010499,CF:91.1CT FV:v22.01
and so on, until I clear it with a `cat /dev/usbtmc0`

This does not matter on whether I put any sleep (tried it from
milliseconds to seconds) between the write and read. The sleep(0.01)
between the two queries is need also, otherwise it fails with Error110
every time. Not sure about the minimum time for that, though...

3)
I tried to read it in a trickier way, using such a function, when I
throw out the error messages and read until succeed or timeout:

def recvCmd(handle, timeout):
    starttime = time()
    while (time() - starttime) < timeout:
        try:
            data = handle.readline()
            return data
        except:
            continue
    return ""

This works generally better, I can get an answer a lot of times, and
the right one (not the "previous"). But it still times out in a big
percentage of times.
I compared this with using Tektronix's software (TekVISA and
Talker-Listener) where I can send commands and see the answers pretty
much the same way as here: no commands ever failed or timed out. I can
loop it to my heart's content (as fast as the interface allowes), and
no failed read.

4)
Is there a buffer built in the kernel side somewhere? I see that the
data read is only possible in 1024byte portions.
E.g. retrieving a scan from the oscilloscope ("CURVE?" query) in
binary should return a 2507byte, or 5007byte length string (where the
last byte is the line-feed).
On windows, the Talker-Listener reads all this in one go, wheres on
linux I have to do multiple reads and stitch them together.
Also, there are quite a few times when (on Linux) I cannot read all
the data that I expect, and receive less then the required bytes.


With respect to these issues, are these expected behaviours that I
just don't comprehend? I'm not convinced, since in the Agilent docs
they don't have any similar things - but I don't have any Agilent
USBTMC device to test it against, and the Tektronix scopes seems to
work flawlessly and as expected with their TekVISA drivers on windows.

Is there a better way to read this data?

Is there any test that I can do to provide more information? It would
be awesome if this would work....

Cheers,
     Greg



[1] http://www.home.agilent.com/upload/cmc_upload/All/usbtmc.html
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux