Advertisement
Guest User

Untitled

a guest
Feb 21st, 2020
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.91 KB | None | 0 0
  1. vna_communication.py
  2. import socket
  3. import re
  4. import numpy as np
  5. import datetime
  6. from pathlib import Path
  7.  
  8. PORT = 5001
  9. BUFFER_SIZE = 1048576 #maximum size of packages returned by socket.recv()
  10. #size is arbitrary, low size leads to slow transmittion.
  11. RESOLUTION = 16001 #16001 is maximum
  12. class VNA:
  13. """This class communicates with the MS46122B VNA via the Shockline
  14. software. It takes care of Networking and formatting of results, so
  15. that it can be used easily in Matlab. It contains a setup,
  16. run_measurement and get_results method for easy access of data but
  17. also passes on the low level send and receive commands, so that further
  18. optimization can be easily done in Matlab.
  19. Known Bugs:
  20. First Measurement might contain weird data. Be sure to run one test
  21. measurement before using data.
  22. Possible explaination: Initialization might send unexpected data.
  23. Possible fix: search for begin of <DataFile>.
  24. Will fix if needed.
  25. """
  26. def __init__(self, ip):
  27. self.path = str(Path(__file__).parent.absolute())
  28. self.logdir = self.path+"/logs/"
  29. Path(self.logdir).mkdir(parents=True, exist_ok=True)
  30. self.vna=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  31. self.vna.settimeout(120.0)
  32. #*OPC? command might take very long to answer
  33. self.vna.connect((ip, 5001))
  34.  
  35. def setup(self,start, end):
  36. """Sets parameters for Measurement, like start and end Frequency
  37. but also resolution and sets mode to single sweep.
  38. """
  39. self.send("SENS:FREQ:STAR "+ start)
  40. # set start and end frequency.
  41. self.send("SENS:FREQ:STOP "+ end)
  42. self.send("SENS1:SWEEP:POINT "+str(RESOLUTION))
  43. # set to maximum resolution.
  44. self.send("INIT:MODE:SING")
  45. # set Measurement mode to single.
  46.  
  47.  
  48. def run_measurement(self):
  49. """Starts a Measurement and returns when it has finished.
  50. """
  51. self.send("TRIG:SING")
  52. self.send("*OPC?") # tell device to answer when finished
  53. self.receive() # wait till end of measurement
  54.  
  55. def get_results(self):
  56. """Collects the results of a Measurement as a Python array.
  57. """
  58. self.send("CALC1:TDATA:SDATA?")
  59. self.receive() #throws away length of transmittion
  60. data = b""
  61. #This loop ensures data is complete, as receive behaves unpredictably
  62. while not data.endswith(b"</DataFile>\n"):
  63. data += self.receive()
  64. data = data.decode("ASCII")
  65. start_point = data.find("<!--Freq(GHz);Real; Imag-->") + 35
  66. #35 length of the used find marker + whitespace
  67. end_point = data.find(" </Values>")-1
  68. #-1 removes the newline
  69. data = data[start_point:end_point]
  70. raw_data_array=data.split("\r\n ")
  71. timestamp = datetime.datetime.now().isoformat("_", "seconds")
  72. Ilog = open(self.logdir+"inputlog_"+timestamp+".txt", "w")
  73. Olog = open(self.logdir+"outputlog_"+timestamp+".txt", "w")
  74.  
  75. return_data_array = np.empty([RESOLUTION,3])
  76. for line in raw_data_array:
  77. Ilog.write(line+"\n")
  78. if(line.startswith("<Point_")):
  79. match = re.match(
  80. r"<Point_(\d+)>(.+);(.+);(.+)</Point_\d+>",line,)
  81. iterator = int(match.group(1))-1 #Data starts at 1
  82. frequency = float(match.group(2).replace(",","."))
  83. real = float(match.group(3).replace(",","."))
  84. imag = float(match.group(4).replace(",","."))
  85. if(not(np.isnan(iterator)
  86. or np.isnan(frequency)
  87. or np.isnan(real)
  88. or np.isnan(imag))):
  89. return_data_array[iterator,0] = frequency
  90. return_data_array[iterator,1] = real
  91. return_data_array[iterator,2] = imag
  92. Olog.write(str(iterator)+" "+str(frequency)+" "\
  93. +str(real)+" "+str(imag)+"\n")
  94. Ilog.close()
  95. Olog.close()
  96. return return_data_array
  97.  
  98. def send(self,command):
  99. """sends a command to the VNA, Command format is found in the
  100. Programming guide: https://dl.cdn-anritsu.com/en-us/test-measurement/files/Manuals/Programming-Manual/10410-00746U.pdf
  101. """
  102. self.vna.send(str.encode(command+"\n"))
  103.  
  104. def receive(self):
  105. try:
  106. return self.vna.recv(BUFFER_SIZE)
  107. except Exception as err:
  108. #Catches everything that goes wrong and writes it to file.
  109. #Cancels execution.
  110. outF = open(self.logdir+"error.txt", "a")
  111. outF.write(datetime.datetime.now().isoformat("_", "seconds")+"\n")
  112. outF.write(str(err)+"\n")
  113. outF.close()
  114. sys.exit(str(err))
  115.  
  116. VNA_mat.m
  117. classdef VNA_mat
  118. properties
  119. socket
  120. end
  121. methods
  122. function vna = VNA_mat(IP)
  123. py.importlib.import_module('vna_communication');
  124. vna.socket = py.vna_communication.VNA(IP);
  125. end
  126. function send(vna, command)
  127. vna.socket.send(command);
  128. end
  129.  
  130. function message = receive(vna)
  131. message = vna.socket.receive();
  132. end
  133. function setup(vna,start,stop)
  134. vna.socket.setup(start,stop);
  135. end
  136. function run_measurement(vna)
  137. vna.socket.run_measurement();
  138. end
  139. function result = get_results(vna)
  140. nparray = vna.socket.get_results();
  141. %found at https://de.mathworks.com/matlabcentral/answers/157347-convert-python-numpy-array-to-double
  142. %nparray2mat Convert an nparray from numpy to a Matlab array
  143. %Convert an n-dimensional nparray into an equivalent Matlab array
  144. data_size = cellfun(@int64,cell(nparray.shape));
  145. if length(data_size)==1
  146. % This is a simple operation
  147. result=double(py.array.array('d', py.numpy.nditer(nparray)));
  148. elseif length(data_size)==2
  149. % order='F' is used to get data in column-major order (as in Fortran
  150. % 'F' and Matlab)
  151. result=reshape(double(py.array.array('d', ...
  152. py.numpy.nditer(nparray, pyargs('order', 'F')))), ...
  153. data_size);
  154. else
  155. % For multidimensional arrays more manipulation is required
  156. % First recover in python order (C contiguous order)
  157. result=double(py.array.array('d', ...
  158. py.numpy.nditer(nparray, pyargs('order', 'C'))));
  159. % Switch the order of the dimensions (as Python views this in the
  160. % opposite order to Matlab) and reshape to the corresponding C-like
  161. % array
  162. result=reshape(result,fliplr(data_size));
  163. % Now transpose rows and columns of the 2D sub-arrays to arrive at the
  164. % correct Matlab structuring
  165. result=permute(result,[length(data_size):-1:1]);
  166. end
  167. end
  168. end
  169. end
  170.  
  171.  
  172. vna_test.m
  173.  
  174. clear all
  175. vna = VNA_mat("134.96.22.37");
  176. %vna.send("*IDN?");
  177. %vna.receive();
  178. vna.setup("9.747E+009","9.754E+009");
  179. vna.run_measurement();
  180. res = vna.get_results();
  181. frequencies = zeros(16001,1);
  182. values = zeros(16001,1);
  183. index_ = 1;
  184. while index_ <= 16001
  185. frequency=res(index_,1);
  186. real=res(index_,2);
  187. im=res(index_,3);
  188. frequencies(index_) = frequency;
  189. val = sqrt(real^2+im^2);
  190. values(index_) = val;
  191. %sprintf("%0.4g Real %0.4g Im %0.4g res %0.4g",index_,real,im,val)
  192. index_ = index_ + 1;
  193. end
  194.  
  195. plot(frequencies, values);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement