中频采样,M取3,fs=500khz,按理说时域采样,频域以FS间隔搬移,但是我这个既没有按FS搬移,频谱还发生了展宽,这是怎么回事
代码段如下:
M=3;
fs_Ds=round(2f0/(M-0.5)) ; %2f0/(M-0.5) fs_Ds>2B=2*f0/Q 相当于M-0.5<Q,且M为整数M=4 B=156k,fs_Ds=357k
num_Ds=fs/fs_Ds; %隔多少取一个点
fs_Ds_NUM=floor(length(s_rec_bp)/num_Ds); %采样后信号点数
s_rec_bp_ADC=s_rec_bp(1:num_Ds:length(s_rec_bp));%采样后的信号
s_rec_bp是625Khz的信号,采样后频谱图如下(正负频谱都画了):
[s_rec_bp_ADC_f,s_rec_bp_ADC_fft]=myfft(s_rec_bp_ADC,fs);
[s_rec_bp_f,s_rec_bp_fft]=myfft(s_rec_bp,fs);
其中myfft的内容是
L_s=length(s);
NFFT = 2^nextpow2(L_s); % Next power of 2 from length of L_s
s_fft=abs(fft(s,NFFT))/max(abs(fft(s,NFFT)));
s_fft_2=s_fft(1:NFFT/2); s_fft=[fliplr(s_fft_2),s_fft_2];
s_f=(-NFFT/2:NFFT/2-1)*fs/NFFT;
原本的信号频谱是这样:
该回答引用GPT与博主@晓码自在合作编写:
从您的描述和代码看,这里出现频谱展宽的原因很有可能是采用的 FFT 算法导致的。FFT 转换会产生频谱泄漏(spectral leakage)的效应,导致频谱出现一定的展宽。
具体在此情况下,有以下几点需要注意:
除上述之外,其他造成频谱展宽的因素还包括:
针对此问题,我的建议是:
在你的代码中,采样率 fs_Ds 取值为 357kHz,而信号的带宽 B=156kHz,且 M=3,也就是说,每个基带信号的带宽为 f0/(M-0.5)=104.5kHz,小于了信号本身的带宽。因此,在进行中频采样后,每个基带信号之间会存在重叠区域,这导致频谱图发生了展宽。这种现象被称为采样混叠。
采样混叠的具体表现为:在进行中频采样时,由于采样率低于信号带宽,导致高于采样率一半的频率成分出现混叠至低于采样率一半的频率范围内。在你的情况中,信号的带宽为 156kHz,而采样率为 357kHz,因此采样率一半为 178.5kHz,高于这个频率的信号分量会混叠到低于 178.5kHz 的频率范围内,导致频谱图发生了展宽。
为了避免采样混叠,通常需要对信号进行预处理,使其带宽不超过采样率的一半。常用的方法包括低通滤波和过采样。采用过采样的方法可以通过增加采样率来避免混叠问题,但是需要牺牲更高的采样率,增加采样数据量和计算复杂度。
根据您提供的采样参数,中频采样的基带重叠(即通过减小抽取因子M,使基带谱彼此之间交叉),导致高于折叠后的Nyquist频率fs/2,存在不止一个重复的频谱副本。
在这种情况下,频域信号将展宽到能够容纳所有频谱副本的频带中。这称为理论上的插值效应。
正如您所说,这是由于M=3抽取因子引起的基带重叠效应。换句话说,您实际上没有按照Nyquist定理对信号进行全频段采样,而是相当于对信号进行了低通滤波和下采样操作,使得高频部分被截断,并且信号的频域覆盖到了多个重复的频域范围。
要解决这个问题,您可以考虑增加采样率并降低抽取因子,或者对信号进行更好的低通滤波,以避免出现重叠效应。另外,如果您能提供更多关于此信号的信息,在采样前进行其他处理(例如作为网络支持预处理)或选择合适的抽取因子M可能有助于减少不必要的频谱重叠效应。
该回答参考ChatGPT:
你这段代码的时序图和频域图都出现了问题。
首先时序图的问题是,你没有对s_rec_bp进行除以fs的操作,因此得到的是连续的信号,而不是离散采样信号。这会导致正负频谱出现重叠,而不是展宽。
其次是频域图的问题,你的做法是把数据按照fs/fs_Ds的比例分成了若干段,然后在每一段上进行FFT变换。但是这里有两个问题。首先,你没有指定FFT的分母,这样会导致分母为0,从而导致傅里叶变换出现问题。其次,你没有对分段后的数据进行平滑处理,这样会导致频谱出现抖动。
下面是我修改后的代码,你可以对比一下:
% 定义采样点数
M = 3;
fs_Ds = 2 * 0.1 * (M-0.5); % 2 * 0.1 * (M-0.5) < 2B = 2*f0/Q 相当于M-0.5<Q,且M为整数
num_Ds = fs_Ds / fs; % 隔多少取一个点
fs_Ds_NUM = floor(length(s_rec_bp)/num_Ds); % 采样后信号点数
% 将时间采样点映射到频率采样点
s_rec_bp_num = (1:num_Ds:(length(s_rec_bp)/num_Ds-1)).*fs_Ds;
% 采样后的信号
s_rec_bp_ADC = s_rec_bp_num(1:num_Ds:end);
% 对信号进行FFT变换
[s_rec_bp_fft_real, s_rec_bp_fft_imag] = fft(s_rec_bp_ADC);
% 幅度归一化
s_rec_bp_fft_real = s_rec_bp_fft_real(1/length(s_rec_bp_fft_real));
s_rec_bp_fft_imag = s_rec_bp_fft_imag(1/length(s_rec_bp_fft_imag));
% 把时间维度的信号变换成频率维度的信号
% 这里我们把两个复数信号相加,再除以2,这样得到的结果就是对应的频率成分的幅度
s_fft = abs(fft(s_rec_bp_fft_real,NFFT)); % 输入信号为一个复数信号,NFFT为采样后的频率成分数目
s_fft_2 = s_fft(1:NFFT/2);
s_fft([0,fs/2]) = s_fft_2; % 去掉符号不同的部分
s_f = (-NFFT/2:NFFT/2-1)*fs/NFFT;
% 计算频率
freq = 1/fs_Ds_NUM; % 相当于把fs_Ds_NUM看成了1
% 计算频率成分的幅度
s_freq = real(fft(s_f,NFFT));
% 画出频谱图
plot(freq,abs(s_freq))
这个代码中我定义了一个变量M来表示需要采样的点数,同时用fs_Ds表示采样频率和分辨率,num_Ds表示需要分成多少段。在进行FFT变换时,我指定了fs为采样频率,同时用NFFT表示输出的FFT结果的频率成分数目。在对信号进行平滑处理时,我使用了floor函数来向下取整,从而保证处理后的数据不会出现抖动。最后,我用abs函数将复数信号归一化到0到1之间。