TB066

AnĂ¡lisis de Circuitos (TB066)
Index Commits Files Refs
tp/scripts/owon_hds25s_bode/bode_scpi_data.py (7617B)
   1 import pyvisa
   2 import time
   3 import numpy as np
   4 
   5 # List of all valid timebases supported by OWON HDS2* series
   6 TIMEBASES = [
   7     (2e-9, "2.0ns"), (5e-9, "5.0ns"), (10e-9, "10.0ns"), (20e-9, "20.0ns"),
   8     (50e-9, "50.0ns"), (100e-9, "100ns"), (200e-9, "200ns"), (500e-9, "500ns"),
   9     (1e-6, "1.0us"), (2e-6, "2.0us"), (5e-6, "5.0us"), (10e-6, "10us"),
  10     (20e-6, "20us"), (50e-6, "50us"), (100e-6, "100us"), (200e-6, "200us"),
  11     (500e-6, "500us"), (1e-3, "1.0ms"), (2e-3, "2.0ms"), (5e-3, "5.0ms"),
  12     (10e-3, "10ms"), (20e-3, "20ms"), (50e-3, "50ms"), (100e-3, "100ms"),
  13     (200e-3, "200ms"), (500e-3, "500ms"), (1.0, "1.0s"), (2.0, "2.0s"),
  14     (5.0, "5.0s"), (10.0, "10s"), (20.0, "20s"), (50.0, "50s"),
  15     (100.0, "100s"), (200.0, "200s"), (500.0, "500s"), (1000.0, "1000s")
  16 ]
  17 
  18 # Supported scale tables according to probe attenuation
  19 VOLT_SCALES = {
  20     "1X": [
  21         (0.010, "10.0mV"), (0.020, "20.0mV"), (0.050, "50.0mV"),
  22         (0.100, "100mV"),  (0.200, "200mV"),  (0.500, "500mV"),
  23         (1.000, "1.00V"),  (2.000, "2.00V"),  (5.000, "5.00V"),
  24         (10.00, "10.0V")
  25     ],
  26     "10X": [
  27         (0.100, "100mV"),  (0.200, "200mV"),  (0.500, "500mV"),
  28         (1.000, "1.00V"),  (2.000, "2.00V"),  (5.000, "5.00V"),
  29         (10.00, "10.0V"),  (20.00, "20.0V"),  (50.00, "50.0V"),
  30         (100.0, "100V")
  31     ],
  32     "100X": [
  33         (1.000, "1.00V"),  (2.000, "2.00V"),  (5.000, "5.00V"),
  34         (10.00, "10.0V"),  (20.00, "20.0V"),  (50.00, "50.0V"),
  35         (100.0, "100V"),   (200.0, "200V"),   (500.0, "500V"),
  36         (1000.0, "1.00kV")
  37     ],
  38     "1000X": [
  39         (10.00, "10.0V"),  (20.00, "20.0V"),  (50.00, "50.0V"),
  40         (100.0, "100V"),   (200.0, "200V"),   (500.0, "500V"),
  41         (1000.0, "1.00kV"),(2000.0, "2.00kV"),(5000.0, "5.00kV"),
  42         (10000.0, "10.0kV")
  43     ]
  44 }
  45 
  46 CSV_FILEPATH      = "csv/bode_data.csv"
  47 LOG_ENABLE        = False
  48 PROBE             = "1X"
  49 GEN_PEAK          = 0.10 # 2*GEN_PEAK peak to peak voltage
  50 FREQS_COUNT       = 10
  51 MEAN_SAMPLE_COUNT = 3
  52 curr_scale_idx    = 2 # 500 mV startup vertical height
  53 scales            = VOLT_SCALES.get(PROBE)
  54 
  55 def LOG(msg):
  56     if LOG_ENABLE:
  57         print(f"[LOG] {msg}")
  58 
  59 def LOG_LOC(loc, msg):
  60     if LOG_ENABLE:
  61         print(f"[LOG]{loc} {msg}")
  62 
  63 def set_best_timebase(frequency):
  64     period = 1.0 / frequency
  65     target_scale = period / 2.0  # Display width is roughly 10 divisions
  66 
  67     # Pick the closest supported value in the list
  68     best_match = min(TIMEBASES, key=lambda x: abs(x[0] - target_scale))
  69     LOG(f"HORizontal:SCALe {best_match[1]}")
  70     time.sleep(0.1)
  71     scope.write(f":HORizontal:SCALe {best_match[1]}")
  72 
  73 def set_best_vert_scale():
  74     global curr_scale_idx
  75 
  76     read_val_str = scope.query(":MEASurement:CH1:MAX?").strip()
  77     LOG_LOC("[set_best_vert_scale]", f"read_val_str == {read_val_str}")
  78 
  79     while read_val_str.startswith(">"):
  80         LOG_LOC("[set_best_vert_scale]['>']", f"startswith('>')")
  81         if curr_scale_idx <= 9:
  82             curr_scale_idx = curr_scale_idx + 1
  83             new_scale = scales[curr_scale_idx][1]
  84             LOG_LOC("[set_best_vert_scale]['>']", f"Changing vertical scale to {new_scale}")
  85             scope.write(f":CH1:SCALe {new_scale}")
  86 
  87             if freq < 10:
  88                 # Roll mode
  89                 time.sleep(10)
  90             else:
  91                 time.sleep(1)
  92 
  93             # Read again with new scale
  94             read_val_str = scope.query(":MEASurement:CH1:MAX?").strip()
  95             LOG_LOC("[set_best_vert_scale]['>'][read again]", f"read_val_str == {read_val_str}")
  96         else:
  97             read_val_str.lstrip(">")
  98 
  99     while read_val_str.startswith("<"):
 100         LOG_LOC("[set_best_vert_scale]['<']", f"startswith('<')")
 101         if curr_scale_idx > 0:
 102             curr_scale_idx = curr_scale_idx - 1
 103             new_scale = scales[curr_scale_idx][1]
 104             # print(f"Changing vertical scale to {new_scale}")
 105             scope.write(f":CH1:SCALe {new_scale}")
 106 
 107             if freq < 10:
 108                 # Roll mode
 109                 time.sleep(10)
 110             else:
 111                 time.sleep(1)
 112 
 113             # Read again with new scale
 114             read_val_str = scope.query(":MEASurement:CH1:MAX?").strip()
 115             LOG_LOC("[set_best_vert_scale]['<']", f"read_val_str == {read_val_str}")
 116         else:
 117             read_val_str.lstrip("<")
 118 
 119     read_val = float(read_val_str)
 120     LOG_LOC("[set_best_vert_scale]", f"read_val == {read_val_str}")
 121 
 122     if curr_scale_idx > 0 and read_val < 2*scales[curr_scale_idx - 1][0]:
 123         curr_scale_idx = curr_scale_idx - 1
 124         new_scale = scales[curr_scale_idx][1]
 125         # print(f"Changing vertical scale to {new_scale}")
 126         scope.write(f":CH1:SCALe {new_scale}")
 127 
 128         if freq < 10:
 129             # Roll mode
 130             time.sleep(10)
 131 
 132         # Read again with new scale
 133         read_val_str = scope.query(":MEASurement:CH1:MAX?").strip()
 134         LOG_LOC("[set_best_vert_scale][read_val < 2*next_scale", f"read_val_str == {read_val_str}")
 135 
 136         while read_val_str.startswith(">") or read_val_str.startswith("<"):
 137             read_val_str = scope.query(":MEASurement:CH1:MAX?").strip()
 138 
 139         read_val = float(read_val_str)
 140 
 141 # example: 5 decades (10^0 to 10^5) at 5 points/decade -> 5 * 5 + 1 = 26 points
 142 # freqs = np.concatenate((np.array([1]), np.logspace(4, 5, num=FREQS_COUNT)))
 143 freqs = np.logspace(0, 5, num=FREQS_COUNT)
 144 freqs = np.unique([int(f) for f in freqs])
 145 print(freqs)
 146 amps  = []
 147 
 148 rm = pyvisa.ResourceManager('@py')
 149 
 150 try:
 151     scope = rm.open_resource("ASRL/dev/ttyUSB0::INSTR")
 152 except:
 153     print("[ERROR] Device not found")
 154     exit(0)
 155 
 156 try:
 157     data = scope.read_raw()
 158     print("Pending:", data)
 159 except pyvisa.errors.VisaIOError as e:
 160     print("No pending SCPI data")
 161 
 162 print("Identification: ", scope.query("*IDN?"), end="")
 163 
 164 # Configure scope
 165 scope.write(f":CH1:SCALe {scales[curr_scale_idx][1]}")
 166 scope.write(":CH1:COUPling AC")
 167 scope.write(f":CH1:PROBE {PROBE}")
 168 scope.write(f":FUNCtion:AMPLitude {GEN_PEAK*2}")
 169 scope.write(":FUNCtion SINE")
 170 
 171 print(f"Generator set to function SINE")
 172 # print("    freq,  amp/peak")
 173 
 174 for freq in freqs:
 175     # print(f"Probing {freq:2.2f} Hz")
 176     scope.write(f":FUNCtion:FREQuency {freq:2.2f}")
 177 
 178     # print(scope.query(":FUNCtion:FREQuency?"))
 179     set_best_timebase(freq)
 180 
 181     # Roll mode
 182     if freq < 10:
 183         scope.write(":CH1:COUPling DC")
 184         time.sleep(10)
 185     else:
 186         scope.write(":CH1:COUPling AC")
 187         time.sleep(0.5)
 188 
 189     amp_arr = []
 190     for i in range(MEAN_SAMPLE_COUNT):
 191         set_best_vert_scale()
 192         read_val_str = scope.query(":MEASurement:CH1:MAX?").strip()
 193         LOG_LOC(f"[main_loop]", f"read_val_str == {read_val_str}")
 194 
 195         while read_val_str.startswith(">") or read_val_str.startswith("<"):
 196             set_best_vert_scale()
 197             read_val_str = scope.query(":MEASurement:CH1:MAX?").strip()
 198             LOG_LOC(f"[main_loop]", f"read_val_str == {read_val_str}")
 199 
 200         read_val = float(read_val_str)
 201 
 202         # print(f"{read_val:<3.3f}")
 203         amp_arr.append(read_val)
 204 
 205         time.sleep(0.5) # time between mean samples
 206 
 207     amp_mean = (sum(amp_arr) / MEAN_SAMPLE_COUNT)
 208     amp_mean = 0.001 if amp_mean < 0.001 else amp_mean
 209 
 210     amp_norm = amp_mean / GEN_PEAK
 211     amps.append(amp_norm)
 212 
 213     print(f"{freq:>8}, {amp_norm:<3.3f}")
 214 
 215 scope.close()
 216 
 217 # print(f"freqs = [{' '.join(map(str, freqs))}]")
 218 # print(f"amps  = [{' '.join(map(str, amps))}]")
 219 
 220 data = np.column_stack((freqs, amps))
 221 np.savetxt(f"{CSV_FILEPATH}",
 222            data,
 223            delimiter=",",
 224            header="Frequency,Amplitude",
 225            comments="",
 226            fmt=["%d", "%.3f"])