0

I’m trying to write some Python code to control a couple of instruments using pyvisa. I’m new to Python, so please bear with me. I have some code that works, but I’m really struggling to figure out how to interface this with a tkinter-based GUI.

For my working code, I have a main file (Main.py) which has the main code, and two modules (powermeter.py and powersupply.py) which contain functions for interfacing to the two instruments. This works fine. Some example code is shown here, I’ve only shown code related to one instrument (powersupply) for simplicity. One function (again, just showing one for simplicity) connect() from the module powersupply.py is:

def connect(resource_manager, ID):
    """Open a connection to the supply"""
    instrument_name = resource_manager.open_resource(ID)
    return instrument_name

The main program searches the list of available VISA instruments for a VISA ID that matches what I expect from the brand/model of meter we use. This is saved to the variable ThorID.

import pyvisa
import powermeter

rm = pyvisa.ResourceManager()  # Set up resource manager
resource_list = rm.list_resources()  # Create a list of available instruments

""" Establish connection to power meter """
Thor_str = "0x1313::0x8079"  # Power meter ID should contain this string
Thor = [i for i, s in enumerate(resource_list) if Thor_str in s]

if len(Thor) == 0:
    print("No Thor Labs power meter detected")
    ThorID = ""
else:
   ThorID = resource_list[Thor[0]]  # This is the Thor Labs VISA ID
   print("Thor Labs power meter detected")

I can then use the function connect() to connect to the meter once it has been found and then return the variable pm, which is (as I understand) the full VISA resource name/ID that I need for other functions (not shown here):

pm = powermeter.connect(rm, ThorID)  # Open a connection to the Power Meter

So far so good. However, my understanding totally breaks down when considering how to integrate this to a GUI. In the GUI there is a button (tk.Button) Connect to device. When I push this button, essentially I want to execute the command pm = powermeter.connect(rm, ThorID), making a connection and returning the variable pm. However tkinter wants me to use the syntax command = function_name(), and I know that the syntax command = pm = powermeter.connect(rm, ThorID) can’t be right!

I’ve tried defining another function in the main program, called e.g. connect_instruments(). However, that also appears to be the wrong way to do it because it seems to execute even before I press the button!

If anyone could give some advice here, that would be great. I find this incredibly confusing to be honest, even though what I want to do (execute this code when this button is pressed) seems very simple!

martineau
  • 119,623
  • 25
  • 170
  • 301
McKendrigo
  • 39
  • 1
  • 5
  • Write a class that `pm` lives in, have that class persist, then pass a class method to the button which sets the class's `pm` to `powermeter.connect(rm, ThorID)`. – Random Davis Sep 30 '20 at 15:29
  • Callback functions are called by `tkinter` and their return value, if any, is ignored. Also very important: When specifying a callback function ***don't call it*** — which means use `command=function_name`, not `command=function_name()`. – martineau Sep 30 '20 at 15:57
  • @RandomDavis thanks for the response, though because my Python is so limited I don't fully understand it. What do you mean by "have that class persist"? – McKendrigo Sep 30 '20 at 16:05
  • @martineau Thanks, I guess that explains why my other function was executing before the button was pressed? – McKendrigo Sep 30 '20 at 16:06
  • Yes, that's right. Possible duplicate of [Why is Button parameter “command” executed when declared?](https://stackoverflow.com/questions/5767228/why-is-button-parameter-command-executed-when-declared), however I won't close your question because more than one thing is being asked (I think). – martineau Sep 30 '20 at 16:08
  • @McKendrigo create the class at the beginning of your program, then keep that reference around the whole time. – Random Davis Sep 30 '20 at 16:08
  • @martineau Yes, I'm also asking how to access any values returned by the callback functions, as I need to use these values for other callbacks. – McKendrigo Sep 30 '20 at 16:10
  • Please focus on one Q at a time, if you did ask two Q before, anyway why not use `global`? – Delrius Euphoria Sep 30 '20 at 16:10
  • I suggest you ask a new question about just that (because I am going to close this one after all — best to only have one topic per question). – martineau Sep 30 '20 at 16:12
  • @CoolCloud I didn't use global variables because I had seen people elsewhere indicating that such an approach was not a good practice, at least for longer more complex programs. – McKendrigo Sep 30 '20 at 16:13
  • @martineau Fair enough, I hadn't even really understood I was asking more than one thing! Thanks for your help. – McKendrigo Sep 30 '20 at 16:14
  • McKendrigo: Bring the topic of avoiding global variables up in your new question (because it's a very valid concern) – martineau Sep 30 '20 at 16:14
  • Not using `global` then i think you might have to use classes – Delrius Euphoria Sep 30 '20 at 17:02
  • See [How to avoid globals (and use classes)?](https://stackoverflow.com/questions/56525272/how-to-avoid-globals-and-use-classes) – martineau Sep 30 '20 at 18:19

0 Answers0