如何用Python绘制带线性变化参数的Chirp方波信号?
生成线性参数变化的扫频方波信号(Chirp Square Wave)
维基百科定义:Chirp(扫频信号)是频率随时间升高(上扫频)或降低(下扫频)的信号,部分资料中该术语与扫频信号可互换使用。
需求概述
需要生成具备以下线性变化参数的方波信号段:
- 信号总时长
- 起始/终止频率
- 起始/终止幅值
- 起始/终止占空比
示例场景:信号初始为10Hz、幅值10%、占空比20%,60秒后线性过渡为20Hz、幅值50%、占空比80%。
已知Scipy提供了支持t0/f0/t1/f1参数的正弦扫频生成函数,现需实现类似的方波版本,同时支持占空比的线性变化。目前已有基础代码片段:
from matplotlib import pyplot as plt import numpy as np import math x = np.linspace(0, 10, 1000) y = np.array([1 if math.floor(2 * t) % 2 == 0 else 0 for t in x]) plt.plot(x,y) plt.show()
实现思路与公式推导
要生成参数线性变化的方波,核心是计算每个时间点t对应的瞬时相位、瞬时幅值和瞬时占空比,再判断当前相位是否落在占空比区间内。
1. 线性变化的参数计算
对于任意时间t(范围[0, T],T为总时长),各参数的线性插值公式:
- 瞬时频率:
f(t) = f0 + (f1 - f0) * t / T - 瞬时幅值:
A(t) = A0 + (A1 - A0) * t / T - 瞬时占空比:
D(t) = D0 + (D1 - D0) * t / T(占空比取0~1之间的数值)
2. 瞬时相位计算
扫频信号的相位是频率对时间的积分,因频率随时间线性变化,积分结果为:φ(t) = 2π * ∫₀ᵗ f(τ) dτ = 2π * [f0*t + 0.5*(f1-f0)*t²/T]
对相位取小数部分(即φ(t) % (2π)后除以2π),得到当前时刻在一个周期内的位置(范围[0,1))。
3. 方波电平判断
如果当前周期位置小于等于瞬时占空比D(t),则输出幅值A(t),否则输出0(如需正负方波,可将0替换为-A(t))。
代码实现
基于上述思路,可实现向量化解法(避免循环,提升效率):
import numpy as np import matplotlib.pyplot as plt def linear_chirp_square(T, f0, f1, A0, A1, D0, D1, num_samples=10000): # 生成时间轴 t = np.linspace(0, T, num_samples) # 计算各瞬时参数 f_t = f0 + (f1 - f0) * t / T A_t = A0 + (A1 - A0) * t / T D_t = D0 + (D1 - D0) * t / T # 计算瞬时相位的小数部分(周期内位置) phase = 2 * np.pi * (f0 * t + 0.5 * (f1 - f0) * t**2 / T) cycle_pos = phase % (2 * np.pi) / (2 * np.pi) # 范围[0,1) # 生成方波信号 square_wave = np.where(cycle_pos <= D_t, A_t, 0) return t, square_wave # 示例调用:对应题目中的需求 t, wave = linear_chirp_square( T=60, f0=10, f1=20, A0=0.1, A1=0.5, # 幅值用0~1表示百分比 D0=0.2, D1=0.8, num_samples=60000 ) # 绘图展示 plt.figure(figsize=(12,6)) plt.plot(t, wave) plt.xlabel('时间 (s)') plt.ylabel('幅值') plt.title('线性参数变化的扫频方波') plt.grid(True) plt.show()
关键说明
- 向量化解法:使用NumPy向量化操作替代循环,处理大量采样点时效率更高。
- 参数适配:占空比需传入0~1的数值,幅值可根据需求调整(如需正负方波,修改
np.where的第三个参数即可)。 - 相位特性:线性扫频的相位积分是二次函数,这是区别于固定频率方波的核心——固定频率方波的相位是线性的,而扫频方波是二次的。
内容的提问来源于stack exchange,提问作者DrCoolZic
相关产品推荐
相关产品推荐

