MATLAB - Karta pomiarowa i FFT

Z tego wpisu dowiecie się, jak napisać prosty program, dzięki któremu będzie możliwe przejęcie kontroli nad kartą pomiarową. Naszym celem będzie akwizycja i wizualizacja sygnału na ekranie monitora oraz obliczanie jego widma za pomocą szybkiej transformaty Fouriera FFT. MATLAB Karta pomiarowa i FFT ? Tak, zapraszam do lektury!

Z poprzednich wpisów dowiedzieliście się co to są systemy pomiarowe oraz jak przygotować MATLABa do programowania sprzętu kontrolnopomiarowego. Jeżeli jeszcze nie czytaliście postów z wakacji, to zachęcam do lektury. Tym razem zajmę się konkretnym przykładem, budowy prostego systemu pomiarowego, który będzie kontrolowany z poziomu MATLABa. Dzięki funkcjom toolboxa Data Acquisition, będzie możliwa bieżąca analiza sygnału, z wyznaczaniem FFT włącznie.

MATLAB Karta pomiarowa i FFT - konfiguracja sprzętowa

Podobnie jak w przypadku poprzedniego wpisu, do dyspozycji mamy generator RIGOL DG1022 oraz  kartę pomiarową NI USB-6002. Obydwa urządzenia łączymy ze sobą kablem BNC, zwracając uwagę, do którego wejścia karty doprowadzamy sygnał. Ta informacja będzie potrzebna na etapie programowego konfigurowania karty. W moim przypadku sygnał doprowadziłem do wejścia ai0 karty. Układ jest więc trywialny, ale chodzi o to aby nie komplikować przykładu: z generatora doprowadzamy sygnał do karty pomiarowej, za pośrednictwem której następuje jego akwizycja. MATLAB zajmie się dalszą analizą sygnału i obliczaniem FFT.

MATLAB Karta pomiarowa i FFT

W tym miejscu jest potrzebna krótka dygresja. Rozróżniamy tryby pracy karty Single-ended i Differential. W trybie Sigle-ended pomiary są dokonywane względem jednej masy, to znaczy sygnały (jeżeli jest ich więcej niż jeden) są doprowadzane do wejść sygnałowych karty i jednej wspólnej masy układu. Podobnie jak w oscyloskopie. Wadą tego trybu jest mała odporność na zakłócenia indukowane w przewodach, szczególnie złej jakości. Tryb Differential umożliwia pomiar w układzie w którym nie ma wspólnej masy, jednak liczba dostępnych wejść jest mniejsza o połowę. Zaletą trybu Differencial jest większa odporność na zakłócenia. Schemat połączeń w obydwu trybach obrazują zdjęcia i rysunki.

MATLAB Karta pomiarowa i FFT - konfiguracja programowa

Poniżej znajdziecie kolejne sekcje programu, które połączone w jedną całość dadzą w pełni funkcjonalny program. Jego pierwsza część dotyczy konfiguracji używanych urządzeń. W drugiej jest realizowana akwizycja sygnału, jego wyświetlanie i obliczanie FFT. Program działa w pętli, to znaczy po uruchomieniu w sposób ciągły wyświetlany jest przebieg sygnału oraz jego widmo.

Zacznijmy od konfiguracji generatora i karty pomiarowej. W pierwszej kolejności użytkownik powinien wprowadzić podstawowe parametry akwizycji sygnału, takie jak: częstotliwość próbkowania, czas obserwacji sygnału, nazwę wejścia analogowego do którego doprowadzony jest sygnał (w tym przypadku ai0), zakres pomiarowy i tryb pracy karty (SingleEnded). O wprowadzenie wszystkich parametrów, program poprosi użytkowania po jego uruchomieniu z poziomu command window. Dla celów dydaktycznych proponuje na początek ustawić próbkowanie na 500Hz, a czas obserwacji sygnału na 0.1s. Ten czas determinuje rozdzielczość analizy FFT oraz częstość odświeżania obrazu na ekranie monitora. Zakres pomiarowy zależy od urządzenia, dla karty NI USB-6002 można ustawić 10V. Kluczową rolę w tej części programu odgrywają dwie funkcje: daq.getDevices oraz daq.createSession. Pierwsza wyświetla listę dostępnych urządzeń do akwizycji danych, druga, tworzy obiekt do konfiguracji urządzenia konkretnego producenta.

