Red Pitaya信号收发Python程序卡在client.recv无报错求助
问题解决:Red Pitaya信号采集卡在
client.recv()无输出 问题核心原因
代码卡在client.recv(1048)是因为两个关键逻辑缺失:Red Pitaya未收到数据请求命令,不会主动发送采样数据;同时缺少触发等待机制,设备未完成采集流程。此外Matplotlib的显示方式会阻塞程序循环,导致无实时图表输出。
修复步骤
1. 补全SCPI协议必要命令
Red Pitaya遵循SCPI协议,必须明确发送:
ACQ:WAIT:阻塞等待触发完成(或用ACQ:TRIG:IMM实现立即触发)ACQ:DATA?:主动请求采样数据,设备才会返回数据
2. 优化Socket通信
- 用
sendall()替代send(),确保命令完整传输到设备 - 将配置类命令(如触发参数、输出设置)移到循环外,避免重复配置浪费资源
3. 调整Matplotlib显示逻辑
启用交互式模式plt.ion(),循环内仅更新图表数据而非重新创建窗口,避免窗口阻塞程序运行。
修改后的完整代码
import socket import numpy as np import matplotlib.pyplot as plt # Red Pitaya configuration RP_IP = "169.254.79.236" RP_OUT_CHANNEL = "out1" RP_IN_CHANNEL = "in1" RP_SAMPLE_RATE = 1e6 RP_WAVEFORM_FREQUENCY = 1e3 RP_AMPLITUDE = 1 # 缩短单次采样时长,提升图表刷新流畅度 num_samples_per_iteration = int(RP_SAMPLE_RATE * 0.1) # Create socket client client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) RP_PORT = 5000 # Connect to Red Pitaya client.connect((RP_IP, RP_PORT)) # 一次性完成采集与输出配置 client.sendall(f"ACQ:RST\n".encode()) client.sendall(f"ACQ:SOUR {RP_IN_CHANNEL}\n".encode()) client.sendall(f"ACQ:TRIG:LEVEL 0.0\n".encode()) client.sendall(f"ACQ:TRIG:DLY 0\n".encode()) client.sendall(f"ACQ:AVG OFF\n".encode()) client.sendall(f"ACQ:START\n".encode()) # 配置输出信号 client.sendall(f"SOUR:{RP_OUT_CHANNEL}:FUNC SINE\n".encode()) client.sendall(f"SOUR:{RP_OUT_CHANNEL}:FREQ {RP_WAVEFORM_FREQUENCY}\n".encode()) client.sendall(f"SOUR:{RP_OUT_CHANNEL}:AMPL {RP_AMPLITUDE}\n".encode()) client.sendall(f"SOUR:{RP_OUT_CHANNEL}:OUTP ON\n".encode()) # 初始化Matplotlib交互式绘图 plt.ion() fig, ax = plt.subplots() line, = ax.plot([], []) ax.set_xlabel("Time (s)") ax.set_ylabel("Amplitude") ax.set_title("Real-time Acquired Data") # 适配Red Pitaya 16位采样范围 ax.set_ylim(-32768, 32767) try: while True: # 等待触发完成(若无需触发,替换为ACQ:TRIG:IMM) client.sendall(f"ACQ:WAIT\n".encode()) # 请求采样数据 client.sendall(f"ACQ:DATA?\n".encode()) # 接收数据 data = bytearray() received_samples = 0 while received_samples < num_samples_per_iteration: chunk = client.recv(1024) if not chunk: break data.extend(chunk) received_samples = len(data) // 2 # 每个采样为2字节int16 # 更新图表 if len(data) >= 2: acquired_data = np.frombuffer(data, dtype=np.int16)[:num_samples_per_iteration] time_axis = np.arange(0, len(acquired_data)) / RP_SAMPLE_RATE line.set_data(time_axis, acquired_data) ax.set_xlim(0, time_axis[-1]) fig.canvas.draw() fig.canvas.flush_events() finally: # 程序退出时清理资源 client.sendall(f"SOUR:{RP_OUT_CHANNEL}:OUTP OFF\n".encode()) client.close() plt.ioff() plt.close()
额外说明
- 若不需要触发功能,可将
ACQ:WAIT替换为client.sendall(f"ACQ:TRIG:IMM\n".encode())实现立即采集 - 可根据需求调整
num_samples_per_iteration的值,平衡采样时长与刷新速度 - Red Pitaya的16位采样原始值范围为
-32768到32767,若需转换为实际电压值,可乘以0.00015258789(对应1V量程)
内容的提问来源于stack exchange,提问作者shirazn
相关产品推荐
相关产品推荐

