Partie HW faite a peu près

This commit is contained in:
hackens-bot 2025-01-16 13:42:30 +01:00
parent 3c053bf278
commit 524ec7bf09
4 changed files with 195 additions and 99 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
Microphone as source follower. 175uA DC @ ~3V Vds
X = [62.0, 68.0, 75.0, 82.0, 91.0, 100.0, 110.00000000000001, 120.0, 130.0, 150.0, 160.0, 180.0, 200.0, 220.00000000000003, 240.0, 270.0, 300.0, 330.0, 360.0, 390.0, 430.0, 470.0, 509.99999999999994, 560.0, 620.0, 680.0, 750.0, 819.9999999999999, 910.0, 1000.0, 1100.0, 1200.0, 1300.0, 1500.0, 1600.0, 1800.0, 2000.0, 2200.0, 2400.0, 2700.0, 3000.0, 3300.0, 3600.0, 3900.0, 4300.0, 4700.0, 5100.0, 5600.0, 6200.0, 6800.0, 7500.0, 8200.0, 9100.0, 10000.0, 11000.0, 12000.0, 13000.0, 15000.0, 16000.0, 18000.0, 20000.0]
H = [(0.47012032175840673+0.01812983402014712j), (0.470773859825163+0.01694020487348213j), (0.47014391070243977+0.015085538991270814j), (0.47015580025611164+0.01290140838256883j), (0.4707965853705939+0.012540456593345836j), (0.4702655782670737+0.01146515427066669j), (0.47001958941149374+0.009066724097094081j), (0.4698897845061736+0.008590954654956465j), (0.4703328317106061+0.007680708662404258j), (0.47059597197084874+0.006947035949722949j), (0.4704696033876575+0.00577097334067109j), (0.4706101838316291+0.004496916581939091j), (0.4700645514757954+0.004640777774023917j), (0.46970384793911085+0.0038522275542666844j), (0.47072172644838994+0.004356868460710158j), (0.46985620214068086+0.0027604993703299464j), (0.4706992493463072+0.002204339769185796j), (0.47106305332005566+0.0021205228985848017j), (0.47028285448669327+0.0018612810692497153j), (0.4691514968724328+0.002292957901098495j), (0.4701873122263507+0.0002420230304226658j), (0.4689285261898509+0.0007289920633161568j), (0.46956552462586804-0.0007236174387345418j), (0.4678562305849072-0.0006907393785490914j), (0.46836755615019-0.0006038427857997494j), (0.4689235574748159-0.0016181768655454802j), (0.46876318278299123-0.0017764947735754034j), (0.4683097999229312-0.0027640827428271906j), (0.46786090676077974-0.002610856644027095j), (0.46753731928396514-0.002241714250446953j), (0.46801984732360963-0.002119721318204412j), (0.4663227653685854-0.0016727148025411536j), (0.4663031260029301-0.0022085460059039328j), (0.4658401896506971-0.0020177518020752486j), (0.46612388968980756-0.002207265245165768j), (0.4645078371101538-0.0028048732307074937j), (0.46394264877360886-0.0021639899863904162j), (0.4642719966632143-0.0015964764527535004j), (0.4632949784333158-0.0018359364430161399j), (0.46339335082824507-0.0007557123371271958j), (0.46374916001466004-0.0006997385251981024j), (0.46251209195262455-0.00011522690154944387j), (0.46177373985629666+0.0005354488426995059j), (0.4630923556768662+0.0009618057371807924j), (0.46250026655427934+0.002019603274076546j), (0.46115066695013796+0.002618340722087239j), (0.4599367294994153+0.001487858985361092j), (0.45947368133692446+0.0026319865902357893j), (0.4607616438306012+0.004473565837816463j), (0.46123373027180997+0.0039563877327196545j), (0.4612432999999601+0.004773317207737592j), (0.46113397679743406+0.006135235798210173j), (0.46122910037870635+0.005727347168252464j), (0.46150279974005726+0.007471744392586996j), (0.46260297120248955+0.007760981385780426j), (0.461474728572703+0.010231892504492484j), (0.46216777324979+0.009433273729074564j), (0.46091102876674295+0.010621600555034331j), (0.46093670915980167+0.012440290976269985j), (0.46216882884840704+0.014888096834763371j), (0.46407411135079274+0.015274025203592433j)]
We get a ~12kOhm output impedance, and negligible output capacitance.

View file

