Add gain control & options for data collection/plotting; fix doc

master
Harry Ho 2021-03-15 15:26:36 +08:00
parent bd792739c3
commit 33d81cdbdc
3 changed files with 38 additions and 16 deletions

View File

@ -6,7 +6,7 @@
# └── pi/
# └── mlabs-testsuite/
# ├── rp_get_sayma_data.py
# └── creotech-raw/
# └── raw/
# | (possible existing data files, will be overwritten)
# ├── rp_..._y1_raw.bin.py
# ├── rp_..._y2_raw.bin.py
@ -25,24 +25,27 @@
export HOST=pi@rpi-2
export HOSTPORT=6000
if [[ $1 = "" ]] || [[ $2 = "" ]] || [[ $3 = "" ]] || [[ $4 = "" ]]
if [[ $1 = "" ]] || [[ $2 = "" ]] || [[ $3 = "" ]] || [[ $4 = "" ]] || [[ $5 = "" ]]
then
echo "Arguments: <RP#1 name> <RP#1 channel> <RP#2 name> <RP#2 channel>"
echo "(RP#1 and RP#2 can be the same)"
echo "Arguments: <RP#1 name> <RP#1 channel> <RP#2 name> <RP#1 channel> <RP#1 name>:<IN1 gain>,<IN2 gain> [<RP#2 name>:<IN1 gain>,<IN2 gain>]"
echo "(If RP#1 and RP#2 are the same, skip the bracketed arguments)"
echo "Examples: "
echo "(1) creotech-1 1 creotech-1 2 creotech-1:LV,HV"
echo "(2) creotech-1 1 creotech-2 1 creotech-1:LV,LV creotech-2:HV,HV"
exit
fi
# Acquire data at the remote
if [[ $1 = $3 ]]
then
ssh -t -p $HOSTPORT $HOST "cd mlabs-testsuite && python3 rp_get_sayma_data.py creotech-raw $1"
ssh -t -p $HOSTPORT $HOST "cd mlabs-testsuite && python3 rp_get_sayma_data.py raw $5"
else
ssh -t -p $HOSTPORT $HOST "cd mlabs-testsuite && python3 rp_get_sayma_data.py creotech-raw $1 $3"
ssh -t -p $HOSTPORT $HOST "cd mlabs-testsuite && python3 rp_get_sayma_data.py raw $5 $6"
fi
# Transfer data from remote to local
scp -P $HOSTPORT $HOST:/home/pi/mlabs-testsuite/creotech-raw/rp_$1_y$2_raw.bin creotech-raw/
scp -P $HOSTPORT $HOST:/home/pi/mlabs-testsuite/creotech-raw/rp_$3_y$4_raw.bin creotech-raw/
scp -P $HOSTPORT $HOST:/home/pi/mlabs-testsuite/raw/rp_$1_y$2_raw.bin creotech-raw/
scp -P $HOSTPORT $HOST:/home/pi/mlabs-testsuite/raw/rp_$3_y$4_raw.bin creotech-raw/
# Plot data at local
# (Note: requires numpy, matplotlib and scipy on local)

View File

@ -46,15 +46,17 @@ def main():
y1 = rp_raw_to_numpy(y1_raw)
y2 = rp_raw_to_numpy(y2_raw)
# Note that RedPitaya's oscilloscope has a sampling rate @ 125MHz
# Define t as an array of timestamps (in seconds) for each sample
# (Note that RedPitaya's oscilloscope has a sampling rate @ 125MHz)
t = np.arange(y1.shape[0])/125e6
# Generate matrix Y by having arrays y1 and y2 as 2 rows
y = np.c_[y1, y2].T
# Multiply an array of cos(2pi*9e6*t) with each row in Y;
# Then, downsample the array by 10 as Z.
# Element-wise multiply an array of cos(2pi*9e6*t) with each row in Y;
# Then, downsample the array by 10 as Z
z = signal.decimate(y*np.exp(1j*2*np.pi*9e6*t), q=10, ftype="fir", zero_phase=True)[:, 10:]
# Downsample Z by 10 again.
z = signal.decimate(z, q=10, ftype="fir", zero_phase=True)[:, 10:]
# Element-wise multiply Z[0] with the conjugate of Z[1] to get the phase difference (i.e. angle(z0) - angle(z1)), and use the mean value.
angle = np.angle(np.mean(z[0]*z[1].conj()))
print(angle)

View File

@ -6,9 +6,11 @@ import os
class RPSCPI:
def __init__(self, rp_name, rp_host):
def __init__(self, rp_name, rp_host, ch1_gain, ch2_gain):
self.name = rp_name
self.host = rp_host
self.ch1_gain = ch1_gain
self.ch2_gain = ch2_gain
def connect(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -27,6 +29,8 @@ class RPSCPI:
def trigger_prep(self):
self.sendmsg("ACQ:RST")
self.sendmsg("ACQ:SOUR1:GAIN {}".format(self.ch1_gain.upper()))
self.sendmsg("ACQ:SOUR2:GAIN {}".format(self.ch2_gain.upper()))
self.sendmsg("ACQ:START")
async def trigger(self):
@ -55,17 +59,30 @@ async def gather_trigger(rp_list):
def main():
parser = argparse.ArgumentParser(description="Data collection tool for Sayma DAC/TTL at RedPitaya")
parser.add_argument("dir", help="output directory", type=str)
parser.add_argument("rps", help="name(s) of the target RedPitayas where data is collected "
"simultaneously; any of: " + " ".join(list(RP_IP_ADDRS.keys())),
parser.add_argument("rps_gains", metavar="RP_NAME:CH1_GAIN,CH2_GAIN",
help="choose LV (+-1V) gain or HV (+-20V) gain on each channel for RP named <RP_NAME>; "
"e.g. mlabs:LV,HV means LV for IN1 and HV for IN2 on RP mlabs;\n"
"<RP_NAME> must be one of: " + " ".join(list(RP_IP_ADDRS.keys())),
type=str, nargs='+')
parser.add_argument("--txt", help="save data as additional human-readable text files",
action="store_true")
args = parser.parse_args()
gains = dict()
try:
for gain in args.rps_gains:
rp_name, ch1ch2_gains = gain.split(':')
ch1_gain, ch2_gain = ch1ch2_gains.split(',')
gains[rp_name] = ch1_gain, ch2_gain
if rp_name == "" or ch1_gain == "" or ch2_gain == "":
raise SyntaxError("Must specify IN1 and IN2 gains for each target RP.")
except ValueError:
raise SyntaxError("Must specify input gains in the format of: <RP_NAME>:<CH1_GAIN>,<CH2_GAIN>")
# Connect a socket to each RP
rps = []
for rp_name in args.rps:
rp = RPSCPI(rp_name, RP_IP_ADDRS[rp_name])
for rp_name in gains:
rp = RPSCPI(rp_name, RP_IP_ADDRS[rp_name], *gains[rp_name])
rp.connect()
rps.append(rp)