I have written a small python script to enable the output of a HAMEG HMG4040 triple power-supply. I am using pyvisa 1.14.1 along with NI-VISA 20.0
import pyvisa
import time
# Initialize the PyVISA resource manager
pyvisa.log_to_screen()
rm = pyvisa.ResourceManager()
# List all connected VISA devices
def list_devices():
devices = rm.list_resources()
if devices:
print("Available VISA devices:")
for idx, device in enumerate(devices):
print(f"{idx + 1}: {device}")
else:
print("No VISA devices found.")
return devices
# Function to query the device
def query_device(resource_name, command):
try:
# Open the device resource
with rm.open_resource(resource_name) as instrument:
instrument.timeout = 5000 # Set timeout to 1000 ms (1 seconds)
# Write the query command to the device
instrument.write(command)
# Read the response from the device
response = instrument.read()
return response
except Exception as e:
print(f"Error querying device: {e}")
return None
# Function to query the device
def send_cmd_device(resource_name, command):
try:
# Open the device resource
with rm.open_resource(resource_name) as instrument:
instrument.timeout = 5000 # Set timeout to 1000 ms (1 seconds)
# Write the query command to the device
instrument.write(command)
return 1
except Exception as e:
print(f"Error querying device: {e}")
return None
# Main function
if __name__ == "__main__":
# List available devices
devices = list_devices()
if devices:
# Choose the device you want to query
resource_name = devices[0] # Use the first detected device for this example
# Command to send to the device (replace with actual command)
command = "*IDN?"
# Query the device and get the response
response = query_device(resource_name, command)
if response:
print(f"Response from HMG4040: {response}")
else:
print("No response from the device.")
state = input("specify PSUP state: [ON/OFF]\n")
#select and activate output 1,2 and 4
with rm.open_resource(resource_name) as instrument:
instrument.timeout = 1000 # Set timeout to 1000 ms (1 seconds)
instrument.write("INST OUT1")
instrument.write("OUTP:SEL " + state)
instrument.write("INST OUT3")
instrument.write("OUTP:SEL " + state)
instrument.write("INST OUT4")
instrument.write("OUTP:SEL " + state)
instrument.write("OUTP:GEN " + state)
send_cmd_device(resource_name, "INST OUT1")
send_cmd_device(resource_name, "OUTP:SEL " + state)
send_cmd_device(resource_name, "INST OUT3")
send_cmd_device(resource_name, "OUTP:SEL " + state)
send_cmd_device(resource_name, "INST OUT4")
send_cmd_device(resource_name, "OUTP:SEL " + state)
send_cmd_device(resource_name, "OUTP:GEN " + state)
else:
print("No devices to query.")
If I comment out the send_cmd_device()
lines the script is working fine either in debug mode or normal python execution.
However, if I comment out this part:
with rm.open_resource(resource_name) as instrument:
instrument.timeout = 1000 # Set timeout to 1000 ms (1 seconds)
instrument.write("INST OUT1")
instrument.write("OUTP:SEL " + state)
instrument.write("INST OUT3")
instrument.write("OUTP:SEL " + state)
instrument.write("INST OUT4")
instrument.write("OUTP:SEL " + state)
instrument.write("OUTP:GEN " + state)
The script only works if I place a breakpoint and step, in debug mode, through each line including the send_cmd_device()
lines.
Could someone explain why the script doesn't work in normal full speed exection when using the method call? I have tried adding delays everywhere but that didn't help.
I've never worked with this instrument in particular, but I've seen similar issues in other instruments where the commands are either sent too quickly in succession or one of the commands is badly formatted. Based on the instrument documentation it supports the common *OPC
command for "Operation Complete." As a debugging step, I would suggest to query *OPC
after every command. Right now, your code is stepping through as fast as python and the GPIB interface on your controller can go, with no regard for the internal state of the machine. By querying for status, you can be sure that each step was completed correctly before starting the next step. Try modifying the problem section as follows:
with rm.open_resource(resource_name) as instrument:
instrument.timeout = 1000 # Set timeout to 1000 ms (1 seconds)
instrument.write("INST OUT1")
print(instrument.query("*OPC?"))
instrument.write("OUTP:SEL " + state)
print(instrument.query("*OPC?"))
instrument.write("INST OUT3")
print(instrument.query("*OPC?"))
instrument.write("OUTP:SEL " + state)
print(instrument.query("*OPC?"))
instrument.write("INST OUT4")
print(instrument.query("*OPC?"))
instrument.write("OUTP:SEL " + state)
print(instrument.query("*OPC?"))
instrument.write("OUTP:GEN " + state)
print(instrument.query("*OPC?"))
If this works, remove the queries one-by-one to find the point where the instrument fails again. Then you know the step that needs a longer delay. For this reason, I often end up writing GPIB drivers that use a combination of .write()
followed by .query("*OPC?")
for particular items that take extra time.
Based on the comments, I'm starting to think this is not an issue of the commands executing too quickly, but rather because the GPIB resource is opened many times. It's better to open the resource once and keep the connection rather than opening many times. In theory, opening many times should also work, just more slowly. In practice, there may be some conflict/overload in the GPIB controller. Here's a refactored version that passes the instrument resource to query_device
and send_cmd_device
. In addition, it uses instrument.query
in send_cmd_device
to check that each command completed correctly.
import pyvisa
# Initialize the PyVISA resource manager
pyvisa.log_to_screen()
rm = pyvisa.ResourceManager()
# List all connected VISA devices
def list_devices():
devices = rm.list_resources()
if devices:
print("Available VISA devices:")
for idx, device in enumerate(devices):
print(f"{idx + 1}: {device}")
else:
print("No VISA devices found.")
return devices
# Function to query the device
def query_device(instrument, command):
try:
# Write the query command to the device
instrument.write(command)
# Read the response from the device
response = instrument.read()
return response
except Exception as e:
print(f"Error querying device: {e}")
return None
# Function to query the device
def send_cmd_device(instrument, command):
try:
instrument.timeout = 5000 # Set timeout to 1000 ms (1 seconds)
# Write the query command to the device
instrument.write(command)
print(instrument.query("*OPC?"))
return 1
except Exception as e:
print(f"Error querying device: {e}")
return None
# Main function
if __name__ == "__main__":
# List available devices
devices = list_devices()
if devices:
# Choose the device you want to query
resource = rm.open_resource(devices[0]) # Use the first detected device for this example
# Command to send to the device (replace with actual command)
command = "*IDN?"
# Query the device and get the response
response = query_device(resource, command)
if response:
print(f"Response from HMG4040: {response}")
else:
print("No response from the device.")
state = input("specify PSUP state: [ON/OFF]\n")
# select and activate output 1,2 and 4
resource.timeout = 1000 # Set timeout to 1000 ms (1 seconds)
resource.write("INST OUT1")
resource.write("OUTP:SEL " + state)
resource.write("INST OUT3")
resource.write("OUTP:SEL " + state)
resource.write("INST OUT4")
resource.write("OUTP:SEL " + state)
resource.write("OUTP:GEN " + state)
send_cmd_device(resource, "INST OUT1")
send_cmd_device(resource, "OUTP:SEL " + state)
send_cmd_device(resource, "INST OUT3")
send_cmd_device(resource, "OUTP:SEL " + state)
send_cmd_device(resource, "INST OUT4")
send_cmd_device(resource, "OUTP:SEL " + state)
send_cmd_device(resource, "OUTP:GEN " + state)
else:
print("No devices to query.")