RPi to DS2000 control commands - Page 1
Forum section: electronics / projects

author: Harvs
author_rank: Super Contributor
timestamp: June 22, 2013, 12:59:48 am
content: I've had a look around but I'm somewhat lost in the Linux jargon on the net.I was wondering if it's possible to some how feed commands to the Rigol DS2000 scope from a RPi. This is trivial to do from Windows with NI-VISA, but from what I can gather the Linux NI-VISA drivers only support a couple of distributions and there isn't an ARM version. (I know very little about the workings of Linux so this may sound stupid.)What I'd like to do if it's easy enough make a small side panel (using laser cut acrylic) of user programmable keys. As they no longer have a RS232 interface like the DS1000, it's no-longer just a matter of sending serial SCPI commands from any old uC.As much as it's a great scope, there's a few things that I wish were just at the push of 1-button. Like, when debugging duplex serial, regularly changing from triggering on CH1 to CH2 is a right PITA.

author: daveatol
author_rank: Regular Contributor
timestamp: June 22, 2013, 07:11:47 am
content: If you can't get the driver source and cross-compile for RPi, you could have a look at what is being sent to the device using usbmon (or the USBPcap on windows); both can be used with wireshark. Once you've seen the transactions that take place when talking to your device, you may be able to duplicate it using libUSB (and the libusb generic driver). I assume there will be a few setup commands, and then the control commands will just be sent through bulk transactions similar to the serial port.

author: Harvs
author_rank: Super Contributor
timestamp: June 22, 2013, 11:01:20 am
content: Quote from: daveatol on June 22, 2013, 07:11:47 amWell you were pretty much spot on about how it's sent. There's a bunch of USB enumeration stuff than goes on, then there's two endpoints that are used for input and output. It seems the commands are just sent and read back as ASCII inside the packet. I've attached an example of a command that changes to CHAN2 edge trigger.Now I just need to work out how to replicate it...

author: Harvs
author_rank: Super Contributor
timestamp: June 22, 2013, 11:02:42 am
content: PS any more tips would be great!

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: June 22, 2013, 11:07:44 am
content: If you know the USB commands used, I wonder if it might be simpler to use a cheap MCU that has USB host, e.g. the PIC24FJ64GB002.This may also be easier to power neatly, e.g. from the USB host port, which might struggle to power a Rpi. Also avoids boot time issues.

author: Harvs
author_rank: Super Contributor
timestamp: June 22, 2013, 11:31:12 am
content: Quote from: mikeselectricstuff on June 22, 2013, 11:07:44 amThat's actually what I'm hoping for now. After a bit of reading, I think this should be easy to test out on the RPi just using PyUSB. Then I'll look to building something on a uC if I can.

author: bingo600
author_rank: Super Contributor
timestamp: June 22, 2013, 11:55:34 am
content: I would have thought the magic word was USBTMC , when talking Test/Measurement via USB.And i think it ought to be incorporated in any recent kernal./Bingo

author: daveatol
author_rank: Regular Contributor
timestamp: June 22, 2013, 11:58:30 am
content: I interfaced the pickit2 to avrdude ages back; the process was to open the usb device, set the configuration, claim the interface, then send data out the pipes.Code:handle = usb_open(dev);usb_set_configuration(handle, 1);usb_claim_interface(handle, 0);Good luck with pyUSB.

author: Harvs
author_rank: Super Contributor
timestamp: June 22, 2013, 01:47:05 pm
content: @daveatolThanks for pointing me in the right direction. Works a treat. I'll post the code once it's more complete.Cheers

author: daveatol
author_rank: Regular Contributor
timestamp: June 22, 2013, 11:52:31 pm
content: You're quick! I'd be interested in seeing what you post.

author: Harvs
author_rank: Super Contributor
timestamp: June 23, 2013, 01:01:33 pm
content: I wish I could say it's because I'm awesome, but I'm afraid once I'd captured a few messages, then downloaded the USBTMC specification to properly decode them, then the rest is really trivial. My biggest problem is actually using Python, there's lots of things that don't work the same a C which I always program in, I need to get better at it.So the code below is just a flat file that a writes a "*IDN?\n" command followed by a read request (which together is what NI call a Query). Obviously I will build this into generic functions with error handling and implement the control stuff as I get time.Code:import usb.coreimport usb.utilimport sys# find our devicedev = usb.core.find(idVendor=0x1ab1, idProduct=0x04b0)# was it found?if dev is None:raise ValueError('Device not found')# set the active configuration. With no arguments, the first# configuration will be the active onedev.set_configuration()"""*************************************************************Perform a message write*************************************************************"""#message ID 1=DEV_DEP_MSG_OUT, 2=REQUEST_DEV_DEP_MSG_INMsgID = 0x01# sequential message identifierbTag = 0x01bTagInverse = (bTag ^ 0xFF)command = bytearray("*IDN?\n")#size of message to writetxSize_0 = len(command)txSize_1 = 0x00txSize_2 = 0x00txSize_3 = 0x00EOM = 0x01bReserved = 0x00frame = [MsgID, bTag, bTagInverse, bReserved, txSize_0, txSize_1, \txSize_2, txSize_3, EOM, bReserved, bReserved, bReserved]# add the commandframe += command# pad the frame to 4 byte (32bit) chunkswhile ((len(frame) % 4) > 0):frame += ret = dev.write(0x02, frame)"""*************************************************************Write the read back request giving the device the ability towrite back to the BULK-IN endpoint*************************************************************"""#message ID 1=DEV_DEP_MSG_OUT, 2=REQUEST_DEV_DEP_MSG_INMsgID = 0x02# sequential message identifierbTag = 0x02bTagInverse = (bTag ^ 0xFF)#number of bytes to read backrxSize_0 = 0xFF #read back 256 bytesrxSize_1 = 0x00rxSize_2 = 0x00rxSize_3 = 0x00bReserved = 0x00#last two bytes are termination chars not supported by the rigol and must be 0frame = [MsgID, bTag, bTagInverse, bReserved, rxSize_0, rxSize_1, \rxSize_2, rxSize_3, 0x00, 0x00]# pad the frame to 4 byte (32bit) chunkswhile ((len(frame) % 4) > 0):frame += ret = dev.write(0x02, frame)"""Try and read the response back from the device"""ret = dev.read(0x86, 0xFF, 0, 200)print ret.tostring()#close the devicedev.reset()