@ -79,15 +79,18 @@ audio_strm = paudio.open(format=pa.paFloat32,
print(paudio.get_default_output_device_info())
print(audio_strm.is_active())
def acquire_samples(sc_frequency, oscillo):
global new_f
global change_f
global trans_done
new_f = sc_frequency
change_f = True
while (change_f == True) or (trans_done == False):
time.sleep(0.05)
time.sleep(0.2)
time.sleep(0.01)
time.sleep(0.1)
oscillo.write("acquire:state run")
oscillo.write("data:source CH1")
@ -104,6 +107,12 @@ def manage_measures(f_list, oscillo): # These are NOT normalized frequencies
hscale_index = 0
current_hscale = hscales[hscale_index]
vscales = [0.25, 100e-3, 50e-3, 25e-3]
vscales_str = ["2.5e-1", "1.0e-1", "5.0e-2", "2.5e-2"]
vscale_index = 0
current_vscale = vscales[vscale_index]
cal_A = []
cal_B = []
cal_done = False
@ -115,16 +124,44 @@ def manage_measures(f_list, oscillo): # These are NOT normalized frequencies
for f in f_list:
sc_frequency = np.round(2**20/44100 * f)/2**20
num_periods = f * 10 * current_hscale
update_hscale = False
while(num_periods >= 5 * 2.5):
hscale_index += 1
current_hscale = hscales[hscale_index]
num_periods = f * 10 * current_hscale
update_hscale = True
if update_hscale:
print("horizontal:main:scale " + hscales_str[hscale_index])
oscillo.write("horizontal:main:scale " + hscales_str[hscale_index])
cal_done = False
print(f, " : ", current_hscale,"s/div, ", num_periods, " periods")
A, B = acquire_samples(sc_frequency, oscillo)
is_sat, is_under = False, True
for x in B:
is_sat |= (abs(x) >= 127)
is_under &= ~(abs(x) >= 64)
while((is_sat and vscale_index != 0) or (is_under and vscale_index != len(vscales)-1)):
if(is_sat):
print("We have saturation")
vscale_index-=1
elif(is_under):
print("We are wasting bits")
vscale_index+=1
current_vscale = vscales[vscale_index]
osci.write("ch2:scale " + vscales_str[vscale_index])
cal_done = False
A, B = acquire_samples(sc_frequency, oscillo)
is_sat, is_under = False, True
for x in B:
is_sat |= (abs(x) >= 120)
is_under &= ~(abs(x) >= 64)
if not cal_done:
cal_A, cal_B = acquire_samples(0., oscillo)
cal_done = True
@ -134,6 +171,8 @@ def manage_measures(f_list, oscillo): # These are NOT normalized frequencies
f_acq = 250./current_hscale
rel_f = f / f_acq
B *= current_vscale/vscales[0]
# Obtain the Fourier transforms of A, B @ rel_f, with flattop windowing
V = np.exp(-2.0j * np.pi * np.arange(2500) * rel_f)
h = np.sum(B*V)/np.sum(A*V)
@ -176,17 +215,53 @@ osci.write("trigger:main:type EDGE")
osci.write("acquire:mode sample")
osci.write("acquire:stopafter sequence")
osci.write("data:encdg RIBinary")
decade = [1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2]
X = [68., 82] + list(np.array(decade)*([100.]*len(decade))) + list(np.array(decade) * ([1000.]*len(decade))) + [1e4, 1.2e4, 1.5e4, 1.8e4]
def build_spoints(decade):
res = []
power_of_ten = 10
while(power_of_ten <= 100000):
for x in decade:
f = x * power_of_ten
if(60. <= f and f <= 20000.):
res.append(f)
power_of_ten *= 10
return res
e12 = [1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2]
e24 = [1.0, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.7, 3.0, 3.3, 3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8, 7.5, 8.2, 9.1]
e48 = [1.00, 1.05, 1.10, 1.15, 1.21, 1.27, 1.33, 1.40, 1.47, 1.54, 1.62, 1.69, 1.78, 1.87, 1.96, 2.05, 2.15, 2.26, 2.37, 2.49, 2.61, 2.74, 2.87, 3.01, 3.16, 3.32, 3.48, 3.65, 3.83, 4.02, 4.22, 4.42, 4.64, 4.87, 5.11, 5.36, 5.62, 5.90, 6.19, 6.49, 6.81, 7.15, 7.50, 7.87, 8.25, 8.66, 9.09, 9.53]
X = build_spoints(e24)
print(X)
H = manage_measures(X, osci)
Y = 20 * np.log10(np.abs(H))
phase = np.angle(H, deg=True)
for i in range(1, len(phase)):
while(abs(phase[i] - phase[i - 1]) >= 180):
if(phase[i] >= phase[i-1]):
phase[i] -= 360
else:
phase[i] += 360
print(X)
print(H)
print("Corrected phase/magnitude :")
print(phase)
print(Y)
fig, axes = plt.subplots(nrows = 2, ncols=1, sharex = True)
axes[0].semilogx(X,Y)
axes[0].grid()
axes[1].semilogx(X, np.angle(H, deg=True))
axes[1].semilogx(X, phase)
axes[1].grid()
plt.show(block = False)
plt.figure(2)
plt.plot(X, phase)
plt.show()