%% Parametry próbkowania
fpr = input('Podaj częstotliwość próbkowania z zakresu 0.1 do 48000 [Hz]: ');
to = input('Podaj czas obserwacji sygnału (sugerowane 0.1) [s]: ');      % co tyle będzie odświeżany obraz (sugerowane 0.1s)
df = 1/to;
disp(['Rozdzielczość częstotliwościowa analizy FFT wynosi: ' num2str(df) ' [Hz]'] )
fprintf('\n\n');
 
analog_input_id = input('Podaj nazwę wejścia analogowego karty od ai0 do ai7 [sugerowane ai0]: ','s');
range = input('Podaj zakres pomiarowy we woltach [sugerowane 10]: ');
terminal_config = input('Podaj tryb pracy wejścia analogowego [sugerowane SigleEnded]: ','s');
fprintf('\n\n');
 
%% Inicjalizacja karty pomiarowej i ustawienie parametrów akwizycji sygnału
 
d = daq.getDevices;              % lista urządzeń DAQ i ich parametry
 
if isempty(d)
    disp('Nie wykryto karty pomiarowej. Program zostaje zatrzymany. Sprawdz podłączenie karty do komputera.')
    return
else
    disp('Wykryto kartę pomiarową o parametrach: '); pause(2)
    disp(d);
    disp('Naciśnij dowolny klawisz aby kontynuować.'); pause; 
    fprintf('\n\n');
end
 
 
s = daq.createSession('ni');     % utworzenie sesji do obsługi urządzeń DAQ.
                                 % Przez odwołania do obiektu 's' można zmieniać parametry akwizycji sygnału
if isempty(s)
    disp('Nie można utworzyć sesji akwizycji danych. Program zostaje zatrzymany. Sprawdz czy urządzenie jest obsługiwane.')
    return
else
    disp('Utworzono sesję akwizycji danych dla wykrytego urządzenia: '); pause(2)
    disp(s);
    disp('Naciśnij dowolny klawisz aby kontynuować.'); pause;
    fprintf('\n\n');
end
 
s.Rate = fpr;                   % ustawienie częstotliwości próbkowania
s.DurationInSeconds = to;       % ustawienie czasu obserwacji sygnału
 
 
ch = addAnalogInputChannel(s,d.ID,analog_input_id,'Voltage');    % otwarcie kanału akwizycji sygnału
                                % dla sesji 's' i urządzenia o identyfikatorze ID (odczytanego z pozycji ID sesji 's'),
                                % wejścia analogowego karty 'ai0' w trybie pomiaru napięcia 'Voltage'
 
ch.Range = [-range, range]; 
ch.TerminalConfig = terminal_config;
 
if isempty(ch)
    disp(['Nie można otworzyć kanału akwizycji danych dla urządzenia ' d.ID ' o wejściu ' analog_input_id '. Program zostaje zatrzymany. Sprawdz ID urządzenia oraz symbol używanego wejścia analogowego.'])
    return
else
    disp(['Otwarto kanał analogowy w trybie pomiaru napięcia na wejściu karty ' analog_input_id ': ']); pause(2)
    disp(ch);
    disp('Naciśnij dowolny klawisz aby kontynuować.'); pause;
    fprintf('\n\n');
end
 
% s.Channels.TerminalConfig = 'SingleEnded';    % opcjonalnie tryb pracy
                                                % karty single ended na
                                                % stałe

Poleceniem s = daq.createSession('ni'); tworzymy obiekt akwizycji danych dla producenta ni czyli National Instruments. Od teraz w prosty sposób można konfigurować kartę, poprzez odwołania do konkretnych parametrów poprzez indeksowanie z kropką. Na przykład  ustawienie wprowadzonej przez użytkownika częstotliwości próbkowania sprowadza się do zapisu  s.Rate = fpr. Podobnie rzecz się ma z pozostałymi parametrami.

Po uruchomieniu i wprowadzeniu niezbędnych parametrów, karta pomiarowa zostanie zainicjowana i zostanie utworzona sesja do jej obsługi. W command window będzie można zaobserwować potwierdzenie tego faktu:

Wykryto kartę pomiarową o parametrach: 
ni: National Instruments USB-6002 (Device ID: 'Dev2')
   Analog input subsystem supports:
      -10 to +10 Volts range
      Rates from 0.1 to 50000.0 scans/sec
      8 channels ('ai0' - 'ai7')
      'Voltage' measurement type
   
   Analog output subsystem supports:
      -10 to +10 Volts range
      Rates from 0.1 to 5000.0 scans/sec
      2 channels ('ao0','ao1')
      'Voltage' measurement type
   
   Digital subsystem supports:
      13 channels ('port0/line0' - 'port2/line0')
      'InputOnly','OutputOnly','Bidirectional' measurement types
   
   Counter input subsystem supports:
      1 channel ('ctr0')
      'EdgeCount' measurement type

