常用规则波形的简单生成方法

  在信号处理应用中,经常需要生成各种规则的标准信号,如正弦信号、方波信号、三角波信号等,虽然现在有很多现成的库函数可供调用,但是理解这些波形的生成原理,在需要的时候简单敲一两行代码就把它实现出来,不仅省去了查照库函数和理解库函数用法的麻烦,而且没准还能在别人面前浅秀一把,也不失为是一件乐事。

1. 正弦信号

  正弦信号的表达式为
s ( t ) = A s i n ( 2 π f 0 t ) s(t) = Asin(2 \pi f_0 t) s(t)=Asin(2πf0t)

  设系统采样率为 f s f_s fs,采样点数为 N N N,则 t = [ 0 : N − 1 ] / f s t=[0:N-1]/f_s t=[0:N1]/fs t n = n / f s t_n=n/f_s tn=n/fs。将上式离散化可得到

s [ t n ] = A s i n ( 2 π f 0 t n ) → s [ n / f s ] = A s i n ( 2 π n f 0 / f s ) s[t_n]=Asin(2\pi f_0 t_n)\rightarrow s[n/f_s]=Asin(2\pi n f_0/f_s) s[tn]=Asin(2πf0tn)s[n/fs]=Asin(2πnf0/fs)

  示例代码如下:

f0 = 100
fs = 10000
N = 1000
A = 1
t = np.arange(0, N, 1) / fs
s = A * np.sin(2 * np.pi * f0 * t)

图1. 正弦波生成示意图

2. 方波信号

  方波信号的表达式为
s ( t ) = { A , n T / 2 < t < ( n + 1 ) T / 2 , n 为偶数 − A , n T / 2 < t < ( n + 1 ) T / 2 , n 为奇数 s(t)=\left\{ \begin{matrix} A, nT/2<t<(n+1)T/2,n为偶数 \\ -A, nT/2<t<(n+1)T/2,n为奇数 \end{matrix} \right. s(t)={A,nT/2<t<(n+1)T/2,n为偶数A,nT/2<t<(n+1)T/2,n为奇数

  在上面的表达式中, T T T表示方波的重复周期, f 0 = 1 / T f_0=1/T f0=1/T表示方波的重复频率。 A A A表示方波的幅度。显然,要生成方波,可以严格按照上面的表达式,对时间进行分段,分段生成波形,并将各分段波形拼接成完整波形。这种方法比较麻烦。下面提供两种比较简单的思路。

2.1 思路1

  方波信号本质上就是对信号的持续时间进行等间隔分段,交替付上定值即可。考虑到正弦信号围绕其均值上下波形恰好上下分段,与方波有相似之处,因此可以在正弦波的基础上,将正弦波大于均值的那些值全部赋值为 A A A,将正弦波小于均值的那些值全部赋值为 − A -A A,以此得到方波,示例代码如下(需要注意的是,此时方波的基频是正弦波频率的1/2):

f0 = 100
fs = 10000
N = 1000
A = 1
t = np.arange(0, N, 1) / fs
sine = A * np.sin(2 * np.pi * f0 * t)
square = A * np.ones(len(sine))
square[sine < 0] = -A

图2. 思路1生成的方波示意图
#### 2.2 思路2   如下图所示,采样时刻是呈线性增长趋势的,方波就是对时间进行切片,分片赋值即可。有一个常用的运算是能够达到分片的效果的,那就是取模(本质上就是求余)运算。我们以下图中两个点为例看看将这两个点对应的采样时刻对方波周期$T$取模得到的结果,对pt1取模后,显然结果$>T/2$,对pt2取模后,结果$

图1. 时间分割示意图

  上述思路的参考代码如下:

f0 = 100
fs = 10000
T = 1 / f0
N = 1000
A = 1
t = np.arange(0, N, 1) / fs
s = A * (2 * np.round(np.mod(t, T) / T) - 1)

图3. 思路2生成的方波示意图

3. 上锯齿信号

  上锯齿信号的表达式为
s ( t ) = A T ( t − n T ) , n = 0 , 1 , . . . , s(t)=\frac{A}{T}(t-nT),n=0,1,..., s(t)=TA(tnT),n=0,1,...,
  在上面的表达式中, A A A为信号幅度, T T T为锯齿周期。上式本质上是将第一个周期的锯齿不断以 T T T为周期进行移位和拼接,得到最终信号。显然,可以直接根据这个表达式分段生成信号后再进行拼接,但是这样的操作相对比较麻烦。在上面生成矩形波的过程中,我们说过取模运算具有切片功能,所以同样可以利用取模来实现锯齿波。具体地,将生成的时间序列 t t t对锯齿周期 T T T取模,即可得到 [ 0 , T ) [0,T) [0,T)范围内的各个时间切片,将其乘以系数 A / T A/T A/T即可得到制定幅度的上锯齿信号。示例代码如下:

图4. 上锯齿波时间切割示意图
f0 = 100
fs = 10000
T = 1 / f0
N = 1000
A = 1
t = np.arange(0, N, 1) / fs
s = A / T * np.mod(t, T)

图5. 生成的上锯齿波形示例

4. 下锯齿信号

  下锯齿信号的表达式为
s ( t ) = − A T ( t − n T ) + A , n = 0 , 1 , . . . , s(t)=-\frac{A}{T}(t-nT)+A,n=0,1,..., s(t)=TA(tnT)+A,n=0,1,...,
  下锯齿波形可以完全仿照上锯齿波形的生成方法,只需要对幅度进行微调即可,故这边不过多赘述,示例代码如下:

f0 = 100
fs = 10000
T = 1 / f0
N = 1000
A = 1
t = np.arange(0, N, 1) / fs
s = -A / T * np.mod(t, T) + A

图6. 生成的下锯齿波形示例

5. 三角波信号

  三角波形的表达式为
s ( t ) = { A 2 T ( t − n T ) , n T ≤ t < n T + T / 2 − A 2 T ( t − n T ) + A , n T + T / 2 ≤ t < ( n + 1 ) T s(t)=\left\{ \begin{matrix} \frac{A}{2T}(t-nT), nT\leq t< nT+T/2\\ -\frac{A}{2T}(t-nT)+A, nT+T/2\leq t <(n+1)T \end{matrix} \right. s(t)={2TA(tnT),nTt<nT+T/22TA(tnT)+A,nT+T/2t<(n+1)T
  显然,三角波可以看成是上锯齿信号和下锯齿信号的叠加,可以采用分段的方法生成后拼接,但是比较麻烦。这边仍然基于取模函数进行处理,不过由于三角波信号在一个周期内有两段信号,所以需要将采样序列对 T / 2 T/2 T/2取模,取模后得到 [ 0 , T / 2 ) [0,T/2) [0,T/2)范围内的信号。在取模后的各个时间段内交替填充上锯齿信号和下锯齿信号即可得到三角波信号,示例代码如下:

f0 = 100
fs = 20001
T = 1 / f0
N = 2000
A = 1
t = np.arange(0, N, 1) / fs
tmp = 2 * np.round(np.mod(t, T) / T) - 1  # 得到-1,1的序列
s = A / (T / 2) * np.mod(t, T / 2) * tmp + (1 - tmp) * A / 2

图7. 生成的三角波形示例

【备注】:上面的方法虽然原理上是没有问题的,但是上述实现示例代码其实还是有一点小小的bug的,就是round这个函数的不确定性,当它取整的数恰好位于两个数中间时,它有可能会向上取整也有可能会向下取整(取最近的偶数),这会带来一定的不确定性,后面需要将其改成floor或ceil函数,以排除这种不确定性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值