Help with getting print screen from a tektronix 7104 O-Scope over GPIB in python - Page 1
Forum section: electronics / testgear

author: smallhill
author_rank: Newbie
timestamp: February 09, 2024, 04:35:18 pm
content: Here is my code, I need help with my def capture_and_save_screen function for capturing the screenshot and saving it to the controlling pc but I keep getting my "Error", "Invalid or incomplete image data received." comment I can't seem to find where I'm going wrong. I have a connect to scope function that already connect to the scope at GPIB address 5 and IDN's the scope successfully. Just can't get the screen capture. I've looked at all the tek forums but the SCIPI commands differ because their different scopes. This is for a TDS 7104 or a TDS 6604.import tkinter as tkfrom tkinter import messagebox, scrolledtext, filedialogimport pyvisaimport timeimport warningsclass OscilloscopeAppEnhanced:def __init__(self, master):self.master = masterself.master.title("TDS 7704 Screen Capture Enhanced")self.master.geometry("600x300")# Label for GPIB address inputself.label_gpib_address = tk.Label(master, text="GPIB Address:")self.label_gpib_address.pack()# Input for GPIB addressself.entry_gpib_address = tk.Entry(master)self.entry_gpib_address.pack()# Create a button to initiate connectionself.connect_button = tk.Button(master, text="Connect", command=self.connect_to_scope)self.connect_button.pack(pady=10)# Create a button to initiate screen capture, now directly opens file dialog to saveself.capture_button = tk.Button(master, text="Capture and Save Screen", command=self.capture_and_save_screen, state=tk.DISABLED)self.capture_button.pack(pady=10)# Status/Command text areaself.text_status = scrolledtext.ScrolledText(master, height=5)self.text_status.pack(pady=10)# Initialize VISA resource managerself.rm = pyvisa.ResourceManager()self.scope = Nonedef connect_to_scope(self):gpib_address_num = self.entry_gpib_address.get().strip()try:gpib_address = f"GPIB0::{gpib_address_num}::INSTR"if not gpib_address_num.isdigit():raise ValueError("Please enter a valid GPIB address number.")self.scope = self.rm.open_resource(gpib_address)self.scope.write("*CLS") # Clear any errors in the error queue.self.scope.timeout = 5000 # Set timeout to 5000 ms (5 seconds) to allow time for response.idn_response = self.scope.query("*IDN?").strip() # Query the instrument identityif len(idn_response) == 0:raise Exception("No response from instrument. Please check the connection and GPIB address.")self.text_status.insert(tk.END, f"Successfully connected to the oscilloscope at {gpib_address}.\n")self.text_status.insert(tk.END, f"Instrument IDN: {idn_response}\n")self.capture_button["state"] = tk.NORMALexcept ValueError as ve:self.text_status.insert(tk.END, f"Error: {str(ve)}\n")except Exception as e:self.text_status.insert(tk.END, f"Failed to connect to the oscilloscope: {str(e)}\n")self.scope = Nonedef capture_and_save_screen(self):fileSaveLocation = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png"), ("All files", "*.*")])if not fileSaveLocation:messagebox.showerror("Error", "Operation cancelled or no file selected.")returnif self.scope:try:# Assuming your oscilloscope is already configured to communicate over GPIBself.scope.write('EXPort:IMAGe NORMal') # Set the export image to NORMALself.scope.write('EXPort:FORMat PNG') # Set the export format to PNGself.scope.write('EXPort:VIEW FULLSCREEN') # Sets the exported view area to Full Screenself.scope.write('HARDCopy:LAYout LANDscape') # Sets the hard copy page orientation to Landscapeself.scope.write('HARDCOPY:PORT GPIB') # Set the hardcopy port to GPIBself.scope.write('HARDCOPY START') # Start the hardcopy processtime.sleep(10) # Adjust based on your oscilloscope's response time# Read the image data from the oscilloscopeimgBytes = b""while True:try:chunk = self.scope.read_raw()if not chunk:break # Break the loop if no more data is receivedimgBytes += chunkexcept pyvisa.errors.VisaIOError as e:if e.error_code == pyvisa.constants.VI_ERROR_TMO: # Timeout errorbreak # Assume end of data on timeoutelse:raise # Re-raise the exception if it's not a timeout error# Check if the received data is valid for a PNG imageif len(imgBytes) < 100: # Arbitrary minimum size check for a PNG filemessagebox.showerror("Error", "Invalid or incomplete image data received.")returnwith open(fileSaveLocation, "wb") as imgFile:imgFile.write(imgBytes)messagebox.showinfo("Success", f"Screen capture saved to {fileSaveLocation}.")except Exception as e:messagebox.showerror("Error", f"Failed to capture and save screen: {str(e)}")# Run the applicationdef run_app_enhanced():root = tk.Tk()app = OscilloscopeAppEnhanced(root)root.mainloop()run_app_enhanced()

author: abeyer
author_rank: Frequent Contributor
timestamp: February 09, 2024, 07:01:51 pm
content: Are you sure you can mix and matchexportandhardcopycommands like that? My understanding is they're kind of distinct functions, one for waveform capture and the other for full "screenshot."

author: smallhill
author_rank: Newbie
timestamp: February 09, 2024, 10:27:30 pm
content: Good question, you see the export commands weren't in their originally only the HARDCopy commands. When they didn't work I assumed why not take a crack at throwing those in their just to see what happens. Same outcome, still didn't get the screen capture from the TDS 6604 or 7104 O-Scope. Easy to remove if need be. Worked on figuring it out a little more. Still looking into it.