Utworzono sesję akwizycji danych dla wykrytego urządzenia: 
Data acquisition session using National Instruments hardware:
   Will run for 0.1 second (500 scans) at 500 scans/second.
   No channels have been added.

Otwarto kanał analogowy w trybie pomiaru napięcia na wejściu karty ai0: 
Data acquisition analog input voltage channel 'ai0' on device 'Dev2':

       Coupling: DC
 TerminalConfig: SingleEnded
          Range: -10 to +10 Volts
           Name: ''
             ID: 'ai0'
         Device: [1x1 daq.ni.DeviceInfo]
MeasurementType: 'Voltage'

Środkowa część programu ma charakter czysto techniczny, obliczamy parametry próbkowania, przygotowujemy wektor czasu do wizualizacji sygnałów i wektor częstotliwości do rysowania FFT oraz inicjalizujemy rysunki. Tworzony jest również wypełniony zerami wektor do przechowywania danych, oraz wektor na wynik FFT.

%% Obliczenie parametrów próbkowania
 
N=fpr*to; dt = 1/fpr;           % liczba próbek 'N' i okres próbkowania 'dt'
t=(0:N-1)*dt;                   % wektor czasu 't'
df=1/to; f=df*(0:N-1);          % rozdzielczość częstotliwościowa 'df' analizy 
                                % widmowej i wektor częstotliwości 'f'
 
% Inicjalizacja wektorów potrzebnych do obliczeń (zerami)
data=zeros(size(t));
FFT_data = zeros(size(f));
 
%% Przygotowanie rysunków
figure; 
subplot(211);
plotHandleSub1 = plot(t,data,'-x','XDataSource','t','YDataSource','data');
title('Sygnał'); xlabel('Czas obserwacji [s]'); ylabel('Amplituda [V]'); grid on;
 
subplot(212);
plotHandleSub2 = stem(f,FFT_data,'XDataSource','f','YDataSource','FFT_data');
title('Widmo częstotliwościowe sygnału w zakresie 0 - fpr');
xlabel('Częstotliwość [Hz]'); ylabel('Amplituda [V]'); grid on; 

Ostatnia część programu to nieskończona pętla, w której następuje akwizycja sygnału, obliczanie FFT oraz odświeżanie rysunków. Do tego celu jest wykorzystana funkcja startForeground(), która wykonuje cykl akwizycji danych pomiarowych zgodnie z konfiguracją karty pomiarowej, która została wykonana na początku programu. Cechą tej funkcji jest to, że na czas akwizycji, blokowane jest wykonywanie innych funkcji MATLABa. Innymi słowy, najpierw gromadzone są dane pomiarowe, a następnie obliczane jest FFT i rysowane są rysunki. Alternatywnie do akwizycji danych pomiarowych można użyć funkcji startBackground(), która powoduje akwizycje sygnału w tle, bez blokowania command window MATLABa.  Jednak w tym prostym przykładzie zostanie użyta pierwsza funkcja.  

%% Główna pętla programu i akwizycja sygnału
while 1
    
    data = s.startForeground();         % Akwizycja sygnału
    FFT_data = 2*abs(fft(data))/N;      % szybka transformata Fouriera
            
    refreshdata(plotHandleSub1,'caller');
    drawnow
    refreshdata(plotHandleSub2,'caller');
    drawnow
        
end
 
stop(s)

Połączenie wszystkich fragmentów programu w całość, da Wam pełny program do obsługi karty pomiarowej. Oczywiście mogą być potrzebne pewne modyfikacje w zależności od tego jakim sprzętem będziecie dysponować. W efekcie na ekranie pojawi się okno z przebiegiem zarejestrowanego sygnału oraz FFT liczonym w zakresie od 0 do fpr. Dzięki temu widać, że widmo jest symetryczne względem połowy częstotliwości próbkowania. Poniżej rysunki dla dwóch różnych częstotliwości sygnału.

MATLAB Karta pomiarowa i FFT - mam nadzieję, że ten wpis był pomocny. MATLAB ma duże możliwości w zakresie programowania sprzętu i budowania systemów pomiarowych. W kolejnych wpisach pokażę Wam jak budować bardziej złożone systemy pomiarowe oraz jak przejąć kontrolę nad aparaturą pomiarową, na przykład generatorem i multimetrem.

(Visited 93 times, 1 visits today)

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *