Matlab FFT纵轴单位、缩放方法及分贝转换技术咨询
Hey Frank, let's walk through each of your questions clearly, and also fix up your MATLAB code to align with best practices for FFT scaling and visualization.
1. What's the unit of the FFT's y-axis after taking the absolute value? Is it still Volts?
Short answer: No, not directly. The raw FFT output (before scaling) is a sum of your time-domain voltage samples, so its unit is Volts multiplied by the number of samples used in the FFT (let's call this number N).
Here's why: The discrete Fourier transform (which FFT implements) sums up N time-domain samples, each in Volts. So the magnitude of the raw FFT result has units of V * N. It's only after proper scaling that you can get back to Volts (or a proportional unit that represents the amplitude of the frequency components in your original signal).
2. How to correctly scale the FFT result? Do I need to double the amplitude after hiding negative frequencies?
Yes, you need to adjust the amplitude for positive frequencies (with exceptions), and scale by the number of samples to get meaningful units. Here's the breakdown:
For real-valued signals (like your voltage measurements), the FFT result is symmetric: the negative frequency components (from
Fs/2toFs) are mirror copies of the positive frequency components (from0toFs/2). When you only plot the positive half (up toFs/2), you're effectively discarding half the energy—so you need to double the amplitude of all components except the DC component (0 Hz) and the Nyquist frequency (Fs/2 Hz) (these have no corresponding negative frequency pairs).Scaling factor: To convert the raw FFT magnitude back to Volts (matching the amplitude of your time-domain signal), you need to divide by the number of time-domain samples (
Lin your code, not the paddedN—since padding with zeros doesn't add actual signal energy).
Putting this together for your code:
- If you pad your signal to
Npoints (usingnextpow2for faster FFT), you still scale by the original signal lengthL. - After taking the absolute value of the FFT, scale it by
1/L, then double the non-DC/non-Nyquist components in the positive frequency half.
3. Should I calculate 20*log10(FFT) for all values to convert to decibels?
Almost—but with two important caveats:
First, you should only apply this to the already scaled FFT magnitude (the one that's in Volts, after step 2 above). Using
20*log10(scaled_fft_magnitude)will give you units of dBV (decibels relative to 1 Volt), which is standard for voltage amplitude in frequency domain.Second, never take the log of zero! Add a tiny epsilon value (like
1e-12) to your FFT magnitude to avoid mathematical errors:20*log10(scaled_fft_magnitude + 1e-12).Note: If you were working with power instead of voltage, you'd use
10*log10(...), but since you're measuring voltage amplitude,20*log10(...)is correct.
Revised MATLAB Code (With Proper Scaling)
Here's how to adjust your code to implement all the above steps:
load('TimeDomain.mat') % Load time-domain voltage signal (assuming variable name is Timedomain) L = length(Timedomain); % Use actual signal length instead of hardcoded value Fs = 500000; % Sampling frequency (Hz) % Pad to next power of two for faster FFT (optional but common optimization) N = 2^nextpow2(L); t = (0:L-1)/Fs; % Correct time array: sample index divided by sampling frequency (units: seconds) % Compute FFT and apply proper scaling fft_result = fft(Timedomain, N); fft_magnitude = abs(fft_result); scaled_magnitude = fft_magnitude / L; % Scale to convert back to Volts % Prepare positive frequency components and adjust amplitude f = linspace(0, Fs/2, N/2 + 1); % Correct frequency array (includes 0 Hz and Fs/2 Hz) scaled_positive = scaled_magnitude(1:N/2 + 1); % Double amplitude for all components except DC and Nyquist scaled_positive(2:end-1) = scaled_positive(2:end-1) * 2; % Plot linear amplitude (Volts) figure(1) plot(f, scaled_positive) xlabel('Frequency (Hz)') ylabel('Amplitude (V)') title('FFT of Voltage Signal (Linear Scale)') % Plot amplitude in decibels (dBV) figure(2) plot(f, 20*log10(scaled_positive + 1e-12)) xlabel('Frequency (Hz)') ylabel('Amplitude (dBV)') title('FFT of Voltage Signal (Log Scale)')
Key fixes in this code:
- Uses the actual signal length instead of hardcoding
L=2500for flexibility. - Corrects the time array calculation to match your sampling frequency.
- Properly scales the FFT magnitude to return to Volts.
- Doubles the relevant positive frequency components to account for discarded negative frequencies.
- Creates a frequency array that perfectly matches the number of positive frequency points.
- Adds a log-scale plot with a small epsilon to avoid errors from taking the logarithm of zero.
内容的提问来源于stack exchange,提问作者Frank

