Hello,
we are currently trying to implement a simple optical intensity stabilization PID loop based on an AOM, photodiode and ARTIQ SUServo sampler + Urukul DDS. This doesn't work at this point, and we want to figure out if it is a software issue (i.e. a code error, as discussed in this message) or an hardware issue (incorrectly set DIP switches on the relevant boards, which we didn't check yet).
To get started we want to ask the SUServo Urukul DDS to output a fixed signal (at 110MHz in the exemple below), in absence of running PID loop. This doesn't work. We based our code on the working code of [(https://forum.m-labs.hk/d/19-suservo-sample-code/3)], which has a device.db file very similar to ours and runs a SUServo PID loop. The code we are using is:
from artiq.experiment import * #imports everything from ARTIQ experiment library
class SUServoMinimal(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("urukul0_cpld") # most likely useless, to be checked
self.setattr_device("suservo0")
self.dds0 = self.get_device("suservo0_ch1") # use DDS channel 1 of Urukul board 0
@kernel
def run(self):
# Prepare core
self.core.reset()
#Initialize and activate SUServo
self.suservo0.init()
self.suservo0.set_config(enable=1)
# Set Sampler gain and Urukul attenuation
g = 0
A = 0.0
self.suservo0.set_pgia_mu(0, g) # set gain on Sampler channel 0 to 10^g
self.suservo0.cpld0.set_att(0, A) # set attenuation on Urukul channel 0 to 0
# Set physical parameters
v_t = 0.0 # target input voltage (V) for Sampler channel
f = 110000000.0 # frequency (Hz) of Urukul output
o = 0.0 # offset to assign to servo to reach target voltage
# Set PI loop parameters
kp = 0.005 # proportional gain in loop
ki = -10.0 # integrator gain
gl = 0.0 # integrator gain limit
adc_ch = 0 # Sampler channel to read from
# Input parameters, activate Urukul output (en_out=1),
# Deactivates PI loop (en_iir=0)
self.dds0.set_iir(profile=0, adc=adc_ch, kp=kp, ki=ki, g=gl)
self.dds0.set_dds(profile=0, frequency=f, offset=o)
self.dds0.set(en_out=1, en_iir=0, profile=0) # en_out=1 (=0) closes (opens) the RF switch for dds0
# en_iir=0 deactivates the feedback loop
delay(1*ms)
self.dds0.set_y(0, 0.8)
and the relevant part of our device.db file is:
device_db["suservo0_ch0"] = {
"type": "local",
"module": "artiq.coredevice.suservo",
"class": "Channel",
"arguments": {"channel": 0x00001e, "servo_device": "suservo0"}
}
device_db["suservo0_ch1"] = {
"type": "local",
"module": "artiq.coredevice.suservo",
"class": "Channel",
"arguments": {"channel": 0x00001f, "servo_device": "suservo0"}
}
device_db["suservo0_ch2"] = {
"type": "local",
"module": "artiq.coredevice.suservo",
"class": "Channel",
"arguments": {"channel": 0x000020, "servo_device": "suservo0"}
}
device_db["suservo0_ch3"] = {
"type": "local",
"module": "artiq.coredevice.suservo",
"class": "Channel",
"arguments": {"channel": 0x000021, "servo_device": "suservo0"}
}
[...]
device_db["suservo0"] = {
"type": "local",
"module": "artiq.coredevice.suservo",
"class": "SUServo",
"arguments": {
"channel": 0x000026,
"pgia_device": "spi_sampler2_pgia",
"cpld0_device": "urukul0_cpld",
"cpld1_device": "urukul1_cpld",
"dds0_device": "urukul0_dds",
"dds1_device": "urukul1_dds"
}
}
device_db["spi_sampler2_pgia"] = {
"type": "local",
"module": "artiq.coredevice.spi2",
"class": "SPIMaster",
"arguments": {"channel": 0x000027}
}
Sanity checks we performed :
- using self.dds0.set(en_out=1, en_iir=0, profile=0) we can turn green the RF switch LED of the Urukul DDS channel of interest (channel 1 in code above), which indicates that the RF switch is correctly closed. Conversely we can turn the LED off using self.dds0.set(en_out=0, en_iir=0, profile=0). This indicates additionally that we are looking at the right output channel for the RF signal.
- we tried the code above for all suservo0_ch0, suservo0_ch1, suservo0_ch2 and suservo0_ch3 channels.
- we used the command print(self.dds0.get_y(0)) to check that self.dds0.set_y(0, 0.8) indeed writes the value 0.8 for the amplitude of the RF signal output, which it does.
Do you see anything evidently wrong in the code above? Thanks in advance for your help,
Vincent Barbé, LaserLaB Amsterdam