I’ve been stuck on this for a long time. My code is in 2 parts. Below is the code I use to create my object (an electronic instrument connected to my laptop via USB that collects data):
# vna_control.py
# It is better to create a class of VNA object that contains a bunch of methods.
from pathlib import Path
import numpy as np
import win32com.client
calibrationpath = Path("C:/Users/ayilarana/PycharmProjects/pythonProject/ring.cal")
calibrationkitpath = Path("C:/Users/ayilarana/PycharmProjects/pythonProject/SF287.kit")
class VNA_Object:
def __init__(self, name, description):
self.vna = win32com.client.Dispatch("PicoControl2.PicoVNA_2")
self.name = name
self.type = description
def open_vna(self):
findVNA = self.vna.FND()
if findVNA == 0:
print("No VNA Loaded")
exit()
else:
print('VNA ' + str(findVNA) + ' Loaded')
dll = self.vna.DLLVer()
print(dll)
cali = self.vna.SelectKit(calibrationkitpath, "1")
print("Result " + str(cali))
enhance_averages = self.vna.SetEnhance("aver", 100)
print("Averages: " + enhance_averages)
ans = self.vna.SelectCal(calibrationpath)
print("Result " + str(ans))
return print("VNA Open")
def measure_vna_frequency(self):
meas = self.vna.Measure("S11")
print("Result " + str(meas))
raw = self.vna.GetData("S11", "logmag", 0)
splitdata = raw.split(',')
converteddata = np.array(splitdata)
converteddata = converteddata.astype(np.float)
x_frequency = converteddata[:: 2]
return x_frequency
def measure_vna_ys11(self):
meas = self.vna.Measure("S11")
print("Result " + str(meas))
raw = self.vna.GetData("S11", "logmag", 0)
splitdata = raw.split(',')
converteddata = np.array(splitdata)
converteddata = converteddata.astype(np.float)
y_s11 = converteddata[1:: 2]
return y_s11
def close_vna(self):
self.vna.CloseVNA()
return print("VNA Closed")
Below is my MAIN code to control my instrument and plot the data (hopefully every 1s) onto a Dash app:
# basic4.py
# import stuff for paths and serials
import win32com.client
import threading
import pythoncom
from pathlib import Path
import vna_control as vna
import time
# import stuff for treating data
import panda_express as pe
import datetime
import numpy as np
# import stuff for plotly and dash
import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
def start():
# Initialize
pythoncom.CoInitialize()
# Get instance
picoVNACOMObj = vna.VNA_Object("Pico VNA", "VNA Instrument")
picoVNACOMObj.open_vna()
print(picoVNACOMObj.measure_vna_frequency())
print(picoVNACOMObj.measure_vna_ys11())
# Create id
global picoVNACOMObj_id
picoVNACOMObj_id = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch, picoVNACOMObj)
# Pass the id to the new thread
thread = threading.Thread(target=update_graph_scatter, kwargs={'picoVNACOMObj_id': picoVNACOMObj_id})
thread.start()
# Wait for child to finish
thread.join()
close = picoVNACOMObj.CloseVNA()
print("closing of VNA " + str(close))
return print("This works")
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Graph(id='live-graph', animate=False),
dcc.Interval(
id='graph-update',
interval=5000,
n_intervals=0
),
]
)
@app.callback(Output('live-graph', 'figure'),
[Input('graph-update', 'n_intervals')])
def update_graph_scatter(n):
pythoncom.CoInitialize()
picoVNACOMObj = win32com.client.Dispatch(pythoncom.CoGetInterfaceAndReleaseStream(picoVNACOMObj_id, pythoncom.IID_IDispatch))
x_frequency = picoVNACOMObj.measure_vna_frquency()
y_s11 = picoVNACOMObj.measure_vna_ys11()
print(x_frequency)
print(y_s11)
data = go.Scatter(
x=x_frequency,
y=y_s11,
name='S11 Parameters of Curling Probe',
mode='lines'
)
return {'data': [data], 'layout': go.Layout(xaxis=dict(range=[min(x_frequency), max(x_frequency)]),
yaxis=dict(range=[min(y_s11), max(y_s11)]),
xaxis_title=dict(text="Frequency (MHz)"),
yaxis_title=dict(text="S11 Parameter"))}
if __name__ == '__main__':
start()
app.run_server(debug=True)
It doesn’t work. I tested a simpler code whereby my threaded function was not a dash one but a simple one that I made. I don’t get marshalling errors with it, so clearly this concept of joining threads for instantiated objects works. But how do I get it to work with Dash? How do I pass my object into the update_graph_scatter() so that it can be controlled there?
Please help. I’ve been stuck on this for a month now.