diff --git a/qutil/measurement/VNA/inst_E5071C.py b/qutil/measurement/VNA/inst_E5071C.py
new file mode 100644
index 0000000000000000000000000000000000000000..0f241b31d27b069506b24ca1c2a86cd3314bf5c2
--- /dev/null
+++ b/qutil/measurement/VNA/inst_E5071C.py
@@ -0,0 +1,217 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sun Oct  2 13:27:14 2022
+
+@author: Ran Xue
+
+modified according to Python Example Retrieve the Data as .csv for all the Traces at the Screen on a E5071C
+https://support.keysight.com/KeysightdCX/s/knowledge-article-detail?language=en_US&keyid=ka05a000000V6MY
+"""
+
+import numpy as np
+import pandas as pd
+import matplotlib.pyplot as plt
+import time
+import visa
+import csv
+
+class VNA:
+    def __init__(self, remote_address):
+        self.remote_address = remote_address
+        self.inst = None
+        self.timeout=50000
+
+    def connect_to_VNA(self):
+        rm=visa.ResourceManager()
+        # print(rm.list_resources())
+        self.inst = rm.open_resource(self.remote_address)
+
+    def identify_inst(self):
+        self.inst.write('*IDN?')
+        IDN = self.inst.read()
+        return IDN
+
+    def get_traces(self):
+
+        MatHeader=[]
+        MatAllData=[]
+        param, getDispMaxChannel = self.get_disp()
+
+        for Channel in range(1,getDispMaxChannel+1):
+            #print(':CALCulate'+str(Channel)+':PARameter1:SELect')
+            self.inst.write(':FORMat:DATA %s' % ('ASCii'))
+            self.inst.write(':CALCulate'+str(Channel)+':PARameter1:SELect')
+            MaxNumTraces = int(self.inst.query(':CALCulate'+str(Channel)+':PARameter:COUNt?'))
+
+            self.inst.write(':FORMat:DATA %s' % ('ASCii'))
+            Frequency = (self.inst.query_ascii_values(':SENSe'+str(Channel)+':FREQuency:DATA?'))
+            MatAllData.append(Frequency)
+
+            for Trace in range(1,MaxNumTraces+1):
+                #print(Trace)
+                param1 = self.inst.query(':SENSe1:SWEep:TYPE?')
+
+                self.inst.write(':FORMat:DATA %s' % ('ASCii'))
+                Data = (self.inst.query_ascii_values(':CALCulate'+str(Channel)+':TRACe'+str(Trace)+':DATA:FDATa?'))
+                #print(Data)
+                #print('Channel'+str(Channel)+'_Trace'+str(Trace)+'amp'+'_Trace'+str(Trace)+'phase')
+                MatHeader.append('Frequency_Channel'+str(Channel)+'_Trace'+str(Trace)+'amp'+'_Trace'+str(Trace)+'phase')
+
+                MatAllData.append(Data[0::2])
+                MatAllData.append(Data[1::2])
+
+        A=MatAllData
+        A=np.array(A).transpose()
+        Headers=' '.join([str(item) for item in MatHeader])
+        return Headers, A
+
+    def setup_measurement(self):
+        # 1 channel 4 traces S11, S12, S21, S22
+        self.inst.write(':CALC1:PAR:COUN 4')
+
+        self.inst.write(':CALC1:PAR1:DEF S11')
+        self.inst.write(':CALC1:PAR2:DEF S12')
+        self.inst.write(':CALC1:PAR3:DEF S21')
+        self.inst.write(':CALC1:PAR4:DEF S22')
+
+        sweep_type = self.inst.query(':SENSe1:SWEep:TYPE?')
+        if sweep_type[:-1] == 'LIN':
+            pass
+        else:
+            self.inst.write(':SENS1:SWE:TYPE LIN\n')
+
+    def make_single_trace(self):
+        # Trigger a measurement
+        trigger_mode = self.inst.query(':TRIG:SOUR?')
+        if trigger_mode[:-1] != 'BUS':
+            self.inst.write(':TRIG:SOUR BUS')
+
+        self.inst.write(':INIT1')  # initiate channel 1 to the idel state (wait for single trigger)
+        time.sleep(1)
+        self.inst.write(':TRIG:SING')  # trigger stimulator
+
+    def get_disp(self):
+        # Get the Shape of the display to know how many channels are needed to be scanned
+        param = self.inst.query(':DISPlay:SPLit?')
+        param = param[0:-1]#remove the \n at the end
+
+        if param=="D1":
+            getDispMaxChannel = 1
+        elif param=="1X1":
+            getDispMaxChannel = 1
+        elif param=="D12":
+            getDispMaxChannel = 2
+        elif param=="D1_2":
+            getDispMaxChannel = 2
+        elif param=="D112":
+            getDispMaxChannel = 2
+        elif param=="D1_1_2":
+            getDispMaxChannel = 2
+        elif param=="D1X2":
+            getDispMaxChannel = 2
+        elif param=="D2X1":
+            getDispMaxChannel = 2
+
+        elif param=="D123":
+            getDispMaxChannel = 3
+        elif param=="D1_2_3":
+            getDispMaxChannel = 3
+        elif param=="D3X1":
+            getDispMaxChannel = 3
+        elif param=="D12_33":
+            getDispMaxChannel = 3
+        elif param=="D11_23":
+            getDispMaxChannel = 3
+        elif param=="D13_23":
+            getDispMaxChannel = 3
+        elif param=="D12_13":
+            getDispMaxChannel = 3
+        elif param=="D1X3":
+            getDispMaxChannel = 3
+
+        elif param=="D1234":
+            getDispMaxChannel = 4
+        elif param=="D1_2_3_4":
+            getDispMaxChannel = 4
+        elif param=="D12_34":
+            getDispMaxChannel = 4
+        elif param=="D1X4":
+            getDispMaxChannel = 4
+        elif param=="D4X1":
+            getDispMaxChannel = 4
+        elif param=="D2X2":
+            getDispMaxChannel = 4
+
+        elif param=="D123_456":
+            getDispMaxChannel = 6
+        elif param=="D12_34_56":
+            getDispMaxChannel = 6
+        elif param=="D2X3":
+            getDispMaxChannel = 6
+        elif param=="D3X2":
+            getDispMaxChannel = 6
+
+        elif param=="D1234_5678":
+            getDispMaxChannel = 8
+        elif param=="D12_34_56_78":
+            getDispMaxChannel = 8
+        elif param=="D2X4":
+            getDispMaxChannel = 8
+        elif param=="D4X2":
+            getDispMaxChannel = 8
+
+        elif param=="D123_456_789":
+            getDispMaxChannel = 9
+        elif param=="D3X3":
+            getDispMaxChannel = 9
+
+        elif param=="D123__ABC":
+            getDispMaxChannel = 12
+        elif param=="D1234__9ABC":
+            getDispMaxChannel = 12
+        elif param=="D3X4":
+            getDispMaxChannel = 12
+        elif param=="D4X3":
+            getDispMaxChannel = 12
+
+        elif param=="D1234_DEFG":
+            getDispMaxChannel = 16
+        elif param=="D1234__CDEF":
+            getDispMaxChannel = 16
+        elif param=="D4X4":
+            getDispMaxChannel = 16
+
+        elif param=="D4X5":
+            getDispMaxChannel = 20
+
+        elif param=="D4X6":
+            getDispMaxChannel = 24
+
+        elif param=="D4X7":
+            getDispMaxChannel = 28
+
+        elif param=="D4X8":
+            getDispMaxChannel = 32
+
+        elif param=="D4X9":
+           getDispMaxChannel = 36
+
+        elif param=="D8X9":
+           getDispMaxChannel = 72
+        elif param=="D6X12":
+           getDispMaxChannel = 72
+
+        elif param=="D8X12":
+           getDispMaxChannel = 96
+
+        elif param=="D10X16":
+           getDispMaxChannel = 160
+
+        else:
+            getDispMaxChannel=1
+
+        return param, getDispMaxChannel
+
+    def disconnect_inst(self):
+        self.inst.close()
+        rm.close()
diff --git a/qutil/measurement/VNA/scheduled_measurement.py b/qutil/measurement/VNA/scheduled_measurement.py
new file mode 100644
index 0000000000000000000000000000000000000000..8971926587f4d790d0275d94aaaa58f7f5bb65e3
--- /dev/null
+++ b/qutil/measurement/VNA/scheduled_measurement.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sun Oct  2 13:14:22 2022
+
+@author: Ran Xue
+"""
+
+#For scheduling task execution
+import schedule
+import time
+import inst_E5071C
+from pathlib import Path
+import numpy as np
+
+timeformat = "%Y_%m_%d_%H%M%S"
+datapath = Path(r'C:\Users\lablocal\Documents\Measurement_QuBus\setup_characterization\VNA_measurement')
+
+def make_scheduled_single_trace():
+    VNA = inst_E5071C.VNA('TCPIP::169.254.40.9::INSTR') # instantiate a VNA
+    VNA.connect_to_VNA()
+
+    if VNA.identify_inst() is None:
+        try:
+            VNA.connect_to_VNA()
+            idn = VNA.identify_inst()
+            print(f'refresh connection to VNA: {idn}')
+        except:
+            raise ConnectionError('No such an instrument found! Please check the connection first.')
+
+    VNA.setup_measurement()
+    VNA.make_single_trace()
+    headers, data = VNA.get_traces()
+
+    timestamp = time.strftime(timeformat)
+    filename = datapath / f'{timestamp}_data.csv'
+    np.savetxt(filename, data, delimiter=',', fmt='%5s', header= headers)
+    print(f'[{timestamp}] - VNA measurement saved.')
+
+print('>>> Start a scheduled measurement: VNA trace during cooling down <<<')
+schedule.every(10).minutes.do(make_scheduled_single_trace)
+print('Sleep for 10 min')
+
+while True:
+    schedule.run_pending()
+    time.sleep(1)
\ No newline at end of file