Search code examples
gousblibusbvisa

Connecting to USBTMC devices via USB in Linux


I'm currently implementing a gotmc/VISA package to send SCPI commands to my multimeter.

But every time I try to connect to the device, it gets me the same message:

libusb: device or resource busy [code -6].

Is there a way to handle this problem? From one source I read, I need to detach the kernel from the device, but can I do it from this package?

If there is another package that support SCPI commands over USB I would be grateful of hearing about it.

Here is my example code:

package main

import (
    "fmt"
    "io"
    "log"
    "time"

    _ "github.com/gotmc/usbtmc/driver/google"
    "github.com/gotmc/visa"
    _ "github.com/gotmc/visa/driver/usbtmc"
)
const (
    usbAddress string = "USB0::10893::4610::MY58130019::INSTR"
)

func main() {
    fg, err := visa.NewResource(usbAddress)
    usbtmc.De
    if err != nil {
        log.Fatal("Couldn't open the resource for the function generator")
    }
}

Solution

  • Here are a few things to try:

    1. The line usbtmc.De appears to be incomplete or a typo in your example code. Could you please provide the full line?
    2. Confirm that the VISA address string you're using is correct for your multimeter.
    3. There have been some updates to the gotmc/usbtmc project since this question was asked, so I'd recommend using v0.4.0 or newer in your go.mod.
    4. Eliminate gotmc/visa for now while trying to debug.
    5. Enable USB debugging as shown in the code below and running the program using USB debug level 4.
    6. Try using NewDeviceByVIDPID() instead of using NewDevice().
    7. What's the Keysight model number of the multimeter?

    Command to run with USB level 4 debug

    $ ./myprogram -d=4
    

    go.mod

    module github.com/myproj/myrepo
    
    go 1.12
    
    github.com/gotmc/usbtmc v0.4.0
    

    main.go

    package main
    
    import (
        "flag"
        "log"
        "time"
    
        "github.com/gotmc/usbtmc"
        _ "github.com/gotmc/usbtmc/driver/google"
    )
    
    var (
        debugLevel uint
    )
    
    func init() {
        const (
            defaultLevel = 1
            debugUsage   = "USB debug level"
        )
        flag.UintVar(&debugLevel, "debug", defaultLevel, debugUsage)
        flag.UintVar(&debugLevel, "d", defaultLevel, debugUsage+" (shorthand)")
    }
    
    func main() {
        // Parse the config flags to determine the config JSON filename
        flag.Parse()
    
        // Create new USBTMC context and new device.
        start := time.Now()
        ctx, err := usbtmc.NewContext()
        if err != nil {
            log.Fatalf("Error creating new USB context: %s", err)
        }
        ctx.SetDebugLevel(int(debugLevel))
    
        mm, err := ctx.NewDevice("USB0::10893::4610::MY58130019::INSTR")
        // You could try the following instead:
        // mm, err := ctx.NewDeviceByVIDPID(10893, 4610)
    
        if err != nil {
            log.Fatalf("NewDevice error: %s", err)
        }
        log.Printf("%.2fs to create new device.", time.Since(start).Seconds())
        
        // Send a SCPI command to the multimeter.
        mm.WriteString("*CLS\n")
    
        // Close the multimeter and USBTMC context and check for errors.
        err = mm.Close()
        if err != nil {
            log.Printf("error closing mm: %s", err)
        }
        err = ctx.Close()
        if err != nil {
            log.Printf("Error closing context: %s", err)
        }
    }