DMA Acquisition breaks on 2nd attempt, every time.
Posted: Wed Apr 24, 2024 7:28 pm
125-14 (2-channel)
# Version: 2.00-aff683518
# Build: 35
# Commit: aff683518f5e62e9eb01c944949f9c3b7da1ec0f
# U-Boot: "redpitaya-v2022.1"
# Linux Kernel: "branch-redpitaya-v2024.1"
# Pro Applications: ""
Hi All,
Following the example: "acquire_trigger_posedge_axi_bigbuffer.py" to acquire RFIn1, and using an external-PE trigger.
Original code from:
GIT: \RedPitaya-master\RedPitaya-master\Examples\python\acquire_trigger_posedge_axi_bigbuffer.py
I intend to compare transfer times using different block sizes. This works for the first try, but then after trying another acquisition (with the same block size - as a test), the code breaks. - Pointing to a basic misunderstanding (on my part) of how this is supposed to work.
Error:
As shown, the first iteration seems to work, but when I try one more acquisition loop (with the same settings), things break. Harshly. It feels like I'm walking over some memory, or something low level like that, as the board sometimes hangs (and loses all network awareness, requiring a reboot).
Any ideas?
-Chris
# Version: 2.00-aff683518
# Build: 35
# Commit: aff683518f5e62e9eb01c944949f9c3b7da1ec0f
# U-Boot: "redpitaya-v2022.1"
# Linux Kernel: "branch-redpitaya-v2024.1"
# Pro Applications: ""
Hi All,
Following the example: "acquire_trigger_posedge_axi_bigbuffer.py" to acquire RFIn1, and using an external-PE trigger.
Original code from:
GIT: \RedPitaya-master\RedPitaya-master\Examples\python\acquire_trigger_posedge_axi_bigbuffer.py
I intend to compare transfer times using different block sizes. This works for the first try, but then after trying another acquisition (with the same block size - as a test), the code breaks. - Pointing to a basic misunderstanding (on my part) of how this is supposed to work.
Error:
I am looping the bottom section of the code below (range(2)):"ner_acquire_trigger_posedge_axi_bigbuffer.py"
Acquire # 0
ACQ:AXI:DATA:UNITS?: RAW
ACQ:AXI:DEC?: 1
Start address 16777216 size of available memory 2097152
Number of samples to capture per channel 1048576
All data captured
All data transferred. Fail_ct: 40. Samples recovered: 1050000.
Buffer last 100 samples [ -92. -89. -91. -91. -90. <snip>]
Releasing Red Pitaya resources.
Traceback (most recent call last):
File "ner_acquire_trigger_posedge_axi_bigbuffer.py", line 61, in <module>
print('ACQ:AXI:DATA:UNITS?: ',rp_s.txrx_txt('ACQ:AXI:DATA:UNITS?'))
File "redpitaya_scpi.py", line 99, in txrx_txt
return self.rx_txt()
File "redpitaya_scpi.py", line 46, in rx_txt
chunk = self._socket.recv(chunksize).decode('utf-8') # Receive chunk size of 2^n preferably
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 10: invalid start byte
Acquire # 1
Process finished with exit code 1
Code: Select all
#!/usr/bin/python3
import redpitaya_scpi as scpi
import matplotlib.pyplot as plot
import struct
import time
import numpy as np
# ---- CUSTOM CODE START ----
# The Red Pitaya has an External Trigger Input on DIO0_P
# Setup and reserve that pin for EXT TRIG use.
# Use by default DIO1_P as an output line to fire the HV Pulser.
# Connect externally DIO0_P and DIO1_P together via a series 300-ohm resistor,
# to feed the threaded trigger signal back into the Red Pitaya.
def pulser_fire_dio_setup(my_rp_s, this_dio='DIO1_P'):
# Set Red Pitaya EXT TRIG pin to input
# There's no indication in the docs or examples that we need to do this.
# But it sure seems like a good idea to me.
my_rp_s.tx_txt('DIG:PIN:DIR IN, DIO0_P')
# Set pulser trigger-in pin to output
my_rp_s.tx_txt(f'DIG:PIN:DIR OUT, {this_dio}')
# set pulser trigger pin LOW
my_rp_s.tx_txt(f'DIG:PIN {this_dio},0')
return
# The Red Pitaya has an External Trigger Input on DIO0_P
# Setup and reserve that pin for EXT TRIG use.
# Use, by default, DIO1_P as an output line to fire the HV Pulser.
def pulser_fire_once(my_rp_s, this_dio='DIO1_P'):
# Set DIO High, delay tiny bit, set pulser Low.
my_rp_s.tx_txt(f'DIG:PIN {this_dio},1')
time.sleep(0.05)
my_rp_s.tx_txt(f'DIG:PIN {this_dio},0')
time.sleep(0.05)
return
# ^^^^ CUSTOM CODE END ^^^^
rp_s = scpi.scpi('192.168.0.91')
# ---- CUSTOM CODE START ----
# Setup Red Pitaya Output #2 to control the pulser
pulser_fire_dio_setup(rp_s)
# ^^^^ CUSTOM CODE END ^^^^
for i in range(2): # 1st loop seems to work. Next one does not.
print(f"Acquire # {i}")
rp_s.tx_txt('ACQ:RST')
rp_s.tx_txt('ACQ:DATA:FORMAT BIN')
rp_s.tx_txt('ACQ:AXI:DATA:UNITS RAW')
print('ACQ:AXI:DATA:UNITS?: ',rp_s.txrx_txt('ACQ:AXI:DATA:UNITS?'))
rp_s.check_error()
rp_s.tx_txt('ACQ:AXI:DEC 1')
print('ACQ:AXI:DEC?: ',rp_s.txrx_txt('ACQ:AXI:DEC?'))
rp_s.check_error()
start = int(rp_s.txrx_txt('ACQ:AXI:START?'))
size = int(rp_s.txrx_txt('ACQ:AXI:SIZE?'))
samples = (size // 2) # 1 sample = 16 Bit
rp_s.check_error()
print("Start address ",start," size of available memory ",size)
print("Number of samples to capture per channel " + str(samples))
# Specify the buffer sizes in bytes for the first and second channels
add_str_ch1 = 'ACQ:AXI:SOUR1:SET:Buffer ' + str(start) + ',' + str(size)
rp_s.tx_txt(add_str_ch1)
rp_s.check_error()
# You need to specify the number of samples after the trigger
rp_s.tx_txt('ACQ:AXI:SOUR1:Trig:Dly '+ str(samples))
rp_s.check_error()
rp_s.tx_txt('ACQ:AXI:SOUR1:ENable ON')
rp_s.check_error()
rp_s.tx_txt('ACQ:START')
# rp_s.tx_txt('ACQ:TRIG CH1_PE') # Replaced below.
# rp_s.check_error()
# ---- CUSTOM CODE START ----
rp_s.tx_txt('ACQ:TRig:LEV 0.9') # 0.9V seems to work reliably so far.
rp_s.tx_txt('ACQ:TRIG EXT_PE') # Wait for Trigger on the External Input, Positive Edge
# ^^^^ CUSTOM CODE END ^^^^
while 1:
rp_s.tx_txt('ACQ:AXI:SOUR1:TRIG:FILL?')
if rp_s.rx_txt() == '1':
break
pulser_fire_once(rp_s)
print("All data captured")
rp_s.tx_txt('ACQ:STOP')
trig = int(rp_s.txrx_txt('ACQ:AXI:SOUR1:Trig:Pos?'))
# It is quite difficult for the server to transfer a large amount of data at once, and there may not be
# enough memory with a very large capture buffer. Therefore, we request data from the server in parts.
received_size = 0
block_size = 50000
buff_all = []
fail_ct = 0
while received_size < samples:
if (received_size + block_size) > samples:
block_size = samples - received_size
rp_s.tx_txt('ACQ:AXI:SOUR1:DATA:Start:N? ' + str(trig)+',' + str(block_size))
buff_byte = rp_s.rx_arb()
if buff_byte:
buff = [struct.unpack('!h',bytearray(buff_byte[i:i+2]))[0] for i in range(0, len(buff_byte), 2)]
buff_all = np.append(buff_all, buff)
trig += block_size
trig = trig % samples
received_size += block_size
else:
fail_ct += 1
if fail_ct > 100:
print(f"scope_get_dma_data(): Timeout receiving data. Giving up.")
print(f"All data transferred. Fail_ct: {fail_ct}. Samples recovered: {len(buff_all)}.")
print("Buffer last 100 samples",buff_all[-100:])
print('Releasing Red Pitaya resources.')
rp_s.tx_txt('ACQ:AXI:SOUR1:ENable OFF')
time.sleep(1) # Paranoia. May/should not be necessary.
# plot.plot(buff_all)
# plot.ylabel('Voltage')
# plot.show()
# Close connection with Red Pitaya
print('Releasing Red Pitaya resources.')
rp_s.close()
print("Exiting.")
Any ideas?
-Chris