Python采样扫频代码异常:末端频率与预期值不符
问题原因分析
你的代码中线性调频信号的相位计算逻辑错误,导致波形实际频率偏离预期,具体来说:
LoRa的chirp信号是线性调频信号,其瞬时频率随时间线性变化:f(t) = f_begin + k*t(k为调频斜率,即k = BW / Tsymbol)。这类信号的相位应该是瞬时频率对时间的积分,而不是直接用当前瞬时频率乘以累计时间t。
你当前的相位计算方式是:
sineValue = np.sin(float(2 * np.pi) * float(f) * float(t))
这里的t是累计时间,f是当前瞬时频率,这种计算相当于假设每个采样点的频率是恒定的,且从0时刻就保持当前频率,完全违背了线性调频信号的相位变化规律。随着时间推移,相位的累计误差会越来越大,导致波形的实际频率远高于预期值。
当你将Fdelta减半时,相当于人为降低了调频斜率,刚好让错误的相位计算结果巧合接近正确值,但这只是掩盖问题,并非根本解决方法。
修复方案
有两种正确的相位计算方式,任选其一即可:
方式1:相位累加(推荐,适合FPGA移植)
维护一个累计相位变量,每个采样点累加当前频率对应的相位增量(每个采样间隔内频率可近似为恒定值),同时对相位取模2π避免数值溢出:
修改chirp函数中的循环部分:
# 初始化累计相位 phase = 0.0 t = 0 tlist = [] f = f_begin + s / num_chips * num_samples * Fdelta for i in range(num_samples): sineValue = np.sin(phase) sineValuesBin.append(bin(int(sineValue * binaryRange / 2 + binaryRange / 2))[2:].zfill(10)) sineValues.append(sineValue) tlist.append(t) file.write(f"Frequency: {f}\n") # 累加相位增量:当前频率 * 采样时间 * 2π phase += 2 * np.pi * f * Tsample # 对2π取模,防止相位数值过大 phase = phase % (2 * np.pi) f += Fdelta # 当前参数下f不会超过f_end,该判断可移除 # if f > f_end: # f = f_begin t += Tsample print(f"freq: {f}; t: {t}")
方式2:用积分公式计算相位
直接利用线性调频信号的相位积分公式:phase(t) = 2π * (f_begin*t + 0.5*k*t²),其中k = BW / Tsymbol:
修改chirp函数中的循环部分:
t = 0 tlist = [] f = f_begin + s / num_chips * num_samples * Fdelta # 计算调频斜率 k = BW / Tsymbol for i in range(num_samples): # 用积分公式计算正确相位 phase = 2 * np.pi * (f_begin * t + 0.5 * k * t**2) sineValue = np.sin(phase) sineValuesBin.append(bin(int(sineValue * binaryRange / 2 + binaryRange / 2))[2:].zfill(10)) sineValues.append(sineValue) tlist.append(t) file.write(f"Frequency: {f}\n") f += Fdelta # 当前参数下f不会超过f_end,该判断可移除 # if f > f_end: # f = f_begin t += Tsample print(f"freq: {f}; t: {t}")
额外优化点
- 移除
if f > f_end: f = f_begin判断:根据你的参数计算,一个symbol的采样点刚好能让频率从f_begin扫到f_end,不需要重置频率,多余的判断反而可能引入错误。 - 相位取模:在FPGA中实现时,相位数值过大可能导致资源浪费,所以用相位累加并取模的方式更适合移植。
内容的提问来源于stack exchange,提问作者Mart
相关产品推荐
相关产品推荐

