Hello, we are working on a project to automatise the testing of any un-proven code from the Owntech repo.
So far we decided to only automatise a simple test sequence, by testing a functionnality in the platformIO editor (create PWMs with different phase), and then use a python script to auto-build/send it in the SPIN, and in that same script we will use pyvisa to access the instrument and make a selection of relevant measures (in the case of PWM, their vAmp, duty cycle and phase compared to eachother), then use that data to OK/KO the test.
If this works, this base could be easely expanded to a lot of functions from the SPIN, and tested in a single script.
We assembled our testbench already (1 spin connected with 3 mux, synchronising them, and all relevant outputs linked to a mux channel, for exemple three pwms output on each channel0 of each mux, with a measure probe in the mux output pin, that we can access via Pyvisa), and we made functions to set the mux channels we want, which was validated. PWM generation also works.
Our next step is to control our instrument via pyvisa. We made a code that we couldn’t test properly besides managing to connect to our device and preset it.
Here is our python script so far, as requested by Mr Villa :
import time
import pyvisa
def setup_scope_for_measurements(scope, averages=8, do_autoset=True):
# Reset système (comme si on redémarrait)
scope.write(":SYSTem:RESet")
time.sleep(1.0)
# Active les voies 1 et 2 (on test sans la 3 pour l'instant)
scope.write(":CHANnel1:DISPlay ON")
scope.write(":CHANnel2:DISPlay ON")
# Couplage DC
scope.write(":CHANnel1:COUPling DC")
scope.write(":CHANnel2:COUPling DC")
# Nettoie toutes les mesures actives
scope.write(":MEASure:DELete")
# Seuils par défaut
scope.write(":MEASure:THReshold:DEFault")
# Acquisition en moyenne
scope.write(":ACQuire:TYPE AVERages")
# Le guide indique un count entier de 1 Ă 16
avg = int(max(1, min(16, averages)))
scope.write(f":ACQuire:AVERages {avg}")
# AUToset pour un trigger automatique
if do_autoset:
scope.write(":AUToset")
time.sleep(1.0)
time.sleep(0.5)
def _query_float(scope, cmd):
resp = scope.query(cmd).strip()
return float(resp)
def measure_ch1_ch2_and_phase(scope):
# Amplitudes
vamp_ch1 = _query_float(scope, ":MEASure:ITEM? VAMP,CHANnel1")
vamp_ch2 = _query_float(scope, ":MEASure:ITEM? VAMP,CHANnel2")
# Déphasage entre CH1 et CH2
phase_rr = _query_float(scope, ":MEASure:ITEM? RRPHase,CHANnel1,CHANnel2")
return vamp_ch1, vamp_ch2, phase_rr
if __name__ == "__main__":
rm = pyvisa.ResourceManager()
resources = rm.list_resources()
print("Ressources VISA détectées :")
print(resources)
if not resources:
raise RuntimeError(
"Aucune ressource VISA détectée. Vérifie le câble USB, le driver VISA, "
"et que l'oscillo est bien en mode remote/USB-TMC."
)
scope = rm.open_resource(resources[0])
scope.timeout = 10000
print("IDN =", scope.query("*IDN?").strip())
setup_scope_for_measurements(scope, averages=8, do_autoset=True)
v1, v2, ph = measure_ch1_ch2_and_phase(scope)
print(f"Vamp CH1 = {v1} V")
print(f"Vamp CH2 = {v2} V")
print(f"RRPHase(CH1,CH2) = {ph} (unité selon l'oscillo, typiquement en degrés)")
Thanks for reading us ![]()


