SUServo Sample Code
Okay. So calling the servo init isn’t initialising your urukul correctly. Probably one of:clocking issue, dip switches incorrect for servo (you need to switch one to enable servo mode) or a gateware/device_db mismatch. One thing you can try is probing the urukul eem cable and check you get spi transactions when you call the init code. Also try probing the clock chip and check the right clock gets to the ddss
https://nixbld.m-labs.hk/build/13368
https://nixbld.m-labs.hk/build/13271
The conda package (if you want to use conda) is on the channel https://conda.m-labs.hk/artiq-beta/
JSON file with EEM numbers: https://git.m-labs.hk/M-Labs/sinara-systems/src/branch/master/oregon.json
(please check that they are correct, I copied the NUDT ones as you asked)
@sb10q, the kasli-oregon configuration seems to be working just fine! There's something about SU servo though that I wasn't entirely clear on. Is there any way of directly controlling the set point for the Sampler? The closest I could find was the offset parameter in Channel.set_dds(), and it seems like the y-value is being set to this offset parameter regardless of what kind of signal is being fed into the Sampler. It doesn't look like the Urukul signal is being modulated.
I just wanted to clarify whether or not the offset parameter is used to control the set point before continuing to debug our current code/hardware setup.
Yes. E.g. set_dds(offset=-.5)
controls the offset of the ADC inputs and thus the setpoint of the servo.
And make sure you have the P/I profile coefficients and all parameters (ADC channel, channel enable, IIR enable, delay etc), set up as well, then select profile and enable the channel.
The ADC itself measures in machine units, not in Volts. The relation between machine units and volts depends on e.g. the PGIA setting. You can backtrack from IIR filter full scale units to Volts at PGIA input using the gain, like https://m-labs.hk/artiq/manual-beta/_modules/artiq/coredevice/sampler.html#adc_mu_to_volt
- Edited
rjo We were able to get our servo system up and running. Thank you very much for your help!
Edit: In case someone else comes along who might benefit from it, here's an example of some minimal code that gets a servo loop running. This loop will target the input voltage v_t for the Sampler channel adc_ch. The target voltage is set using the offset parameter in set_dds. This offset should be minus the target voltage scaled by the gain.
from artiq.experiment import *
class SUServoMinimal(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("urukul0_cpld")
self.setattr_device("suservo0")
self.setattr_device("suservo0_ch0")
@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.07 # target input voltage (V) for Sampler channel
f = 100000000.0 # frequency (Hz) of Urukul output
o = -v_t*(10.0**(g-1)) # 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),
# activate PI loop (en_iir=1)
self.suservo0_ch0.set_iir(profile=0, adc=adc_ch, kp=kp, ki=ki, g=gl)
self.suservo0_ch0.set_dds(profile=0, frequency=f, offset=o)
self.suservo0_ch0.set(en_out=1, en_iir=1, profile=0)