Bakgrund
Mätning av "Noise spectral density" (samma som amplitude eller voltage) är inte helt smidigt via "Spectrum" i Digilents WaveForms. Detta då samplingsminnet är väldigt begränsat på Analog Discovery.
Däremot kan man spela in direkt till hårddisk för att sedan presentera resultatet via egna beräkningar. Vidare tycker jag även detta känns bättre då jag inte helt litar på resultat från från "RMS Average" i Digilents WaveForms.
Introduktion
Kort sammanfattat, data spelas in med Analog Discovery. Med GNU Octave används sedan Welch-metod för att presentera resultat. Jag har inte klurat på om just Welch-metod är bäst, däremot önskar jag medelvärdesbildning från flera FFT-fönster för att få ner bruset i frekvensdomänen.
Länkar
https://digilent.com/shop/analog-discovery-3/
https://digilent.com/reference/software ... ms-3/start
https://octave.org
https://octave.sourceforge.io/signal/fu ... welch.html
Digilent WaveForms Välj "Scope" under "Welcome" tabben. Klicka på "Rate, Samples..." för inställningar.
Välj önskad samplingsfrekvens (Rate) och inspelningslängd (Samples). Tänk på att Welch-metod används nedan. Därav behövs lång inspelningen, beroende på hur många FFT-fönster man väljer att medelvärdesbilda ifrån.
Klicka på "Rec" för att komma till "Record to file".
Välj typ till "Comma Seperated Values". Detta endast för att jag inte testat något annat. I framtiden finns kanske bättre alternativ. Särskilt då CSV tar lång tid att läsa in i GNU Octave. Vidare behöver format vara float. Tryck start för att påbörja inspelning av brus.
GNU Octave
Kör nedanstående skript i GNU Octave. Glöm inte ställa filnamn, samplingsfrekvens och antal medelvärdesbildningar. 10 stycken medelvärdesbildningar brukar räcka för en snygg graf.
Kod: Markera allt
% plot_noise_spectral_density.m
% 2025-12-30
pkg load signal
% Options
Filename = 'shorted_input-100kHz-2Msamples.csv';
G = 1; % [V/V], voltage gain
fs = 100e3; % [Hz], Sample rate
%% Read recorded CVS data from export function in Digilent WaveForms.
%data = dlmread(Filename,',',11,0);
%data_time = data(:,1); % [s]
%data_ch1 = data(:,2); % [V]
%data_ch2 = data(:,3); % [V]
% Read recorded CVS data from record to file function in Digilent WaveForms
data = dlmread(Filename,',',0,0);
data_ch1 = data(:,1); % [V]
data_ch2 = data(:,2); % [V]
% Compute number of samples
N = length(data_ch1);
% Remove any DC component
data_ch1 = data_ch1 - mean(data_ch1);
data_ch2 = data_ch2 - mean(data_ch2);
% White noise for reference
A_rms = 1e-6;
data_test = sqrt(fs)*A_rms/sqrt(2) * randn(N,1);
# Welch parameters
Navg = 100; % Number of averages
Nfft = floor(N/Navg); % Length of FFT.
window = hamming(Nfft);
overlap = 0.5;
% Compute power spectral density
[PSD_test, f] = pwelch(data_test, window, overlap, Nfft, fs);
[PSD_ch1, f] = pwelch(data_ch1, window, overlap, Nfft, fs);
[PSD_ch2, f] = pwelch(data_ch2, window, overlap, Nfft, fs);
% Compute amplitude spectral density
ASD_test = sqrt(PSD_test);
ASD_ch1 = sqrt(PSD_ch1);
ASD_ch2 = sqrt(PSD_ch2);
% Plot amplitude spectral density
figure(1); clf; hold on;
semilogx(f, ASD_test, "linewidth", 1.2);
semilogx(f, ASD_ch1, "linewidth", 1.2);
semilogx(f, ASD_ch2, "linewidth", 1.2);
title("Noise spectral density");
xlabel("Frequency [Hz]");
ylabel("ASD [V/√Hz]");
legend("Test noise", "Channel 1", "Channel 2");
grid on;
För att kontrollera beräkningarna gjorde jag nedanstående skript. Vitt brus för att enkelt kunna beräkna power spectral density över specificerad bandbredd.
Kod: Markera allt
% verify_pwelch.m
% 2025-12-30
pkg load signal
% Options
fs = 20e3; % [Hz], Sample rate.
bw = fs/2; % [Hz], Nyquist bandwidth.
N = 1e6; % Number of samples.
A_asd = 4; % [V_RMS/√Hz] Amplitude spectral density level.
A_psd = A_asd^2; % [V^2/Hz] Power spectral density level.
printf("Converting spectral density to RMS noise by hand: \n")
A_asd
bw
noise_power = A_psd*bw % [V^2]
noise_amplitude = sqrt(noise_power) % [V_RMS]
printf("\n")
printf("Generate white noise and compute noise amplitude with rms function: \n")
noise = sqrt(fs)*A_asd/sqrt(2) * randn(N,1);
rms_noise = rms(noise)
# Welch parameters
Navg = 100; % Number of averages
Nfft = floor(N/Navg); % Length of FFT.
window = hamming(Nfft);
overlap = 0.5;
% Compute power spectral density
[PSD_noise, f] = pwelch(noise, window, overlap, Nfft, fs);
% Compute amplitude spectral density
ASD_noise = sqrt(PSD_noise);
% Plot amplitude spectral density
semilogx(f, ASD_noise, "linewidth", 1.2);
xlabel("Frequency [Hz]");
ylabel("ASD [V/√Hz]");
grid on;
