mirror of
https://github.com/jonathanhogg/scopething
synced 2025-07-14 03:02:09 +01:00
Just poking around really
This commit is contained in:
38
scope.py
38
scope.py
@ -54,15 +54,17 @@ class Scope(vm.VirtualMachine):
|
||||
self.awg_sample_buffer_size = 1024
|
||||
self.awg_minimum_clock = 33
|
||||
self.awg_maximum_voltage = 3.33
|
||||
self.analog_params = self.AnalogParams(20.2, -4.9, 300, 18.333, -7.517)
|
||||
self.analog_offsets = {'A': 0, 'B': 0}
|
||||
self.analog_min = -5.7
|
||||
#self.analog_params = self.AnalogParams(20, -5, 300, 18.3, -7.5)
|
||||
#self.analog_offsets = {'A': 0, 'B': 0}
|
||||
self.analog_params = self.AnalogParams(19.7, -4.86, 298.6, 18.361, -7.496)
|
||||
self.analog_offsets = {'A': -0.00937, 'B': 0.00937}
|
||||
self.analog_min = -5.5
|
||||
self.analog_max = 8
|
||||
self.capture_clock_period = 25e-9
|
||||
self.capture_buffer_size = 12<<10
|
||||
self.timeout_clock_period = 6.4e-6
|
||||
else:
|
||||
raise RuntimeError(f"Unsupported scope revision: {revision}")
|
||||
raise RuntimeError(f"Unsupported scope, revision: {revision}")
|
||||
self._awg_running = False
|
||||
Log.info(f"Initialised scope, revision: {revision}")
|
||||
|
||||
@ -78,10 +80,10 @@ class Scope(vm.VirtualMachine):
|
||||
params = self.analog_params if params is None else self.AnalogParams(*params)
|
||||
l = (low - params.offset) / params.scale
|
||||
h = (high - params.offset) / params.scale
|
||||
al = params.d + params.f * (2*l-1)**2
|
||||
ah = params.d + params.f * (2*h-1)**2
|
||||
dl = l + (2*l-h)*al/params.b
|
||||
dh = h + (2*h-l-1)*ah/params.b
|
||||
al = params.d + params.f*(2*l-1)**2
|
||||
ah = params.d + params.f*(2*h-1)**2
|
||||
dl = l - al*(h-2*l)/params.b
|
||||
dh = h + ah*(2*h-l-1)/params.b
|
||||
return dl, dh
|
||||
|
||||
async def capture(self, channels=['A'], trigger=None, trigger_level=None, trigger_type='rising', hair_trigger=False,
|
||||
@ -323,21 +325,21 @@ class Scope(vm.VirtualMachine):
|
||||
async def calibrate(self, n=32):
|
||||
import numpy as np
|
||||
from scipy.optimize import least_squares
|
||||
global items
|
||||
items = []
|
||||
await self.start_generator(frequency=1000, waveform='square')
|
||||
i = 0
|
||||
low_min, high_max = self.calculate_lo_hi(self.analog_min, self.analog_max)
|
||||
low_max, high_min = self.calculate_lo_hi(0, self.awg_maximum_voltage)
|
||||
for low in np.linspace(low_min, low_max*0.9, n):
|
||||
for high in np.linspace(high_min*1.1, high_max, n):
|
||||
for low in np.linspace(low_min, low_max, n):
|
||||
for high in np.linspace(high_min, high_max, n):
|
||||
data = await self.capture(channels=['A','B'], period=2e-3 if i%2 == 0 else 1e-3, nsamples=2000, low=low, high=high, timeout=0, raw=True)
|
||||
A = np.fromiter(data['A'].values(), dtype='float')
|
||||
A.sort()
|
||||
B = np.fromiter(data['B'].values(), dtype='float')
|
||||
B.sort()
|
||||
Azero, Amax = A[10:490].mean(), A[510:990].mean()
|
||||
Bzero, Bmax = B[10:490].mean(), B[510:990].mean()
|
||||
Azero, Amax = A[25:475].mean(), A[525:975].mean()
|
||||
Bzero, Bmax = B[25:475].mean(), B[525:975].mean()
|
||||
if Azero > 0.1 and Bzero > 0.1 and Amax < 0.9 and Bmax < 0.9:
|
||||
zero = (Azero + Bzero) / 2
|
||||
analog_range = self.awg_maximum_voltage / ((Amax + Bmax)/2 - zero)
|
||||
analog_low = -zero * analog_range
|
||||
@ -350,15 +352,19 @@ class Scope(vm.VirtualMachine):
|
||||
def f(params, analog_low, analog_high, low, high):
|
||||
lo, hi = self.calculate_lo_hi(analog_low, analog_high, params)
|
||||
return np.sqrt((low - lo) ** 2 + (high - hi) ** 2)
|
||||
result = least_squares(f, self.analog_params, args=items.T[:4], max_nfev=10000,
|
||||
bounds=([0, -np.inf, 285, 17.4, -7.89], [np.inf, np.inf, 315, 19.2, -7.14]))
|
||||
result = least_squares(f, self.analog_params, args=items.T[:4], xtol=1e-9, max_nfev=10000,
|
||||
bounds=([0, -np.inf, 200, 0, -np.inf],
|
||||
[np.inf, np.inf, 400, np.inf, 0]))
|
||||
if result.success in range(1, 5):
|
||||
Log.info(f"Calibration succeeded: {result.success}")
|
||||
self.analog_params = params = self.AnalogParams(*result.x)
|
||||
Log.info(f"Analog parameters: d={params.d:.1f}Ω f={params.f:.2f}Ω b={params.b:.1f}Ω scale={params.scale:.3f}V offset={params.offset:.3f}V")
|
||||
clow, chigh = self.calculate_lo_hi(items[:,0], items[:,1])
|
||||
diff = np.sqrt((((clow-items[:,2])**2).mean() + ((chigh-items[:,3])**2).mean()) / 2)
|
||||
Log.info(f"Mean error: {diff*10000:.1f}bps")
|
||||
offsets = items[:,4]
|
||||
offset = offsets.mean()
|
||||
Log.info(f"Mean A-B offset is {offset*1000:.1f}mV (+/- {100*offsets.std()/offset:.1f}%)")
|
||||
Log.info(f"Mean A-B offset: {offset*1000:.1f}mV (+/- {100*offsets.std()/offset:.1f}%)")
|
||||
self.analog_offsets = {'A': -offset/2, 'B': +offset/2}
|
||||
else:
|
||||
Log.warning(f"Calibration failed: {result.message}")
|
||||
|
Reference in New Issue
Block a user