You are on page 1of 164

1

ROMAN SALAMON

MATLAB
PODSTAWY I ZASTOSOWANIA

SKRYPT DLA STUDENTÓW I ROKU KIERUNKU „ELEKTRONIKA


I TELEKOMUNIKACJA” POLITECHNIKI GDAŃSKIEJ
DO PRZEDMIOTU
„TECHNIKA OBLICZENIOWA I SYMULACYJNA”

POLITECHNIKA GDAŃSKA
WYDZIAŁ ELEKTRONIKI, TELEKOMUNIKACJI
I INFORMATYKI
KATEDRA ELEKTRONIKI MORSKIEJ
GDAŃSK 2008
2

 Copyright Roman Salamon 2008


Katedra Systemów Elektroniki Morskiej Politechniki Gdańskiej

Skrypt objęty jest prawem autorskim. Prawa autorskiego nie narusza korzystanie z jego wersji
elektronicznej oraz jednokrotny wydruk części lub całości skryptu do użytku prywatnego
przez studentów Wydziału Elektroniki, Telekomunikacji i Informatyki Politechniki Gdań-
skiej. Pozostałe formy wykorzystania skryptu wymagają pisemnej zgody autora.

Autor będzie zobowiązany za przekazanie uwag dotyczących treści skryptu i dostrzeżonych


błędów na adres: roman.salamon@eti.pg.gda.pl
3

SPIS TREŚCI

1. WPROWADZENIE .......................................................................................................................... 5

CZĘŚĆ I. PODSTAWY UŻYTKOWANIA PROGRAMU MATLAB .......... 6


2. INFORMACJE WSTĘPNE ............................................................................................................. 7
2.1. PRZYGOTOWANIE PROGRAMU MATLAB ® DO PRACY ............................................ 7
2.2. CZĘSTO STOSOWANE POLECENIA .......................................................................... 10
3. PODSTAWOWY OBLICZEŃ NUMERYCZNYCH W PROGRAMIE MATLAB® ............... 12
3.1. WARTOŚCI LICZBOWE ........................................................................................... 12
3.1. Liczby rzeczywiste ............................................................................................ 12
3.1.2. Liczby zespolone ........................................................................................... 13
3.1.3. Zaokrąglenia liczb ........................................................................................ 14
3.2. MACIERZE I WEKTORY .......................................................................................... 15
3.2.1. Definiowanie macierzy i wektorów ............................................................... 15
3.2.2. Podstawowe operacje macierzowe ............................................................... 20
3.2.3. Macierze kwadratowe ................................................................................... 22
3.3. TABLICE ................................................................................................................ 24
3.3.1. Tablice numeryczne ...................................................................................... 24
3.3.2. Łańcuchy ....................................................................................................... 25
3.4. FUNKCJE ............................................................................................................... 26
3.4.1. Funkcje standardowe .................................................................................... 26
3.4.2. Funkcje macierzowe ..................................................................................... 28
3.4.3 Relacje i operacje logiczne ............................................................................ 31
3.4.4. Instrukcje warunkowe ................................................................................... 32
3.4.5. Definiowanie funkcji ..................................................................................... 34
3.5.5. Pętle .............................................................................................................. 37
4. GRAFIKA ........................................................................................................................................ 44
4.1. GRAFIKA DWUWYMIAROWA.................................................................................. 44
4.1.1. Podstawowe funkcje graficzne ...................................................................... 44
4.1.2. Funkcje formatujące rysunek ........................................................................ 47
4.1.3. Tworzenie wielu rysunków ............................................................................ 48
4.1.4. Dobór parametrów rysunku bez użycia instrukcji graficznych .................... 51
4.2. GRAFIKA TRÓJWYMIAROWA.................................................................................. 54
4.2.1. Linie w przestrzeni trójwymiarowej .............................................................. 54
4.2.2. Tworzenie obrazów funkcji dwóch zmiennych .............................................. 55
4.2.3. Dobór kolorów .............................................................................................. 57
4.2.4. Ustawianie położenia układu współrzędnych ............................................... 60
4.2.5. Efekty oświetlania rysunków trójwymiarowych ............................................ 61
4.2.6. Inne metody formatowania rysunku .............................................................. 62
4.2.7. Obrazy figur trójwymiarowych ..................................................................... 64
4.3. GRAFICZNY INTERFEJS UŻYTKOWNIKA ................................................................. 65
4.3.1. Ogólna charakterystyka ................................................................................ 65
4.3.2. Projektowanie planszy GUI .......................................................................... 66
4.3.3. Podstawy programowania graficznego interfejsu użytkownika GUI ........... 69
4.3.4. Użycie przełącznika Toggle Button i okna edycyjnego Edit Text. ................ 72
4.3.5. Użycie przełącznika Radio Button i okna edycyjnego Edit Text. .................. 75
4.4.6. Użycie Popup Menu ...................................................................................... 77
4

4.3.6. Użycie Listbox i Axes .................................................................................... 78


4.3.7. Zastosowanie suwaka Slider ......................................................................... 80
5. IMPORT I EKSPORT DANYCH ................................................................................................. 83
5.1. WPROWADZENIE ................................................................................................... 83
5.2. EKSPORT I IMPORT DANYCH W FORMACIE BINARNYM ........................................... 83
5.3. ZAPISYWANIE I CZYTANIE DANYCH W FORMACIE TEKSTOWYM ............................. 84
5.4. EKSPORT I IMPORT PLIKÓW DŹWIĘKOWYCH .......................................................... 85
CZĘŚĆ II. ZASTOSOWANIA PROGRAMU MATLAB .................................. 86
6. METODY NUMERYCZNE W ZASTOSOWANIU DO FUNKCJI CIĄGŁYCH ................... 87
6.1. WIELOMIANY ........................................................................................................ 87
6.2. FUNKCJE WYMIERNE ZMIENNEJ ZESPOLONEJ ......................................................... 88
6.3. MIEJSCA ZEROWE, MINIMA I MAKSIMA FUNKCJI .................................................... 91
6.4. CAŁKOWANIE NUMERYCZNE ................................................................................. 94
6.5. RÓWNANIA RÓŻNICZKOWE.................................................................................... 96
7. GENERACJA, ANALIZA I PRZETWARZANIE SYGNAŁÓW ............................................ 104
7.1. SYGNAŁY ANALOGOWE I DYSKRETNE ................................................................. 104
7.2. GENERACJA SYGNAŁÓW IMPULSOWYCH ............................................................. 105
7.3. DYSKRETNA REPREZENTACJA SYGNAŁÓW CIĄGŁYCH ......................................... 110
7.3.1. Sygnały deterministyczne ............................................................................ 110
7.3.2. Sygnały losowe ............................................................................................ 113
7.4. DYSKRETNA TRANSFORMACJA FOURIERA ........................................................... 117
7.4.1. Definicja i podstawowe własności .............................................................. 117
8.4.2. Widmo dyskretne a widmo ciągłe ............................................................... 119
7.4.3. Widma sygnałów o nieograniczonym czasie trwania ................................. 123
7.5. FILTRACJA SYGNAŁÓW DYSKRETNYCH ............................................................... 127
7.5.1. Filtracja w dziedzinie częstotliwości .......................................................... 127
7.5.2. Filtracja w dziedzinie czasu ........................................................................ 129
7.6. SPLOT.................................................................................................................. 135
8. ANALIZA NUMERYCZNA OBWODÓW I UKŁADÓW ELEKTRYCZNYCH .................. 137
8.1. OBWODY PRĄDU STAŁEGO .................................................................................. 137
8.2. ANALIZA OBWODÓW RLC PRZY POBUDZENIU SINUSOIDALNYM ......................... 141
8.2.1. Obwód RL ................................................................................................... 141
8.2.2. Szeregowy obwód rezonansowy .................................................................. 143
8.2.3. Sprzężone równoległe obwody rezonansowe .............................................. 144
8.3. ANALIZA OBWODÓW RLC PRZY DOWOLNYM POBUDZENIU................................. 148
8.3.1. Analiza numeryczna w dziedzinie częstotliwości ........................................ 148
8.3.2. Analiza numeryczna w dziedzinie czasu ..................................................... 150
8.4. PROJEKTOWANIE FILTRÓW ANALOGOWYCH ........................................................ 152
8.4.1. Podstawy teoretyczne .................................................................................. 152
8.4.2. Wybór rozwiązania konstrukcyjnego .......................................................... 155
8.4.3. Wyznaczanie wartości elementów obwodów .............................................. 157
INDEKS INSTRUKCJI I FUNKCJI ............................................................................................... 163
5

1. WPROWADZENIE
Program MATLAB, zwany również często „środowiskiem MATLAB”, przezna-
czony jest do obliczeń inżynierskich i naukowych oraz do wizualizacji ich wyników. W śro-
dowisku MATLAB obowiązuje język, w którym komunikujemy się z programem polecając
mu wykonywanie określonych zadań. Jest to język wysokiego poziomu, co w praktyce ozna-
cza, że w formie prostej instrukcji można wyrazić polecenie wykonania bardzo złożonego
zadania. Cechą charakterystyczną języka MATLAB jest to, że podstawową formą danych
jest w nim macierz rzeczywista bądź zespolona. Dane i wyniki obliczeń są przechowywane w
przestrzeni roboczej i istnieją w niej dopóki nie zostaną usunięte przez użytkownika, bądź
przez zamknięcie programu. Zmienne nie są deklarowane.
Środowisko MATLAB jest otwarte w tym sensie, że użytkownik ma dostęp do jego
funkcji, poleceń i bibliotek oraz może tworzyć własne pliki i funkcje. Program daje także
możliwość współpracy z innymi programami, np. Excel, C, Fortran.
Program MATLAB może być instalowany na praktycznie dowolnym komputerze.
Zmiana platformy sprzętowej nie wiąże się z utratą własnego oprogramowania.
Oprócz podstawowego programu MATLAB istnieją tzw. Toolboxy, które są zawierają
specjalistyczne oprogramowanie z kilkunastu dziedzin nauki i techniki. Podstawowy pakiet
MATLAB można także uzupełnić interaktywnym programem SIMULINK, który służy do
modelowania i symulacji systemów dynamicznych, a w tym systemów elektronicznych, tele-
komunikacyjnych i systemów automatyki.
Niniejszy skrypt został pomyślany jako pomoc dydaktyczna do przedmiotu „Technika
Obliczeniowa i Symulacyjna”, prowadzonego na Wydziale Elektroniki, Telekomunikacji i
Informatyki Politechniki Gdańskiej dla studentów drugiego semestru kierunku Elektronika i
Telekomunikacja. Składa się on z dwóch części; w pierwszej omówione są podstawy użytko-
wania programu MATLAB, zaś w drugiej – praktyczne przykłady zastosowania programu w
elektronice i telekomunikacji. Pisząc ten skrypt autor zakładał, że Czytelnik po raz pierwszy
spotyka się z programem MATLAB oraz że Jego wiedza i umiejętności odpowiadają pro-
gramowi pierwszego semestru studiów. Jedynie w drugiej części skryptu występują przykłady
dotyczące treści przekazywanych na drugim lub wyższych latach studiów.
Materiał zawarty w skrypcie wystarcza do wykonania projektu i ćwiczeń laboratoryj-
nych z przedmiotu „Technika Obliczeniowa i Symulacyjna” w zakresie związanym z użytko-
waniem programu MATLAB.
Dążąc do zmniejszenia objętości skryptu ograniczono przede wszystkim liczbę omó-
wionych funkcji i instrukcji, rezygnując z rzadziej używanych i bardziej skomplikowanych.
Dużą część praktycznych zadań można wykonać bez używania tych pominiętych funkcji i
instrukcji, aczkolwiek ich stosowanie ułatwia niewątpliwie programowanie. Ponadto opis
omawianych instrukcji i funkcji często nie jest kompletny. Pominięto z zasady te możliwości
zawarte w instrukcjach i funkcjach, które znajdują względnie rzadko praktyczne zastosowa-
nie. Funkcjonowanie prawie każdej instrukcji zilustrowano przykładem, co powinno ułatwić
jej pełne zrozumienie, zapamiętanie i dalsze stosowanie we własnych programach.
Autor wyraża nadzieję, że skrypt ułatwi opanowanie przedmiotu i zachęci do głębszego
poznania programu MATLAB, a w przyszłości do jego stosowania w czasie studiów i pracy
zawodowej.
6

CZĘŚĆ I. PODSTAWY UŻYTKOWANIA PROGRAMU MATLAB


7

2. INFORMACJE WSTĘPNE
2.1. Przygotowanie programu MATLAB ® do pracy
Na pulpicie monitora znajduje się ikona programu MATLAB®, której przyciśnięcie le-
wym klawiszem myszy powoduje uruchomienie programu. Pojawia się najpierw na krótką
chwilę logo programu MATLAB®, a następnie okno programu. Okno to może zawierać różne
wewnętrzne okna, w zależności od wcześniejszego ustawienia przez poprzedniego użytkow-
nika. W naszej pracy z programem MATLAB® używać będziemy dwóch okien, a mianowicie
okna podstawowego okna Command Window oraz okna Workspace.
W celu uaktywnienia tych okien wybieramy na górnym pasku View i na rozwiniętej li-
ście zaznaczamy wyżej wymienione nazwy okien. Pożądany widok oka programu MATLAB ®
zawiera po lewej stronie okna Workspace, a po prawej stronie okno Command Window. Prze-
ciągając myszą prawe obramowanie pionowe lewego okna można mu nadać pożądaną szero-
kość – około 1/3 szerokości prawego okna. Okno Command Window wykorzystujemy do
wprowadzania wszystkich instrukcji, komend, danych itp. W oknie Workspace pojawiają się
natomiast sukcesywnie informacje o wszystkich stałych i zmiennych używanych w pisanym
przez nas programie. W kolumnie Name widoczne są użyte symbole stałych i zmiennych, a
obok ich wymiar. Obserwując to okno unikamy niezamierzonego używania tych samych sym-
boli w odniesieniu do innych zmiennych. Użyteczna jest również informacja o wymiarach
zmiennych, która pozwala unikać błędów związanych z niezachowaniem reguł matematycz-
nych obowiązujących w programie MATLAB®. Widok obu okien pokazano na rys. 2.1.

Rys. 2.1. Widok okien programu MATLAB przygotowanego do pracy.


8

Program MATLAB® umożliwia dobranie kroju i wysokości czcionek do upodobań


użytkownika. W razie takiej potrzeby wybieramy w pasku okna MATLAB® etykietę File, a po
rozwinięciu menu etykietę Preferences…. W widocznym menu wybieramy najpierw General.
Pokazuje się wtedy oddzielne okno, w którym można wybrać krój czcionki i jej wysokość, a
także kolory czcionek, którymi będą pisane charakterystyczne elementy programu. Należy
wybierać takie style czcionek, które zawierają polskie litery, co jest ważne w zapisie komen-
tarzy (np. Ariel lub SansSerif1). W oknach Command Window i Editor/Debugger najlepiej ustawić
Use desktop font. Pozostałe ustawienia mają mniejsze znaczenie i nie należy ich zmieniać bez
wyraźnej potrzeby.
Wykorzystując okno Command Window można wykonywać proste obliczenia i wprowa-
dzań komendy. Okno to jest jednak mało użyteczne do pisania większych programów. Do
tego celu służą specjalne skrypty. Otwieranie takiego skryptu odbywa się przez przyciśnięcie
ikony z białą, pustą kartką, umieszczone w lewym skraju paska w oknie programu MAT-
LAB®. Widok okna przedstawia rys.2.2.

Rys. 2.2. Okno do pisania programu


Po przyciśnięciu tej ikony pojawia się nowe okno o nazwie Untitled. W oknie tym bę-
dziemy wpisywać nasz program. Program ten po nadaniu mu nazwy będzie przechowywany
w katalogu Work. W celach porządkowych, każdy użytkownik powinien utworzyć własny fol-

1
Popularny styl Times New Roman ma trudną do odróżnienia literę l i cyfrę 1, co może być przyczyną
błędów w programie.
9

der w katalogu Work i w tym folderze umieszczać swoje skryptu. W tym celu należy wykonać
kolejno następujące czynności:
 w pasku okna Untitled wybrać File
 z menu File wybrać Save As…
 pojawia się okno, w którym na górnym pasku wybieramy ikonę Utwórz nowy folder
 w oknie pojawia się ramka, w której wpisujemy nazwę użytkownika i wciskamy En-
ter
 przyciskamy ikonę nowego folderu i wpisujemy w dolnej ramce nazwę naszego pro-
gramu, która nie zawiera polskich liter
 w oknie nazwanym dotąd Untitled pojawia się tytuł C:\MATLAB\work\nazwa użyt-
kownika\nazwa skryptu.m
Sprawdzamy, czy ścieżka dostępu do naszego skryptu jest prawidłowa i dokonujemy
ewentualnych poprawek opisaną wyżej metodą. Nazwa skryptu ma nadane automatycznie
rozszerzenie .m. Nazwy skryptów z takim rozszerzeniem są traktowane w programie MA-
TLAB® jako zbiory instrukcji przeznaczonych do wykonania.
W otwartym oknie o podanej wyżej nazwie tworzymy nasz program. Pracę rozpoczy-
namy od wpisania nagłówka, którym powinna być (dla porządku) nazwa naszego skryptu.
Wpisujemy ją następująco: ‘nazwa’ (bez kropki). Każdy tekst zwarty między apostrofami ‘’
napisany jest kolorem czerwonym i jest widoczny po uruchomieniu naszego programu w
oknie Command Window. Następnie wpisujemy kolejne instrukcje według zasad podanych w
dalszej części skryptu. Po zakończeniu każdego etapu pracy można postępować w dwojaki
sposób. Jeżeli chcemy zapisać skrypt bez sprawdzania jego poprawności wówczas, po ciśnię-
ciu File, wybieramy w menu polecenie Save lub wciskamy ikonę Save. Jeżeli chcemy jedno-
cześnie sprawdzić działanie naszego programu, wówczas wciskamy na pasku etykietę Debug i
w widocznym menu wybieramy komendę Save and Run. Analogiczny efekt daje wciśnięcie
klawisza F5. Nasz program zostanie zapisany i jednocześnie uruchomiony. Skutki urucho-
mienia programu i jego działanie omówimy w dalszej części skryptu.
Po zapisaniu programu można zakończyć jego użytkowanie przez zamknięcie jego okna
lub kontynuować pracę nad programem. Usilnie zaleca się okresowe zapisywanie programu,
w celu uniknięcia jego utraty w wyniku niewłaściwych działań lub zawieszenia się wykony-
wania programu MATLAB® .
Zapisany i zamknięty skrypt można otworzyć w celu dalszej pracy nad nim lub w celu
uruchomianie zawartego w nim programu. Należy w tym celu na pasku okna programu MA-
TLAB® przycisnąć ikonę Open File i z wybrać z katalogu Work folder z nazwą użytkownika, a
w nim nazwę skryptu. Inny sposób otwarcia skryptu polega na wpisaniu w oknie Command
2
Window polecenia :
>> open <nazwa skryptu>
Jeżeli, przykładowo, nasz skrypt ma nazwę wykres, to odpowiednia komanda ma nastę-
pujący zapis:
>> open wykres
Polecenie jest wykonywane tylko wtedy, gdy w Current Directory wpisana jest właściwa
ścieżka dostępu do naszego skryptu. Zwykle wpisany jest jedynie katalog Work i wtedy należy

2
Symbole < > oznaczają tu i w dalszym tekście miejsce, w którym programista wpisuje ciągi znaków,
których znaczenie wpisano między symbolami.
10

uzupełnić ścieżkę wciskając sąsiednią ikonę Browse for Folder i wybierając z niej nazwę fol-
deru użytkownika.
Po wykonaniu czynności opisanych w powyższej instrukcji można przystąpić do pisania
programu. Aby jednak nasz program funkcjonował zgodnie z naszymi intencjami, konieczne
jest poznanie podstawowych zasad obowiązujących w programie MATLAB® . Przedstawimy
je w następnym rozdziale.

2.2. Często stosowane polecenia


Obsługa programu MATLAB® wymaga znajomości pewnych podstawowych poleceń.
Podamy i omówimy niżej najważniejsze z nich. Część poleceń będzie szerzej opisana w dal-
szej części skryptu. Tutaj sygnalizujemy ich istnienie i znaczenie w celu uniknięcia możli-
wych pomyłek np. w związku z poleceniami występującymi w poprzednim podrozdziale
Polecenia dotyczące plików i rysunków
open <nazwa pliku>
Poleceni otwiera plik lub rysunek o wpisanej nazwie, jeżeli właściwa ścieżka dostępu
podana jest w okienku CurrentDirectory. Jeżeli ścieżka dostępu do poszukiwanego pliku jest
niewłaściwa, to można ją zamienić w okienku Current Directory lub podać w poleceniu open:
open <work\student\wykres.m>
Jeżeli plik o nazwie wykres.m znajduje się w podkatalogu student, to zostanie otwarty.
Dotyczy to również rysunków o nazwach z rozszerzeniem .fig.
W analogiczny sposób można otwierać pliki o innych rozszerzeniach. W zależności od
rodzaju rozszerzenia otwierane są zmienne, rysunki itp. i umieszczane w odpowiednich
oknach.
save <nazwa pliku>
Polecenie zapisuje na dysku wszystkie zmienne występujące w przestrzeni roboczej
(widoczne w oknie Workspace) na dysku w pliku o podanej nazwie i rozszerzeniu .mat (szcze-
góły w rozdziale Eksport i import danych).
saveas(h,’nazwa’)
To polecenie zapisuje rysunek o uchwycie h w pliku o podanej nazwie. Polecenie uży-
wane jest programach dotyczących grafiki.
dir <nazwa katalogu>
W oknie Command Window pojawia się lista plików znajdujących się w podanym kata-
logu lub nazwy podkatalogów. Jeżeli potrzebny plik znajduje się w pewnym podkatalogu to
należy podać ścieżkę dostępu, np.
dir <work\student>
Do znalezienie ścieżki dostępu do poszukiwanej funkcji lub pliku z rozszerzeniem .m
służy polecenie
which <nazwa funkcji>
lub
which <nazwa pliku.m>
11

Program zwraca ścieżkę dostępu do danej funkcji, którą można wykorzystać do jej
otwarcia. Niestety, w wypadku plików umieszczonych w podkatalogach katalogu Work, trzeba
podać ścieżkę dostępu w Current Directory.
what
Powyższe polecenie powoduje pojawienie się wszystkich plików znajdujących się w
bieżącym katalogu, do którego ścieżka podana jest w Current Directory.
Niepotrzebne pliki i obiekty graficzne usuwamy poleceniem
delete <nazwa pliku>
Usunąć można pliki, do których dostęp podany jest w Current Directory.
close
Powyższe polecenie zamyka okno otwartego rysunku. Jeżeli chcemy zamknąć wszyst-
kie rysunku, to dajemy polecenie
close all
Polecenia dotyczące przestrzeni roboczej
clear
Polecenie to usuwa z przestrzeni roboczej wszystkie zmienne. Polecenie uzupełnione o:
clear x,y,z,... – usuwa wymienione zmienne
clear global – usuwa zmienne globalne
clear functions – usuwa funkcje
clear all – usuwa zmienne lokalne, globalne i funkcje.
Listę bieżących zmiennych występujący w przestrzeni roboczej otrzymujemy pisząc
who
Pełną informację o tych zmiennych daje polecenie
whos
Przypominamy, że lista zmiennych znajduje się również w oknie Workspace.
12

3. PODSTAWOWY OBLICZEŃ NUMERYCZNYCH W PROGRAMIE MATLAB®


3.1. Wartości liczbowe
3.1. Liczby rzeczywiste
Program MATLAB® wykonuje obliczenia na liczbach 64-bitowych, skąd wynika, że
minimalna liczba dodatnia ma wartość 1.7∙10-307, zaś maksymalna liczba ma wartość
1.7∙10307. Przekroczenie w trakcie obliczeń maksymalnej wartości jest sygnalizowane jako Inf.
Chociaż obliczenia wykonywane są z bardzo dużą dokładnością, to ich wyniki liczbowe
pokazywane są w oknie Command Window za pomocą mniejszej liczby cyfr. I tak w podsta-
wowym formacie short (domyślnym) liczby są zapisywane często przy użyciu pięciu cyfr i
wykładnika potęgi 10. Oto charakterystyczne przykłady reprezentacji liczb w oknie Command
Window.
>> a=123
a=
123
>> a=123456
a=
123456
>> a=1234.5678
a=
1.2346e+003
Format ostatnio zapisanej liczba zawiera zaokrąglenie do pięciu cyfr znaczących wpisa-
nej liczby oraz wykładnik potęgi 10. Liczba w tym zapisie jest równoważna:
+3
a=1.2346 ∙10
Należy podkreślić, że zaokrąglenie użyte jest wyłącznie przy prezentacji liczby w oknie
Command Window, natomiast obliczenia, w których występuje ta liczba, są wykonywane z
pełną dokładnością.
Jeżeli krótki format liczby nie jest wystarczająco dokładny (co zdarza się bardzo rzad–
ko), to można zmienić go na długi:
>> format long
>> a=1234.5678
a=
1.234567800000000e+003
Podane wyżej instrukcje nadały zmiennej a określone wartości liczbowe. Wartości te są
przechowywane w pamięci do czasu zamknięcia okna Command Window, lub usunięcia z pa-
mięci wszystkich danych. Usuwamy je z pamięci komendą clear. Po wpisaniu tej komendy
program reaguje następująco:
>> clear
>> a
??? Undefined function or variable 'a'.
Zauważmy, że po wpisaniu powyższych instrukcji, w oknie Workspace pojawia się litera
ai obok jej wymiar 1x1. Wszystkie liczby mają taki wymiar, który oznacza w programie
MATLAB® macierz jednoelementową – liczbę.
Liczby mogą być zapisywane bezpośrednio w sposób pokazany wyżej, lub jako wynik
operacji matematycznych. Oto kilka przykładów:
>> a=1+2
a=
3
13

>> a=2*3
a=
6
>> a=2/3
a=
0.6667
>> a=2^3
a=
8
Liczby mogą być również wyrażone jako wartość funkcji:
>> a=sin(2)
a=
0.9093
>> a=log10(2)
a=
0.3010
Zauważmy, że po wpisaniu wartości liczby, program MATLAB® zwraca jej wartość w
stosownym formacie. Bardzo często jest to niewygodne, zwłaszcza, gdy wyniki pośrednich
obliczeń są liczne i nie interesują użytkownika. W celu uniknięcia tej niedogodności, instruk-
cję kończymy znakiem ; . Mamy wtedy:
>> a=2^3;
lecz wartość zmiennej a pozostaje w pamięci, co sprawdzamy pisząc
>> a
a=
8

3.1.2. Liczby zespolone


Program MATLAB® wykonuje obliczenia na liczbach rzeczywistych i zespolonych.
Liczby zespolone zapisujemy w następujący sposób:
>> a=2+i*3
a=
2.0000 + 3.0000i
Podane wyżej sposoby zapisu liczb rzeczywistych odnoszą się w całości do liczb ze-
spolonych. I tak przykładowo mamy:
>> a=sin(2)+i*sin(3)
0.9093 + 0.1411i
Liczbą zespolona może być zapisana w formie wykładniczej. Wyżej podaną liczbę a
można mianowicie zapisać jako:
>> a=abs(a)*exp(i*angle(a))
a=
0.9093 + 0.1411i
Funkcja abs(a) zwraca wartość bezwzględną liczby zespolonej a, zaś funkcja angle –
wartość jej argumentu w radianach. Funkcja exp jest funkcją wykładniczą o podstawie e. Do
zagadnienia funkcji w programie MATLAB® powrócimy w dalszej części skryptu. Tutaj
podamy jeszcze trzy funkcje związane z liczbami zespolonymi. Są to: funkcja real, zwracająca
część rzeczywistą liczby zespolonej i funkcja imag, wyznaczająca część urojoną takiej liczby.
oraz conj, która zmienia liczbę na sprzężoną.
>> real(a)
14

ans =
0.9093
>> imag(a)
ans =
0.1411
>> conj(a)
0.9093 - 0.1411i
W wypadku, kiedy próbujemy wykonać operację, której wynikiem nie jest określona
liczba, program MATLAB® daje ostrzeżenie lub sygnalizuje błąd. Przykładem jest dzielenie
liczby przez zero:
>> 1/0
Warning: Divide by zero.
(Type "warning off MATLAB:divideByZero" to suppress this warning.)
ans =
Inf
Wynikiem operacji jest nieskończoność zapisywana tu jako Inf.
Inny przykład to dzielenie 0/0:
>> 0/0
Warning: Divide by zero.
(Type "warning off MATLAB:divideByZero" to suppress this warning.)
ans =
NaN
Skrót NaN (od ang. Not a Number) oznacza, że wynik nie ma formy liczbowej.
Problemów takich można uniknąć wykorzystując w instrukcjach liczbę oznaczoną jako
eps. Jest to bardzo mała liczba o wartości równej przedziałowi kwantyzacji liczb obwiązują-
cemu w obliczeniach. Zastosowanie tej liczby ilustruje przykład wyznaczania wartości funkcji
sinx/x w punkcie x=0. W punkcie tym występuje dzielenie 0/0, lecz funkcja jest ciągła i ma
wartość 1. Zapiszmy zatem
>> x=0;
>> sin(x)/x
Warning: Divide by zero.
(Type "warning off MATLAB:divideByZero" to suppress this warning.)
ans =
NaN
>> x=0+eps;
>> sin(x)/x
ans =
1
W drugiej instrukcji do argumentu dodaliśmy eps, w wyniku czego otrzymaliśmy pra-
widłowy wynik. Wartość eps wynosi w tym wypadku
>> eps
ans =
2.2204e-016

3.1.3. Zaokrąglenia liczb


Często w obliczeniach numerycznych pojawia się potrzeba zaokrąglenia wartości liczb
do liczb całkowitych. Program MATLAB® ma cztery funkcje, które dokonują zaokrągleń na
cztery różne sposoby. I tak funkcja round zaokrągla liczbę do najbliższej liczby całkowitej:
>> round(2.7)
ans =
3
15

Funkcja floor zaokrągla liczbę do najbliższej liczby całkowitej, najbliższej minus nie-
skończoności.
>> floor(2.7)
ans =
2
Funkcja ceil zaokrągla liczbę do najbliższej liczby całkowitej, najbliższej nieskończono-
ści.
>> ceil (-2.7)
ans =
-2
Funkcja fix zaokrągla liczbę do najbliższej liczby całkowitej, najbliższej zeru.
>> fix(2.7)
ans =
2
Jakkolwiek wyniki zaokrąglenia przy użyciu różnych funkcji bywają jednakowe, to
każda z nich może być przydatna.
Każda z wymienionych funkcji może mieć argument zespolony, a wówczas sposób
uśredniania odnosi się oddzielnie do części rzeczywistej i urojonej liczby. Przykładowo:
>> floor(2.7-i*2.7)
ans =
2.0000 - 3.0000i

3.2. Macierze i wektory


Charakterystyczną cechą programu MATLAB® jest traktowanie każdej zmiennej licz-
bowej jako macierzy lub wektora, który też jest szczególną formą macierzy. Zauważyliśmy
to już, kiedy wymiar liczby zapisany został w oknie Workspace jako 1x1, czyli jako macierz
jednoelementowa. Wynikają stąd w początkowym okresie posługiwania się programem pew-
ne utrudnienia i ograniczenia, które związane są z rachunkiem macierzowym. MATLAB®
traktując każdą zamienną jako macierz akceptuje wyłącznie i konsekwentnie te operacje ma-
tematyczne, które odnoszą się do macierzy i spełniają odpowiednie kryteria. Omówimy te za-
gadnienia szczegółowo.

3.2.1. Definiowanie macierzy i wektorów


Jak wiadomo, macierz składa się z elementów uszeregowanych w wierszach i kolum-
nach. Jeżeli chcemy wprowadzić do programu pewną macierz, to używamy do tego celu na-
stępującego zapisu:
>> X=[1 2 3 4;5 6 7 8;9 10 11 12]
X=
1 2 3 4
5 6 7 8
9 10 11 12
Zapisana w ten sposób macierz ma dwa wiersze i cztery kolumny, co znalazło odbicie w
oknie Workspace, w kolumnie Space, jako 2x4. Zauważmy, że elementy macierzy oddzielone
są spacjami, zaś wiersze średnikami. W ten sposób można definiować macierze o praktycznie
dowolnej liczbie wierszy i kolumn. Elementami macierzy mogą być liczby rzeczywiste i ze-
spolone.
16

Szczególnym rodzajem macierzy są wektory wierszowe i kolumnowe. Wektor wierszo-


wy zapisujemy jako:
>> x=[1 2 3 4 5]
x=
1 2 3 4 5
zaś wektor kolumnowy jako:
>> x=[1;2;3]
x=
1
2
3
Bardzo często zachodzi potrzeba zapisu wektora wierszowego, którego elementami są
liczby tworzące ciąg rosnący lub malejący o stałej różnicy między sąsiednimi liczbami. Ciąg
taki zapisujemy następująco:
>> x=1:2:15
x=
1 3 5 7 9 11 13 15
Jeżeli w zapisie pominiemy drugą liczbę to domyślnie przyjmowana jest jej wartość
jako 1, a mianowicie:
>> x=0:9
x=
0 1 2 3 4 5 6 7 8 9
Ciąg malejący tworzy się następująco:
>> x=2:-0.5:-3
x=
Columns 1 through 6
2.0000 1.5000 1.0000 0.5000 0 -0.5000
Columns 7 through 11
-1.0000 -1.5000 -2.0000 -2.5000 -3.0000
Prostym zapisem można dokonać w macierzy zamiany wierzy na kolumny (utworzyć
macierz transponowaną). W przypadku zamiany macierzy wierszowej na macierz kolumnową
mamy przykładowo:
>> x=(1:4)'
x=
1
2
3
4
Zapis w nawiasach daje macierz wierszową, zaś apostrof zamienia wiersz na kolumnę.
W przypadku transpozycji macierzy mamy:
>> X=[1 2 3; 4 5 6]
X=
1 2 3
4 5 6
>> Y=X’
Y=
1 4
2 5
3 6
17

Jeżeli elementami macierzy są liczby zespolone, to przy zamianie wierszy w kolumny


(lub na odwrót) liczby zamieniają się na sprzężone:
>> X=[1+i*2 2-i*3 3+i*4; 4-i*5 5+i*6 6-i*7]
X=
1.0000 + 2.0000i 2.0000 - 3.0000i 3.0000 + 4.0000i
4.0000 - 5.0000i 5.0000 + 6.0000i 6.0000 - 7.0000i
>> Y=X'
Y=
1.0000 - 2.0000i 4.0000 + 5.0000i
2.0000 + 3.0000i 5.0000 - 6.0000i
3.0000 - 4.0000i 6.0000 + 7.0000i
Jeżeli chcemy dokonać transpozycji macierzy bez zmiany znaków części urojonych,
wówczas stosujemy zapis Y=X.’ (apostrof poprzedzamy kropką).
Każdy element macierzy jest opisany przez podanie numeru jego wiersza i kolumny.
Przykładowo, jeżeli chcemy zapisać wartość elementu macierzy Y zaznaczonej wyżej pogru-
bioną czcionką, wówczas piszemy:
>> y=Y(3,2)
y=
6.0000 + 7.0000i
gdyż zaznaczony element leży w trzecim wierszu i drugiej kolumnie.
Wykorzystując tę zasadę możemy zmienić wartość określonego elementu macierzy. Je-
żeli w macierzy Y w miejsce y chcemy wstawić np. 5 , to piszemy:
>> Y(3,2)=5;
>> Y
Y=
1.0000 - 2.0000i 4.0000 + 5.0000i
2.0000 + 3.0000i 5.0000 - 6.0000i
3.0000 - 4.0000i 5.0000
W napisanym programie często chcemy wprowadzać pewne zmiany w przed kolejnym
jego uruchomieniem. Jeżeli zmiana taka polega na zmianie wartości liczbowej wówczas po-
sługujemy się instrukcją input. Sposób jej wykorzystania ilustrują dwa przykłady. Jeżeli
chamy wprowadzić lub zmienić wartość stałej a, wtedy piszemy:
>> a=input('nowa wartość=')
nowa wartość=2
a=
2
Jeżeli w programie wystąpi instrukcja zapisana w pierwszym wierszu, wówczas w oknie
Command Window pojawi się ciąg znaków ujętych w apostrofy (tu ‘nowa wartość=’). Program
czeka, aż użytkownik wpisze potrzebną wartość stałej a. Po wpisaniu tej wartość program
zwraca jej wartość.
W analogiczny sposób można zmienić wartość dowolnego elementu macierzy. Jeżeli w
zdefiniowanej wyżej macierzy Y chcemy zmienić wartość elementu w drugim wierszu i
pierwszej kolumnie, to piszemy:
>> Y(2,1)=input(‘Y(2,1)=’)
>> Y(2,1)= 0
Y=
1.0000 - 2.0000i 4.0000 + 5.0000i
0 5.0000 - 6.0000i
3.0000 - 4.0000i 5.0000
18

Program MATLAB zwraca wybrany wektor z macierzy, gdy użyjemy dwukropka.


Weźmy jako przykład następującą macierz:
A=
1 2 3 4
5 6 7 8
9 10 11 12
Zaznaczony grubą czcionką wektor otrzymujemy dzięki następującemu zapisowi:
>> a=A(:,3)
a=
3
7
11
Jak widać dwukropek oznacza tu „wszystkie wiersze”
Jeżeli chcemy utworzyć wektor tylko z dwóch wierszy w znajdujących się w trzeciej
kolumnie, to piszemy:
>> a=A(2:3,3)
a=
7
11
W powyższym zapisie dwukropek oznacza „do”.
Dzięki podanemu niżej zapisowi tworzymy macierz z pożądanych wierzy i kolumn.
>> B=A(2:3,1:3)
B=
5 6 7
9 10 11
Program MATLAB® generuje kilka prostych i użytecznych macierzy, a mianowicie
macierz zerową, jedynkową i jednostkową:
>> A=zeros(3,5)
A=
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>> A=ones(4,3)
A=
1 1 1
1 1 1
1 1 1
1 1 1
>> A=eye(3,4)
A=
1 0 0 0
0 1 0 0
0 0 1 0
Ostatnia z podanych macierzy jest szczególnie użyteczna jako macierz kwadratowa.
Ponadto program MATLAB® generuje macierze zawierające wartości losowe o rozkła-
dzie jednostajnym i normalnym, bardzo użyteczne w obliczeniach inżynierskich. Macierz o
rozkładzie jednostajnym zawiera liczby z przedziału <0,1>, a jej przykładowa postać jest na-
stępująca:
>> A=rand(2,5)
19

A=
0.9501 0.6068 0.8913 0.4565 0.8214
0.2311 0.4860 0.7621 0.0185 0.4447
Liczby zawarte w macierzy o rozkładzie normalnym mają wartość średnią zmierzającą
do zera i odchylenie standardowe zmierzające do jedności.
>> A=randn(2,5)
A=
-0.4326 0.1253 -1.1465 1.1892 0.3273
-1.6656 0.2877 1.1909 -0.0376 0.1746
Szczegóły dotyczące praktycznego wykorzystania tych macierzy podamy w dalszej czę-
ści skryptu.
Na zakończenie omawiania sposobów definiowania macierzy pokażemy jeszcze jedną
użyteczną metodę. Polega ona na sklejaniu macierzy o tej samie liczbie wierszy lub kolumn.
Metodę te pokazują następujące przykłady:
>> A=zeros(3,4)
A=
0 0 0 0
0 0 0 0
0 0 0 0
>> B=ones(3,3)
B=
1 1 1
1 1 1
1 1 1
>> C=[A B A]
C=
0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 1 1 1 0 0 0 0
Ze zdefiniowanych macierzy A i B utworzona została macierz C o liczbie wierszy rów-
nej liczbie wierszy macierzy A i B i zwiększonej liczbie kolumn.
Jeżeli macierze mają jednakową liczbę kolumn, to można z nich utworzyć macierz o
zwiększonej liczbie wierszy:
>> C=[A(:,1:3);B;A(:,1:3)]
C=
0 0 0
0 0 0
0 0 0
1 1 1
1 1 1
1 1 1
0 0 0
0 0 0
0 0 0
W macierzy A zmniejszyliśmy liczbę kolumn do trzech stosując wcześniej podany za-
pis. Należy zwrócić uwagę, że macierze w instrukcji zostały rozdzielone średnikiem.
Dogodnym narzędziem wprowadzania zmian istniejącej macierzy jest Array Editor. Jest
to okno, w którym edytowana jest macierz i w którym można zmieniać wartości elementów
macierzy, liczbę wierszy i kolumn oraz wpisywać w nie nowe wartości. Okno to otwiera in-
strukcja
openvar(‘A’)
20

Można je także otworzyć zaznaczając w oknie Workspace odpowiednią macierz (wek-


tor) i przyciskając ikonę Open. Obok ikony Open na pasku okna Workspace znajduje się ikona
Delete, której przyciśnięcie usuwa zaznaczoną macierz (wektor).

3.2.2. Podstawowe operacje macierzowe


Konsekwencją traktowania zmiennych w programie MATLAB® jako macierzy jest ak-
ceptowanie tylko takich operacji na zmiennych, które są zgodne z zasadami rachunku macie-
rzowego. Przypomnimy dlatego pokrótce podstawowe operacje na macierzach i zilustrujemy
je prostymi przykładami.
Zdefiniujemy najpierw dwie macierze, którymi będziemy się posługiwali w przykła-
dach:
>> A=[1 4 -2; 3 -5 6]
A=
1 4 -2
3 -5 6
>> B=[2 4 -4; 6 7 -3]
B=
2 4 -4
6 7 -3
Suma macierzy A i B jest równa:
>> C=A+B
C=
3 8 -6
9 2 3
Sumować można wyłącznie macierze posiadające jednakowy wymiar, czyli tę samą
liczbę wierszy i kolumn. Sumowanie polega na następujących operacjach:
C(m,n)=A(m,n)+B(m,n) dla m=1:M, n=1:N
gdzie M jest liczbą wierszy macierzy A i B, a N – liczbą kolumn tych macierzy.
Jeżeli macierze mają różny wymiar, wtedy program MATLAB® nie wykonuje źle zapi-
sanej operacji i podaje tego przyczynę. Przykładowo zapiszemy:
>> C=B(:,1:2)
C=
1 4
6 7
>> D=A+C
??? Error using ==> +
Matrix dimensions must agree.
Program wykrył błąd w zapisie sumy i wskazał na jego przyczynę: „Wymiary macierzy
muszą być zgodne”. Macierz C ma bowiem tylko dwie kolumny, zaś macierz A – trzy.
Odejmowanie macierzy B od macierzy A o tych samych wymiarach daje macierz C, o
następujących elementach:
>> C=A-B
C=
-1 0 2
-3 -12 9
Mnożenie macierzy A(m,n) o wymiarach MxN przez macierz B(n,k) o wymiarach NxK
daje macierz C(m,k) o następujących elementach:
21

N
C(m, k )   A(m, n)B(n, k) dla m=1:M i k=1:K;
n1

Zdefiniowane wyżej macierze A i B nie mogą być mnożone, bo liczba kolumn macierzy
A nie jest równa liczbie wierszy macierzy B. Rzeczywiści mamy:
>> C=A*B
??? Error using ==> *
Inner matrix dimensions must agree.
Możliwe jest natomiast wykonanie mnożenia macierzy A przez macierz transponowaną
B’.
>> B'
ans =
2 6
4 7
-4 -3
>> C=A*B'
C=
26 40
-38 -35
Użyteczną operacją w obliczeniach jest mnożenie wektora kolumnowego przez wektor
wierszowy. Mamy bowiem wtedy:
N
C(m, k )   A(m,1)B(1, k)  A(m,1)B(1, k) dla
n1
m=1:M i k=1:K;

Każdy element macierzy C jest iloczynem odpowiedniego elementu wektora kolumno-


wego i wierszowego. Przykładowo:
>> a=[1 2 3]'
a=
1
2
3
>> b=[4 5 6 7 8]
b=
4 5 6 7 8
>> C=a*b
C=
4 5 6 7 8
8 10 12 14 16
12 15 18 21 24
Wykorzystując wektory jednostkowe można generować macierze o jednakowych wier-
szach lub kolumnach.
Czwartą operację na macierzach, a mianowicie ich dzielenie omówimy w następnym
punkcie poświęconym macierzom kwadratowym.
Przypomnijmy, że na ogół operacja mnożenia macierzy nie jest przestawna, czyli
A·B≠B A, nawet jeżeli w obu wypadkach mnożenie jest wykonywalne. Ilustruje to następujący
prosty przykład:
>> A=[1 2; 4 5]
A=
1 2
4 5
>> B=[3 4; 6 5]
22

B=
3 4
6 5
>> C=A*B
C=
15 14
42 41
>> D=B*A
D=
19 26
26 37
Jak widać, przestawienie kolejności macierzy daje różna wyniki, gdyż C≠D.

3.2.3. Macierze kwadratowe


Największe znaczenie w obliczeniach inżynierskich mają macierze kwadratowe, czyli
macierze o tej samej liczbie wierszy i kolumn. Z macierzy kwadratowej można utworzyć ma-
cierz odwrotną, która wykorzystuje się do m.in. do rozwiązywania układów równań linio-
wych. Pomijając procedurę wyznaczania macierzy odwrotnej, którą stosuje program MA-
TLAB®, przedstawimy jej podstawowe właściwości i zastosowania w rachunku macierzo-
wym. Macierz odwrotną do macierzy A oznaczmy jako A-1, a wtedy związek między oby ma-
cierzami można zapisać jako:
-1 -1
A·A =1 lub A ·A=1
gdzie 1 oznacza macierz jednostkową.
Jeżeli mamy równanie macierzowe:
A·x=b,
gdzie x jest wektorem niewiadomych, a b wektorem danych, to mnożąc obustronnie powyższe
równanie przez A-1 otrzymujemy:
-1 -1
A ·A·x=A ·b
Wykorzystując podaną wyżej zależność między macierzą i macierzą do niej odwrotną mamy:
-1
1·x=A ·b,
a stąd ostatecznie:
-1
x=A ·b.
Program MATLAB® wyznacza macierz odwrotną do macierzy A, gdy zapiszemy nastę-
pującą instrukcję:
>> inv(A)
lub
>> A^-1
Sposób wykorzystania macierzy odwrotnej pokażemy na przykładzie rozwiązania poda-
nego niżej układu czterech równań liniowych.
2x 1  3 x 2  4 x 3  5 x 4  28
4 x 1  4 x 2  8 x 3  2x 4  4
3 x 1  3 x 2  4 x 3  2x 4  7
2x 1  2x 2  3 x 3  5 x 4  13

Układ ten zapisany w formie macierzowej ma następującą postać:


23

2  3 4 5   x 1   28 
     
4 4  8 2    x 2     4 
3  3  4 2   x 3    7 
     
2  2 3  5  x 4   13

Poniżej przedstawiono program służący do rozwiązania tego układu równań.


>> A=[2 -3 4 5;4 4 -8 2;3 -3 -4 2;2 -2 3 -5];
>> b=[28 -4 -7 -13]';
>> x=inv(A)*b
>> x1=x(1)
x1 =
1.0000
>> x2=x(2)
x2 =
2.0000
>> x3=x(3)
x3 =
3.0000
>> x4=x(4)
x4 =
4.0000
Należy zwrócić uwagę na apostrof przy zapisie wektora b, który zamienia wektor wier-
szowy na kolumnowy. W przedstawionym programie nie jest potrzebna użytkownikowi
jawna postać macierzy odwrotnej. Podamy ją jednak dla porządku w celu ewentualnego
sprawdzenia poprawności obliczeń.
>> inv(A)
ans =
0.1200 0.1400 -0.0400 0.1600
0.0428 0.1303 -0.2097 0.0110
0.1048 0.0131 -0.1269 0.0593
0.0938 0.0117 -0.0083 -0.1048
Instrukcja x=inv(A)*b jest równoważna lewostronnemu dzieleniu macierzy, które zapi-
suje się jako:
>> x=A\b
x=
1.0000
2.0000
3.0000
4.0000
co jest łatwiejsze do zapamiętania.
Prawostronne dzielnie macierzy definiowane jest jako:
>> B/A=B*inv(A)
przy czym B musi mieć taką samą liczbę kolumn, jaką liczbę wierzy ma macierz inv(A). Ope-
racja ta jest rzadko stosowana w praktyce.
W niektórych obliczeniach potrzeby jest wyznacznik macierzy. Dla podanej wyżej ma-
cierzy A, program MATLAB® wyznacza go następująco:
>> det(A)
ans =
1450
24

3.3. Tablice
Program MATLAB® operuje nie tylko na macierzach, lecz również na tablicach (ang.
arrays). Tablicą (dwuwymiarową) jest uporządkowany w wiersze i kolumny zbiór liczb lub
znaków. W tym sensie macierz jest specyficzną tablicą numeryczną, której dotyczą operacje
macierzowe. Specyficzną formą tablic zawierających znaki (ang. charakter arrays) są rów-
nież łańcuchy (ang. strings). W skrypcie zajmiemy się wyłącznie tablicami numerycznymi i
łańcuchami, które mają duże znaczenie z punktu widzenia obliczeń inżynierskich.

3.3.1. Tablice numeryczne


Jedno i dwuwymiarowe tablice numeryczne definiowane są identycznie jak wektory i
macierze. Różnice pojawiają się wtedy, gdy chcemy wykonać na nich określone operacje.
Charakterystyczną cechą tablic jest to, że operacje na nich wykonywane są na ich elementach
metodą „element po elemencie”. Domyślnie każda tablica numeryczna traktowania jest w
programie MATLAB® jako macierz. Jeżeli chcemy wykonać na niej operacje odnoszące się
do tablic, musimy to wyróżnić specjalnym operatorem. Potrzeba taka nie zachodzi tylko w
przypadku dodawania i odejmowania, gdyż operacje te są jednakowe dla tablic i macierzy.
Omówimy teraz pokrótce podstawowe operacje na tablicach.
Mnożenie tablic A i B zapisujemy jako:
>> C=A.*B
Znak mnożenia został poprzedzony kropką, co sygnalizuje, że A i B są tablicami i mno-
żenie ma być wykonane w sposób dla nich właściwy. Mnożenie tablic polega na następują-
cych operacjach:
C(m,n)=A(m,n)·B(m,n) dla m=1:M i n=1:N.
Oto prosty przykład:
>> A=[ 1 2 3; 3 2 1; 4 5 6]
A=
1 2 3
3 2 1
4 5 6
>> B=[2 3 4; 4 3 2; 1 2 3]
B=
2 3 4
4 3 2
1 2 3
>> C=A.*B
C=
2 6 12
12 6 2
4 10 18
W analogiczny sposób zapisujemy operację dzielenia tablic:
C(m,n)=A(m,n)/B(m,n) dla m=1:M i n=1:M.
W programie MATLAB® odpowiednia instrukcja ma następującą postać:
>> C=A./B
C=
0.5000 0.6667 0.7500
0.7500 0.6667 0.5000
4.0000 2.5000 2.0000
Operację potęgowania tablicy zapisujemy jako:
25

>> C=A.^3
C=
1 8 27
27 8 1
64 125 216
Ze względu na sposób wykonywania operacji na tablicach nie są wykonywane niektóre
operacje odnoszące się do macierzy. Przykładowo porównajmy dwie operacje, w których
występuje wcześniej zdefiniowana macierz A:
>> B=[1 2 3]'
B=
1
2
3
>> C=A*B
C=
14
10
32
>> C=A.*B
??? Error using ==> .*
Matrix dimensions must agree.
Pierwsza operacja odnosi się do macierzy i jest poprawna. Druga operacje dotyczy ta-
blic i jest błędna, gdyż obie tablice muszą mieć jednakowy wymiar.
Podane wyżej przykłady dotyczyły tablic kwadratowych. Obowiązują one również dla
tablic prostokątnych, a w tym jednowymiarowych, odpowiadających wektorom. Pokazuje to
następujący przykład:
>> a=1:10
a=
1 2 3 4 5 6 7 8 9 10
>> b=a.^2
b=
1 4 9 16 25 36 49 64 81 100
Zauważmy, że operacja potęgowania jest równoważna mnożeniu. Jeżeli zapiszemy:
>> b=a^2
??? Error using ==> ^
Matrix must be square.
program MATLAB® zgłosi błąd i wskaże na jego przyczynę, która wynika z reguł mnożenia
macierzy (przy mnożeniu a·a=a2 macierz a musi być prostokątna).
W programie MATLAB® można posługiwać się tablicami wielowymiarowymi (ang.
multidimesional arrays). Sposób definiowania takich tablic i posługiwania się nimi pokażemy
w dalszej części skryptu.

3.3.2. Łańcuchy
Łańcuchy wykorzystywane są w prostych obliczeniach inżynierskich głównie do opi-
sywania danych i rysunków. Łańcuch znaków tworzymy ujmując je w apostrofy. Program
MATLAB® sygnalizuje pojawienie się początku łańcucha standardowo kolorem niebieskim, a
jego zakończenie zmianą koloru na czerwony. Łańcuchy wyróżniają się zatem wyraźnie w
pisanym przez użytkownika programie. Każdy znak łańcucha traktowany jest jako element
tablicy, co umożliwia wykonywanie na nich określonych operacji. Kilka prostych operacji
ilustruje poniższy przykład.
26

>> a='dom'
a=
dom
>> a(3)
ans =
m
>> a(2)='y'
a=
dym
W pierwszym wierszu poleceń zdefiniowany został łańcuch, w drugim wywołano trze-
cim element tego łańcuch, a w trzecim zmieniono znak o na znak y.
Łańcuchy można rozszerzać analogicznie jak macierze. Ilustruje to poniższy przykład
>> b='ek'
b=
ek
>> c=[a b]
c=
dymek
Rozdzielnie łańcuchów znakiem średnika powoduje utworzenie tablicy pod warunkiem,
że oba łańcuch mają jednakową liczbę znaków:
>> d='ogień'
d=
ogień
>> e=[c;d]
e=
dymek
ogień

3.4. Funkcje
Program MATLAB® dysponuje wielką liczbą funkcji, z których niewielka część jest
znana z ogólnej matematyki, a pozostała została zdefiniowana w programie w celu rozwiązy-
wania rozmaitych problemów numerycznych i tworzenia grafiki. Nawet pobieżna prezentacja
funkcji występujących w programie MATLAB® zdecydowanie przekracza ramy tego skryptu.
Ograniczymy się zatem do podania ogólnych zasad posługiwania się funkcjami i omówimy
najczęściej stosowane.
Dla potrzeb tego skryptu wygodnie jest podzielić funkcje na kilka charakterystycznych
typów i omówić je oddzielnie.

3.4.1. Funkcje standardowe


Do tej klasy funkcji zaliczymy ogólnie znane funkcje matematyczne. Są to funkcje po-
tęgowe, wykładnicze, logarytmiczne i trygonometryczne. Zapis tych funkcji nie różni się od
stosowanego w matematyce. Program MATLAB® wyznacza wartości tych funkcji dla dys-
kretnych wartości argumentu, którym jest wektor lub macierz. Ogólny zapis standardowych
funkcji ma następującą postać:
>> Y=f(X)
gdzie X jest macierzą argumentów, Y macierzą wartości funkcji, a w miejsce symbolu f wpi-
suje się nazwę funkcji. Przykładowo wartości funkcji sinus wyznacza się następująca instruk-
cja:
27

>> y=sin(x)
Praktyczny sposób wykorzystanie tej instrukcji pokazuje następujący przykład:
>> x=2*pi*(0:0.1:1)
x=
Columns 1 through 7
0 0.6283 1.2566 1.8850 2.5133 3.1416 3.7699
Columns 8 through 11
4.3982 5.0265 5.6549 6.2832
>> y=sin(x)
y=
Columns 1 through 7
0 0.5878 0.9511 0.9511 0.5878 0.0000 -0.5878
Columns 8 through 11
-0.9511 -0.9511 -0.5878 -0.0000

Powyższy program wyznacza wartości funkcji sinus w przedziale <0,2> w punktach


stanowiących kolejne elementy wektora x. Wartości te podano w celach edukacyjnych; w
praktyce należy po pierwszej instrukcji wstawić średnik, dzięki czemu unikniemy niepotrzeb-
nego wypisywania wartości argumentu.
Posługując się funkcjami standardowymi i operatorami można tworzyć własne funkcje.
Pozostając przy zdefiniowanej wyżej funkcji sinusoidalnej można przykładowo utworzyć
niestandardową funkcję sin2(x) i wyznaczyć jej wartości. W tym celu zapisujemy następujące
instrukcje:
>> x=2*pi*(0:0.1:1);
>> y=sin(x).^2
y=
Columns 1 through 7
0 0.3455 0.9045 0.9045 0.3455 0.0000 0.3455
Columns 8 through 11
0.9045 0.9045 0.3455 0.0000
Kropka przed znakiem potęgi jest niezbędna, gdyż powoduje, że potęgowanie dotyczy
każdego elementu wektora sinx. Przy braku kropki program zgłasza błąd.
W zmieszczonej niżej tablicy podano najczęściej używane funkcje standardowe.
Symbol funkcji
matematyczny MATLAB®
sin sin
cos cos
tg tan
arcsin asin
arccos acos
artg atan
log log10
ln log
sqrt
e(.) exp
sinh sinh
cosh cosh
tgh tanh
a
(.) (.)^a
28

Argumenty funkcji w programie MATLAB® mają szersze dziedziny niż podawane w


matematyce elementarnej, gdyż program operuje na liczbach zespolonych. Przykładowo:
>> log10(-2)
ans =
0.3010 + 1.3644i
lub
>> sin(2+i*3)
ans =
9.1545 - 4.1689i
Jak już wspomniano, dziedziną funkcji standardowych są nie tylko wektory, lecz także
macierze. Jeżeli w argumencie funkcji występuje macierz, wówczas program zwraca wartości
funkcji dla każdego elementu macierzy i zapisuje je w formie macierzy. Położenie każdej
wartości funkcji w tej nowej macierzy jest takie same jak argumentu w macierzy stanowiącej
dziedzinę funkcji. Oto prosty przykład funkcji sinus, której argumentem jest macierz:
>> X=[0 pi/2 pi 3*pi/2 2*pi; 0 pi/4 pi/2 3*pi/4 pi]
X=
0 1.5708 3.1416 4.7124 6.2832
0 0.7854 1.5708 2.3562 3.1416
>> Y=sin(X)
Y=
0 1.0000 0.0000 -1.0000 -0.0000
0 0.7071 1.0000 0.7071 0.0000

3.4.2. Funkcje macierzowe


Programie MATLAB® dysponuje bardzo dużą liczbą funkcji, których dziedziną są ma-
cierze i wektory. Omówimy tutaj część tych funkcji, które są najczęściej używane w oblicze-
niach inżynierskich. Niektóre z tych funkcji już poznaliśmy wcześniej i przypomnimy je w
celu podkreślenia, że dotyczą one macierzy jako argumentów.
det(A) – zwraca wyznacznik macierzy prostokątnej
inv(A) – wyznacza macierz odwrotną do macierzy prostokątnej
abs(A) – zwraca macierz zawierającą wartości bezwzględne elementów macierzy A
real(A) – zwraca macierz zawierającą wartości rzeczywiste elementów macierzy A
imag(A) – zwraca macierz zawierającą wartości urojone elementów macierzy A
angle(A) –zwraca macierz zawierającą wartości argumentów elementów macierzy A
conj(A) – zwraca macierz, której elementy są sprzężone względem elementów macierzy
A
zwracają macierze, której elementami są liczby zaokrą-
round(A), floor(A), ceil(A), fix(A) –
glone według reguł opisanych dla liczb
Omówione niżej funkcje wykorzystuje się m.in. do analizy przebiegu funkcji jedno i
dwuwymiarowych zapisywanych numerycznie w formie wektorów lub macierzy.
Funkcja sum dokonuje sumowania liczb oddzielnie w każdej kolumnie macierzy i two-
rzy wektor wierszowy, w którym elementami są wyniki sumowania w odpowiednich kolum-
nach. Ilustruje to następujący przykład:
>> A=[ 1 2 3; -1 3 4; -5 0 1]
A=
29

1 2 3
-1 3 4
-5 0 1
>> a=sum(A)
a=
-5 5 8
Jeżeli argumentem funkcji sum jest wektor, to zwraca ona sumę elementów tego wek-
tora. Tak więc sumę wszystkich elementów macierzy A wyznaczamy jako:
>> as=sum(a)
as =
8
lub bezpośrednio jako:
>> as=sum(sum(A))
as =
8
Bardzo użyteczną funkcją jest cumsum, która jest w obliczeniach numerycznych odpo-
wiednikiem całki
t
y( t )   x()d .
0

Funkcja ta wyznacza macierz, w której wierszach znajdują się bieżące sumy wyzna-
czane oddzielnie w każdej kolumnie według następującego wzoru:
m
B(m, n)   A(m, n) .
n1

Dla rozpatrywanej macierzy A mamy więc:


>> B=cumsum(A)
B=
1 2 3
0 5 7
-5 5 8
Odpowiednikiem różniczkowania w obliczeniach numerycznych jest funkcja diff. Reali-
zuje ona następującą operację:
m
C(m, n)   A(m  1, n)  A(m, n)
n1

Dla macierzy A funkcja diff buduje macierz:


>> C=diff(A)
C=
-2 1 1
-4 -3 -3
Jak widać liczba wierszy w macierzy C jest o jeden mniejsza od liczby wierszy macie-
rzy A.
Funkcja max zwraca wektor wierszowy, w którym znajdują się maksymalne wartości
występujące w odpowiednich kolumnach. Pokazuje to następujący przykład:
>> a=max(A)
a=
1 3 4
30

Jeżeli argument jest wektorem, to funkcja max wyznacza maksymalną wartość tego
wektora:
>> amax=max(a)
amax =
4
Zauważmy, że w tym przykładzie liczba 4 jest wartością maksymalną występującą w
macierzy A. W celu wyznaczenia wartości maksymalnej macierzy można użyć krótszej in-
strukcji:
>> amax=max(max(A))
amax =
4
Funkcja min zwraca wektor wierszowy, w którym znajdują się minimalne wartości wy-
stępujące w odpowiednich kolumnach. Oto przykład:
>> a=min(A)
a=
-5 0 1
>> amin=min(a)
amin =
-5
Funkcja mean zwraca wektor wierszowy, w którym znajdują się średnie wartości licz
występujących w odpowiednich kolumnach. Dla rozpatrywanej to macierzy mamy:
>> a=mean(A)
a=
-1.6667 1.6667 2.6667
>> amean=mean(a)
amean =
0.8889
Ostatnia liczba jest średnią wartością elementów macierzy A.
Funkcja std zwraca wektor wierszowy, w którym znajdują się odchylenia standardowe
wartości w odpowiednich kolumnach.
>> a=std(A)
a=
3.0551 1.5275 1.5275
Funkcja var wyznacza wariancję według podanych wyżej reguł:
>> a=var(A)
a=
9.3333 2.3333 2.3333
Jak widać, wariancja jest równa kwadratowi odchylenia standardowego. W wypadku
ostatnich funkcji nie podano odchylenia standardowego i wariancji wyznaczonego z wekto-
rów, gdyż nie są te wielkości równe i odpowiednim wielkościom dla całej macierzy.
Funkcji mean, std i var używa się głównie do analizy procesów stochastycznych.
Bardzo użyteczną funkcją jest funkcja size, która zwraca liczbę wierszy i kolumn ma-
cierzy:
>> [M,N]=size(A)
M=
3
N=
3
31

Na pierwszy rzut oka wydaje się ona zbędna, jednakże w bardziej złożonych progra-
mach wykorzystuje się ją bardzo często. Wymiary macierzy bywają bowiem zmienne, gdyż
mogą być uzależnione od podawanych przez użytkownika parametrów.

3.4.3 Relacje i operacje logiczne


Operacje logiczne polegają w ogólności na sprawdzaniu, czy zapisana relacja między
macierzami jest prawdziwa. Wynikiem sprawdzenia jest decyzja binarna: prawda oznaczona
cyfrą 1 lub fałsz, oznaczony cyfrą 0. Najczęściej używanymi relacjami są równość i nierów-
ności. Najprostszy przykład dotyczy macierzy jednoelementowych, czyli liczb. Zapiszmy
następującą relację
>> p=3>2
p=
1
>> p=2>3
p=
0
Pierwszą instrukcję należy rozumieć następująco: Sprawdź, czy prawdą jest, że 3 jest
większe od 2. Jeżeli jest to prawda to wstaw p=1, w przeciwnym wypadku wstaw p=0. Ponie-
waż pierwsza nierówność jest prawdziwa, program zwrócił wartość p=1. Druga nierówność
jest fałszywa i stąd p=0.
Ogólny zapis operacji logicznych dla macierzy ma następującą postać:
>> C=A==B lub >> C=eq(A,B) A równe B
>>C=A~=B lub >> C=ne(A,B) A nie równe B
>> C=A<B lub >> C=lt(A,B) A mniejsze od B
>> C=A<=B lub >> C=le(A,B) A mniejsze lub równe B
>> C=A>B lub >> C=gt(A,B) A większe od B
>> C=A>=B lub >> C=ge(A,B) A większe lub równe B
W powyższych relacjach A i B są macierzami o takich samych wymiarach. Sprawdzanie
poprawności zapisanych relacji odnosi się do wszystkich elementów macierzy o tym samym
numerze wiersza i kolumny. W miejscach elementów dla których relacja jest prawdziwa w
macierzy C figurują cyfry 1, a w pozostałych cyfry 0. Ilustrują to następujące przykłady doty-
czące wcześniej zdefiniowanych macierzy A i B.
A=
1 2 3
-1 3 4
-5 0 1
B=
3 2 1
-6 3 0
0 0 1
>> C1=A==B
C1 =
0 1 0
0 1 0
0 1 1
>> C2=A>B
C2=
0 0 1
32

1 0 1
0 0 0
>> C3=A>=B
C3 =
0 1 1
1 1 1
0 1 1
Jeżeli chcemy znać wartości elementów macierzy A lub B, dla których zapisana relacja
jest prawdziwa możemy użyć mnożenia tablicowego (wyraz po wyrazie). Przykładowo rela-
cję równości spełniają w obu macierzach następujące elementy:
>> D=A.*C1
D=
0 2 0
0 3 0
0 0 1
Opis rzadziej używanych operatorów logicznych (np. and lub or) można znaleźć w Help
programu MATLAB.
Wszystkie podane wyżej relacje dotyczą również wektorów o tej samej liczbie elemen-
tów. Można je wykorzystywać m.in. do analizy przebiegu funkcji, rozwiązywania równań
nieliniowych itp.
Przydatną funkcją, w której występują relacje jest funkcja find. Zwraca ona numery
wierszy i kolumn w których dana relacja jest prawdziwa. Ilustruje to następujący przykład:
>> [m,n]=find(D>1)
m=
1
2
n=
2
2
Elementy macierzy D o wartościach większych od 1 to D(1,2) i D(2,2).

3.4.4. Instrukcje warunkowe


Instrukcje warunkowe służą do uzależnienia wykonania instrukcji od spełnienia okre-
ślonych relacji logicznych. Najprostsza struktura instrukcji warunkowej jest następująca:
if <relacja logiczna>
<instrukcja>
end
Instrukcja jest wykonywana tylko wtedy, gdy zapisana wyżej relacja logiczna jest praw
dziwa. W przeciwnym wypadku program przechodzi do instrukcji znajdującej się za end. Oto
prosty przykład:
>> w=2;
>> if w==2
y=2*w
end
y=
4
Ponieważ w =2, to program wykonał instrukcję y=2w i podał jej wynik. Inny przykład:
>> w=2;
33

>> if w>2
y=2*w
end
>> y=3*w
y=
6
Warunkiem wykonania instrukcji y=2w jest to, że w>2; a ponieważ nie jest to prawda,
więc program wykonał pierwszą instrukcję znajdującą się za end i podał jej wynik.
Instrukcje warunkowe mogą być rozbudowane w celu zwiększenia liczby relacji logicz-
nych, których prawdziwość warunkuje wykonanie większej liczby instrukcji. Struktura takich
instrukcji warunkowych ma następującą postać:
if <relacja logiczna 1>
<instrukcja 1>
eleseif <relacja logiczna 2>
<instrukcja 2>
else
<instrukcja 3>
end
Polecenie elseif może powtarzać się wielokrotnie. Polecenie else może być użyte jedno-
krotnie lub być pominięte.
Jeżeli relacja 1 zapisana za if jest prawdziwa, program wykonuje instrukcję 1 i po jej
wykonaniu przechodzi do pierwszej instrukcji po end. W przeciwnym wypadku przechodzi do
polecenia elseif i sprawdza zapisaną relację 2. Jeżeli jest ona prawdziwa, to wykonuje instruk-
cję 2 i po jej wykonaniu przechodzi do pierwszej instrukcji za end. Jeżeli relacja 2 nie jest
prawdziwa, program wykonuje instrukcję 3 znajdującą się za poleceniem else i po jej wyko-
naniu przechodzi od instrukcji znajdującej się za end.
Należy podkreślić, że instrukcje 1, 2 i 3 mogą składać się z całych, rozbudowanych
fragmentów programu.
Wykorzystując relację równości == można sprawdzać zgodność łańcuchów, pod wa-
runkiem, że mają taką samą długość:
a =’kot’
if a=='kot'
'ssak'
elseif a=='kos'
'ptak'
end
ans =
ssak
Poniżej podano przykład programu, który na żądanie użytkownika wyznacza wartości
funkcji sin, cos, log, exp dla wektora x.
clear
x=1:5;
'Wpisz jedną z funkcji; sin, cos, log, exp.'
f=input('f= ');
if f=='sin'
y=sin(x)
elseif f=='cos'
y=cos(x)
elseif f=='log'
y=log10(x)
34

else
y=exp(x)
end
Po uruchomieniu programu mamy:
ans =
Wpisz jedną z funkcji; sin, cos, log, exp.
f= 'sin'
y=
0.8415 0.9093 0.1411 -0.7568 -0.9589
Należy zwrócić uwagę, że nazwy funkcji należy ująć w apostrofy.
Po następnym uruchomieniu programu i wybraniu innej funkcji otrzymujemy:
ans =
Wpisz jedną z funkcji; sin, cos, log, exp.
f= 'log'
y=
0 0.3010 0.4771 0.6021 0.6990

3.4.5. Definiowanie funkcji


Wszystkie funkcje występujące w programie MATLAB są zdefiniowane według reguł
obowiązujących w tym programie. Część plików definiujących i realizujących funkcje można
obejrzeć wpisując instrukcję:
open <nazwa funkcji>
Pliki te mają rozszerzenie .m.
Pewna część funkcji, w tym np. wszystkie funkcje standardowe i podstawowe funkcje
macierzowe, są funkcjami wbudowanymi i nie są dostępne dla użytkownika. Przykładowo
pisząc komendę:
open sin
??? Error using ==> open
Can't open the built-in function 'sin'.
otrzymujemy powyższą informację.
Programista może zdefiniować własną funkcję o nazwie nie występującej w zestawie
funkcji programu MATLAB. Warto zadać sobie pytanie, czy i kiedy należy zdefiniować
taką funkcję. Otóż należy najpierw stwierdzić wyraźnie, że każdy program można napisać bez
konieczności definiowania własnych funkcji. Z kolei program można napisać tak, aby stano-
wił on określoną funkcję. Zwykle między tymi skrajnościami dokonujemy wyboru definiując
fragmenty programu jako funkcję, a pozostawiając pozostałe części w formie zwykłego
zbioru instrukcji. Ogólnie można powiedzieć, że funkcje tworzymy wówczas, gdy będziemy
ich używać wielokrotnie w naszym programie lub chcemy je udostępnić dla innych progra-
mów.
Zasadnicza różnica między zwykłymi programami, a funkcjami polega na tym, że
zmienne występujące w zwykłych programach są tzw. zmiennymi globalnymi, zaś występu-
jące w funkcjach są zmiennymi lokalnymi.
Zmienne globalne przechowywane są w pamięci dostępnej dla wszystkich uruchomio-
nych programów. Jeżeli uruchomimy kolejno dwa programy, a w pierwszym z nich wystąpi
zmienna np. x, to w drugim programie można ją wykorzystać do obliczeń, zmienić jej wartość
itp. Będzie ona dostępna dopóki programy nie zostaną zamknięte lub nie zostanie usunięta
35

specjalną instrukcją. Przy długich programach może to być przyczyną błędów, gdyż można
przypadkowo użyć tej samej nazwy do oznaczenia innych zmiennych. Często w jednym pro-
gramie wykorzystuje się inne programy, które nie są zdefiniowane jako funkcje. Prawdopodo-
bieństwo popełnienia opisanego błędu rośnie wtedy jeszcze bardziej.
Zmienne lokalne występujące w funkcjach nie są widziane poza nimi. Można zatem
używać w programie tych samych nazw zmiennych, które występują w pliku zawierającym
funkcję. Jest to duże ułatwienie dla programisty. Aby funkcja nie była hermetycznie odcięta
od innych programów, konieczne jest stworzenie mechanizmów wprowadzających dane do
funkcji i umożliwiających pobieranie wyników.
Po tych ogólnych informacjach omówimy teraz podstawowe zasady tworzenia funkcji.
Każdy plik definiujący funkcję musi na początku pierwszego wiersza zawierać deklara-
cję function (program pisze ją automatycznie niebieskim kolorem), a następnie zapis funkcji.
Oto prosty przykład definiowania funkcji liniowej y=ax+b:
function u=prosta(v,m,n)
u=m*v+n;
Instrukcje te piszemy w nowym otwartym oknie skryptów (biała kartka na pasku narzę-
dziowym). Następnie wciskamy przyciskamy File i wybieramy z listy poleceń Save As… Do
katalogu Work (lub własnego foldera w katalogu Work) wpisujemy nazwę pliku, która musi
być identyczna jak nazwa funkcji. Plik zawierający funkcję prosta będzie zatem nosił nazwę:
prosta.m.
Zapiszmy teraz w oknie Command Window następujące dwie instrukcje:
>> x=0:10;
>> y=prosta(x,2,3)
y=
3 5 7 9 11 13 15 17 19 21 23
Program zwrócił wartości funkcji y=2x+3. Zauważmy, że w powyższych instrukcjach
użyto innych nazw zmiennych niż w definicji funkcji prosta. Nie ma to znaczenia, gdyż w
zapisie funkcji liczą się wyłącznie pozycje zmiennych.
Dla sprawdzenia czy zmienna v występująca w funkcji jest widoczna poza nią na-
piszmy:
>> v
??? Undefined function or variable 'v'.
Widoczna jest natomiast zmienna globalna x:
>> x
x=
0 1 2 3 4 5 6 7 8 9 10
Można tworzyć funkcje, które mają kilka zmiennych, parametrów liczbowych lub łań-
cuchów. W podanym wyżej przykładzie mamy jedną zmienna i dwa parametry liczbowe.
Funkcja może zwracać także pewną liczbę wyników – zmiennych wyjściowych. Zapis funkcji
jest wtedy bardziej złożony. Pokazuje to zamieszczony wyżej przykład funkcji liniowej, uzu-
pełniony o wyznaczanie kąta nachylenia prostej. Funkcja realizująca te zadania ma następu-
jącą składnię:
function [u,p]=prosta(v,m,n)
u=m*v+n;
p=180*atan(m)/pi
Jeżeli w oknie Command Window napiszmy następujące dwie instrukcje, to otrzymamy:
36

>> x=0:10;
>> [y,nachylenie]=prosta(x,2,3)
y=
3 5 7 9 11 13 15 17 19 21 23
nachylenie =
63.4349
Nachylenie prostej wynosi 63.40.
W podanych wyżej przykładach wpisywaliśmy w instrukcji używającej funkcji t ę samą
liczbę zmiennych, która występowała w definicji funkcji. W niektórych funkcjach nie ma
nieraz potrzeby podawania wszystkich zmiennych występujących w instrukcji. Podobnie nie
zachodzi także zawsze potrzeba zwracania wszystkich zmiennych wyjściowych. Wprowa-
dzono dwie funkcje, które zwracają liczbę zmiennych wejściowych i wejściowych, co wyko-
rzystuje się w programie funkcji. Liczbę zmiennych wejściowych podaje funkcja nargin, zaś
liczbę zmiennych wyjściowych – funkcja nargout.
Argumentami funkcji mogą być liczby, pojedyncze litery lub łańcuchy znaków. Jak to
powiedziano wyżej użytkownik nie musi podawać wszystkich parametrów wejściowych i
wymagać wszystkich wyników. W takich sytuacjach w zapisie definiowanej funkcji poda-
jemy ogólne nazwy argumentów, a mianowicie varargin i varargout. Definicja funkcji ma wów-
czas następującą postać:
function varargout=prosta(varargin)
Częściej jednak stosuje się zapisy mieszane, np.:
function [y,varargout]=prosta(x,varargin)
Podane wyżej ogólne zapisy funkcji są używane przez zaawansowanych użytkowników
Programu MATLAB . Dlatego ograniczamy się do zasygnalizowania ich istnienia, a zainte-
resowanych szczegółami odsyłamy do podanej literatury lub MATLAB Help.
Jeżeli funkcja ma być dostępna tylko w tworzonym programie, można się posłużyć in-
nym sposobem jej definiowania, a mianowicie funkcją inline. Instrukcja inline odnosi się wy-
łącznie do funkcji opisanych wyrażeniami matematycznymi zawierającymi operacje i funkcje
istniejące w zbiorze programu MATLAB. Załóżmy, że chcemy zdefiniować funkcję
f=xsinx.
Funkcja ta nie występuje w zbiorze funkcji programu MATLAB, lecz zbudowana jest
z funkcji standardowych. Definiujemy ją jako:
>> f=inline('x.*sin(x)')
f=
Inline function:
f(x) = x.*sin(x)
Zauważmy, że formuła funkcji zapisana jest jako łańcuch. Zauważmy także, że w zapi-
sie funkcji obowiązują reguły wynikające z traktowania zmiennych jako macierzy. Dlatego
znak mnożenia poprzedzono kropką, gdyż bez niej znak mnożenia interpretowany byłby jako
mnożenie macierzy. Jeżeli z góry zakładamy, że x będzie wyłącznie liczbą, znak kropi nie niej
potrzebny.
Po zdefiniowaniu funkcji f=f(x) możemy wyznaczać jej wartości dla dowolnej liczby x
lub dla wektora x. Przykładowo:
>> f(pi/2)
ans =
1.5708
37

>> x=[1 2 3 4];


>> f(x)
ans =
0.8415 1.8186 0.4234 -3.0272
Instrukcją inline można definiować funkcje wielu zmiennych, np.
2 2
f=x +y
Odpowiednia instrukcja ma następującą postać
>> f=inline(‘x.^2+y.^2’)
Program zwraca zapis funkcji:
f=
Inline function:
f(x,y) = x.^2+y.^2
Zapis ten nie jest edytowany, jeżeli po definicji wstawimy średnik.
Może się wydawać, że nie ma różnicy między definiowaniem funkcji instrukcją inline, a
bezpośrednim zapisem wyrażenia matematycznego. Są to jednak pozory, gdyż różnice są bar-
dzo istotne. Pokażemy je na następującym przykładzie. Załóżmy, że w tej samej linii pew-
nego programu piszemy najpierw
>> f=inline(‘x.^2+y.^2’)
f=
Inline function:
f(x,y) = x.^2+y.^2
Jak widać program zaakceptował tę instrukcję, mimo, że wartości x i y są nieokreślone.
Napiszmy teraz
>> f=x.^2+y.^2
??? Undefined function or variable 'x'.
Program odrzuca powyższą instrukcję i podaje tego przyczynę: nie jest określona war-
tość zmiennej x. Zapis funkcji byłby prawidłowy, gdyby został poprzedzony podaniem warto-
ści x i y. Wynikiem byłaby liczba lub ciąg liczb, będących wartościami funkcji f dla podanych
wcześniej wartości x i y. Wartości funkcji f zdefiniowanej instrukcją inline można wyznaczyć
w dowolnej linii programu po definicji.

3.5.5. Pętle
Pętle używane są do wielokrotnego powtarzania określonych obliczeń lub mówiąc
ogólniej – poleceń. Przykładowa, prosta pętla ma następującą formę:
>> for n=1:10
y(n)=n^2;
end
Każda pętla rozpoczyna się poleceniem for i kończy poleceniem end. Dla wyróżnienia
od innych poleceń program MATLAB zapisuje je kolorem niebieskim. Zapis pętli należy
rozumieć następująco: dla każdej liczby naturalnej n od 1 do 10 wykonaj działanie zapisane
wzorem umieszczonym niżej, przed poleceniem end. W naszym przykładzie polecenie polega
na podniesieniu do kwadratu kolejnych liczb naturalnych i utworzeniu z nich wektora y.
Wektor ten jest zapisany w pamięci i może być edytowany poza pętlą:
>> y
y=
38

1 4 9 16 25 36 49 64 81 100
Jak wiemy, zapis n=1:10 generuje wektor liczb naturalnych. W pętlach można definio-
wać inne wektory, których elementy tworzą ciągi monotoniczne. Zmienna n nie może być
wtedy używana do wytwarzania wektorów lub macierzy, gdy ich elementy oznaczane są wy-
łącznie liczbami naturalnymi. Można temu zaradzić w sposób pokazany w następującym
przykładzie:
>> for x=-5:0.5:5
n=2*x+11;
y(n)=x^2;
end
>> y
y=
Columns 1 through 7
25.0000 20.2500 16.0000 12.2500 9.0000 6.2500 4.0000
Columns 8 through 14
2.2500 1.0000 0.2500 0 0.2500 1.0000 2.2500
Columns 15 through 21
4.0000 6.2500 9.0000 12.2500 16.0000 20.2500 25.0000
Alternatywnym rozwiązaniem są następujące instrukcje:
>> for n=1:11
x=-5+(n-1)/2;
y(n)=x^2;
end
Zapisując pętlę należy zawsze pamiętać o stawianiu średników po każdej instrukcji.
Skutki nie zastosowania się do tej rady pokazuje wykonanie obliczeń w pierwszej z podanych
pętli, gdy pominiemy średnik:
>> for n=1:10
y(n)=n^2
end
y=
1
y=
1 4
y=
1 4 9
y=
1 4 9 16
y=
1 4 9 16 25
y=
1 4 9 16 25 36
y=
1 4 9 16 25 36 49
y=
1 4 9 16 25 36 49 64
y=
1 4 9 16 25 36 49 64 81
y=
1 4 9 16 25 36 49 64 81 100
Program zwraca kolejno budowane wektory, co jest nie tylko zbędne, lecz dodatkowo
zajmuje wiele czasu.
Powyższy przykład ilustruje ponadto mechanizm obliczeń w pętli. W każdym cyklu
tworzony jest nowy wektor o coraz to większej długości. Wymaga to wykonania szeregu ope-
39

racji, które zajmują dużo czasu, nawet, gdy pośrednie wyniki nie są edytowane. Dlatego obli-
czenia w pętlach wykonywane są względnie długo. Jeżeli jest to tylko możliwe staramy się
unikać obliczeń w pętlach i zastąpić je obliczeniami macierzowymi. Przykładowo ostatnią
pętle można i należy zastąpić następującymi instrukcjami:
>> n=1:10;
>> y=n.^2
y=
1 4 9 16 25 36 49 64 81 100
Jeżeli zastosowania pętli nie można uniknąć wówczas przed pętlą należy zdefiniować
najprostszą macierz lub wektor, w których będziemy zapisywać wyniki obliczeń w pętli.
Wymiary macierzy bądź wektora muszą być zgodne z liczbą wyników w pętli. Rozpatrywany
wyżej przykład powinien być zgodnie z tym zapisany jako:
>> y=zeros(1,10);
>> for n=1:10
y(n)=n^2;
end
Mechanizm działania programu jest wówczas odmienny, co ilustruje przykład wykony-
wania obliczeń w tej pętli (pominięto średnik).
>> y=zeros(1,10);
>> for n=1:10
y(n)=n^2
end
y=
1 0 0 0 0 0 0 0 0 0
y=
1 4 0 0 0 0 0 0 0 0
y=
1 4 9 0 0 0 0 0 0 0
y=
1 4 9 16 0 0 0 0 0 0
y=
1 4 9 16 25 0 0 0 0 0
y=
1 4 9 16 25 36 0 0 0 0
y=
1 4 9 16 25 36 49 0 0 0
y=
1 4 9 16 25 36 49 64 0 0
y=
1 4 9 16 25 36 49 64 81 0
y=
1 4 9 16 25 36 49 64 81 100
Program wpisuje do istniejącego obszaru pamięci kolejne wyniki obliczeń, a nie tworzy
coraz to nowe obszary, jak to miało miejsce w poprzedniej wersji pętli. Czas potrzebny na
wpisywanie danych do określonego obszaru pamięci jest znacznie krótsze. Oczywiście róż-
nice w czasie wykonywania obu wersji pętli przy tak małej liczbie operacji są niezauważalne.
Cierpliwy Czytelnik może osobiście przekonać się o sensowności tych wskazówek zmieniając
liczbę 10 na 10000 i pisząc różne wersje zamieszczonych wyżej programów.
Odmianą opisanych pętli jest pętla rozpoczynająca się poleceniem while (dopóki).
Struktura takiej pętli jest podobna do poprzedniej, a mianowicie:
>> while <relacja logiczna>
<instrukcja>
40

end
Pętla ta nie ma określonej liczby cykli i instrukcja wykonuje się dopóki relacja logiczna
jest spełniona. Oto przykład wyznaczania kolejnych liczb naturalnych:
>> y=0;
>> while y<3
y=y+1
end
y=
1
y=
2
y=
3
W pierwszym wierszu zadeklarowana jest wartość początkowa. W drugim wierszu
sprawdzana jest relacja logiczna y<3. Relacja ta jest prawdziwa, dla y=0,1,2. W trzecim wier-
szu zwiększana jest zmienna y o 1. W pierwszym cyklu mamy y=0+1=1, w drugim y=1+1=2 a
w trzecim y=2+1=3. Pętla przestaje działać, gdyż y<3 nie jest prawdziwe.
Poniżej podano przykład prostego programu do wyznaczania wartości x, przy której
funkcja sinπx przyjmuje wartość maksymalną. Dokładność wyniku wynosi 0.00001.
>> d=0; x=0;
>> while d>=0
d=sin(pi*(x+0.00001))-sin(pi*x);
x=x+0.00001;
end
>> x
x=
0.5000
Takie samo zadanie może być wykonane przez inną pętlę z wykorzystaniem polecenia
break. Polecenie to kończy obliczenia w pętli przed ich zakończeniem wskazanym w instruk-
cji obok for. Polecenie break powinno być poprzedzone instrukcją warunkową.
>> for x=0:0.00001:1
d=sin(pi*(x+0.00001))-sin(pi*x);
if d<=0
break
end
end
>> x
x=
0.5000
Pętle są używane do tworzenia wektorów, co już pokazano, a również do budowania
macierzy i tablic wielowymiarowych. Takie pętle zawierają pętle zewnętrzne i wewnętrzne.
Struktura takiej złożonej pętli jest następująca:
for m=1:M
<instrukcja>
for n=1:N
<instrukcja>
end
end
Instrukcja w zewnętrznej linii pętli jest opcjonalna. Prosty przykład pętli generującej
macierz pokazuje następujący przykład:
>> y=zeros(5,6);
41

>> for m=1:5


x=m^2;
for n=1:6
Y(m,n)=x*log10(n);
end
end
>> Y
Y=
0 0.3010 0.4771 0.6021 0.6990 0.7782
0 1.2041 1.9085 2.4082 2.7959 3.1126
0 2.7093 4.2941 5.4185 6.2907 7.0034
0 4.8165 7.6339 9.6330 11.1835 12.4504
0 7.5257 11.9280 15.0515 17.4743 19.4538
Program ten wyznacza macierz o elementach Y(m,n)=m2log(n). Zauważmy, że pętla zo-
stała poprzedzona wytworzeniem macierzy zerowej o liczbie wierszy i kolumn, które są
zgodne z liczbą cykli w pętli. Jak to podkreślano wcześniej, zapewnia to znaczne przyspie-
szenie obliczeń. Wątpliwości może budzić instrukcja w drugiej linii pętli. Na pierwszy rzut
oka wydaje się ona zbędna , gdyż może być zastąpiona instrukcją w pętli wewnętrznej. Pro-
gram dający te same wyniki miałby wtedy następujący zapis:
>> for m=1:5
for n=1:6
Y(m,n)=m^2*log10(n);
end
end
Z punktu widzenia liczby operacji, tą druga wersja jest jednak gorsza. W pierwszej wer-
sji program wykonuje tylko 5 operacji podnoszenia liczby do potęgi 2, zaś w drugiej wersji 30
takich operacji. Przy tak małej liczbie operacji nie ma to oczywiście praktycznego znaczenia,
lecz przy dużych wymiarach macierzy i złożonych operacjach różnica może być duża. Należy
zatem budować pętle tak, aby minimalizować liczbę operacji.
Jak już wspomniano należy unikać stosowania macierzy, gdyż program MATLAB jest
zoptymalizowany pod katem obliczeń macierzowych. Przykładowo, pokazywana wyżej pętla
może być zastąpiona następującymi obliczeniami macierzowymi:
>> m=1:5;
>> a=m.^2;
>> n=1:6;
>> b=log10(n);
>> y=a’*b
0 0.3010 0.4771 0.6021 0.6990 0.7782
0 1.2041 1.9085 2.4082 2.7959 3.1126
0 2.7093 4.2941 5.4185 6.2907 7.0034
0 4.8165 7.6339 9.6330 11.1835 12.4504
0 7.5257 11.9280 15.0515 17.4743 19.4538
Pętle mogą być wykorzystywane do budowania tablic wielowymiarowych. Przykład
tworzenia tablicy trójwymiarowej ilustruje następujący przykład:
>> zeros(4,5,3)
>> for m=1:4
for n=1:5
for k=1:3
Y(m,n,k)=n+m+k;
end
end
end
>> y
42

Y(:,:,1) =
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
6 7 8 9 10
Y(:,:,2) =
4 5 6 7 8
5 6 7 8 9
6 7 8 9 10
7 8 9 10 11
Y(:,:,3) =
5 6 7 8 9
6 7 8 9 10
7 8 9 10 11
8 9 10 11 12
Tablica Y składa się z 3 macierzy o wymiarach 3x5. Wartość elementy tablicy jest sumą
numeru wiersza, kolumny i macierzy, co widoczne jest w podanym wyżej wydruku tablicy. Z
tablicy można utworzyć różne macierze po to, aby na nich wykonywać potrzebne operacje.
Mamy np.
>> A=Y(:,:,2)
A=
4 5 6 7 8
5 6 7 8 9
6 7 8 9 10
7 8 9 10 11
Macierz A jest macierzą o wymiarach:
>> size(A)
ans =
4 5
Niestety utworzenie macierzy, w której występują wiersze lub kolumny ze wszystkich
K tablic stwarza pewien problem. Pisząc bowiem:
>> B=Y(2,:,:)
B(:,:,1) =
4 5 6 7 8
B(:,:,2) =
5 6 7 8 9
B(:,:,3) =
6 7 8 9 10
otrzymujemy nadal tablicę o wymiarach
size(B)
ans =
1 5 3
Na tablicy B nie można wykonywać poznanych już operacji macierzowych. Zachodzi
więc potrzeba przekształcenia takiej tablicy w macierz. Można to uczynić wykorzystując na-
stępującą pętlę:
>> B=zeros(3,5);
>> for m=1:3
for n=1:5
B(m,n)=y(2,n,m);
end
end
>> B
B=
43

4 5 6 7 8
5 6 7 8 9
6 7 8 9 10
Rzeczywiście otrzymaliśmy macierz, gdyż
>> size(B)
ans =
3 5
Można do tego celu wykorzystać również funkcję reshape, która przekształca tablicę w
macierz o odpowiednich wymiarach. Składnię tej funkcji pokazuje przykład:
>> B=reshape(Y(2,:,:),3,5)
B=
4 7 6 9 8
5 8 7 6 9
6 5 8 7 10
a sprawdzamy jej skuteczność pisząc:
>> size(B)
ans =
3 5
44

4. GRAFIKA
4.1. Grafika dwuwymiarowa
4.1.1. Podstawowe funkcje graficzne
Z punktu widzenia obliczeń inżynierskich użyteczne jest szczególnie przedstawianie w
formie graficznej funkcji, wyników obliczeń i symulacji. Na ogół wystarcza do tego celu po-
sługiwanie się dwuwymiarowym układem współrzędny prostokątnych lub biegunowych. W
układach tych mogą być przedstawiane funkcje typu y=f(x) oraz płaskie figury geometryczne.
W programie MATLAB® mają one zwykle formę dwóch wektorów o równej długości, z któ-
rych jeden zawiera dyskretne wartości zmiennej niezależnej x, a drugi – dyskretne wartości
zmiennej zależnej y. Zajmiemy się najpierw graficzną reprezentacją tak rozumianych funkcji.
Do wykonywania wykresów we współrzędnych prostokątnych służą funkcję graficzne,
których podstawowy format jest następujący:
funkcja_graficzna(x,y,<parametry>)
Funkcja graficzna otwiera okno, w którym pojawi się wykres określony wektorem x,
wektorem y oraz parametrami. Parametry są opcjonalne i przy ich braku wykres wykonywany
jest przy parametrach domyślnych. Parametry umożliwiają wybór koloru wykresu, rodzaju
linii lub znaczników, z których jest wykonany. Lista tych parametrów jest długa i można je
znaleźć pisząc help plot. Przykładowy zapis funkcji graficznej wygląda następująco:
plot(x,y,’k*--‘);
gdzie parametry oznaczają: k –czarny kolor linii, * – oznaczenie punktów wykresu gwiazdką,
-- – wykres wykonany linią kreskową.
Format funkcji graficznych może być bardziej rozbudowany, ale ograniczymy się w
tym miejscu do formatu podstawowego.
Wektor wyznacza punkty na osi poziomej, którym przyporządkowane są elementy
wektora y. Inaczej mówiąc element wektora x(n) określa współrzędną x, a element y(n) –
współrzędną y punktu, przez którą przechodzi wykres. Charakterystyczną cechą grafiki pro-
gramu MATLAB® jest to, że elementy wektora x nie muszą być rozmieszczone równomier-
nie, a nawet nie muszą stanowić ciągu monotonicznego (rosnącego lub malejącego). Pominię-
cie w zapisie funkcji graficznej wektora x powoduje, że skalą x będzie ciąg liczb naturalnych
od 1 do N, gdzie N jest długością wektora y.
Jeżeli nie użyjemy specjalnych, dodatkowych funkcji graficznych, to zakres osi X i Y
program dobiera automatycznie.
Program MATLAB® oferuje następujące funkcje graficzne, których efektem jest wyko-
nanie wykresu. Są to:
 plot – wykonuje wykresy linią łamaną, przerywaną lub znacznikami, a linia ta
przechodzi prze punkty wyznaczone przez wektory x i y
 stem – wykonuje wykresy w formie próbek
 stairs – wykonuje wykresy w formie schodkowej
 bar – wykonuje wykresy w postaci słupków
 polar – sporządza wykresy we współrzędnych biegunowych
Ograniczymy się tu do opisu funkcji plot, stem i polar, gdyż pozostałe mają mniejsze
znaczenie w zastosowaniach inżynierskich.
45

Funkcja plot jest używana głównie do prezentacji graficznej funkcji ciągłych, chociaż z
konieczności są to w programie numerycznym funkcje dyskretne. Przykładowo, funkcja sinus
jest funkcją ciągłą, lecz program MATLAB® wyznacza jej wartości w skończonej liczbie
punktów i na wykresie łączy je odcinkami linii prostej. Przy malej liczbie punktów wykres
jest widoczny jako linia łamana, co fałszuje rzeczywisty przebieg funkcji. Zwiększając liczbę
punktów i zagęszczając je uzyskujemy pożądany efekt ciągłości, czyli zbliżamy obraz gra-
ficznych do rzeczywistego przebiegu funkcji. Ilustruje to przykład pokazany na rys. 4.1.

Rys. 4.1. Wykresy funkcji sinus przy rożnej gęstości punktów zmiennej niezależnej, sporządzony
przez funkcję plot.
Funkcji stem używamy do prezentacji graficznej funkcji dyskretnych, zwłaszcza wtedy
gdy chcemy uwypuklić ich dyskretny charakter. Jeżeli przykładowo analizujemy lub symulu-
jemy system cyfrowy wykorzystujący próbki sygnałów, to dobrze jest zaznaczyć graficznie,
że wyniki mają postać dyskretną, a zatem są dostępne tylko w ograniczonej liczbie punktów
zmiennej niezależnej (np. czasu). Przebieg funkcji sinus przedstawiony przy użyciu funkcji
stem ma postać przedstawioną na rys. 4.2.

Rys. 4.2. Wykres funkcji w formie próbek wykonany przy użyciu funkcji stem.
46

Funkcję polar stosujemy wtedy, gdy chcemy zaprezentować graficznie funkcję, której
zmienną niezależną jest kąt. Na rys. 4.3. pokazano wykres funkcji sin(3x)/(3x), gdzie x jest
kątem wyrażonym w radianach.

Rys. 4.3. Wykres funkcji we współrzędnych biegunowych wykonany przez funkcję polar.
Na jednym rysunku można zamieścić większa liczbę krzywych używając następującego
formatu funkcji plot:
plot(x,y,<parametry>,u,v,<parametry>,…)
Zmienne (x,y), (u,v) i dalsze opisują parami kolejne krzywe umieszczone na wykresie. Za
każdą parą zmiennych można wpisać (opcjonalnie) łańcuch znaków określających parametry
danej krzywej, np.’g+-‘, co oznacza krzywą narysowaną linią ciągłą w kolorze zielonym z
punktami zaznaczonymi plusem.
Jeżeli zmienna y jest zespolona, to zapis plot(y) powoduje rysowanie krzywej
plot(real(y),imag(y)), czyli na osi poziomej umieszczane są współrzędne części rzeczywistej
liczby zespolonej y, zaś na osi pionowej – współrzędne części urojonej liczby zespolonej z.
Jest to klasyczny sposób prezentacji graficznej liczb zespolonych. Każdy inny zapis funkcji
plot, np. plot(x,y), gdzie y jest liczbą zespoloną powoduje pominięcie części urojonych i wyko-
nywany jest wykres plot(x,real(y)).
Wykonany rysunek chcemy najczęściej przechować w pamięci. W tym celu w oknie Fi-
gure No. 1 (lub o wyższym numerze) otwieramy menu File i wybieramy w nim Save As... Po-
woduje to otwarcie okna, które umożliwia zapisanie rysunku w pożądanym folderze i nadanie
mu nazwy.
Rysunek wykonany w programie MATLAB można skopiować do innego programu,
np. do jednego programu z zestawu Microsoft Office. W tym celu w oknie rysunku wybieramy
Edit i z wywołanego menu Copy Figure. Możliwe jest również wybranie sposobu kopiowania
rysunku. W menu Edit wybieramy wówczas polecenie Copy Options, co powoduje rozwinięcie
okna Preferenses. W oknie tym należy wybrać Figure Copy Template i w oknie Figure Copy
Template Preferenses wybrać program, do którego będą kopiowane rysunki, a następnie usta-
wić pożądane parametry. Po rozwiniecie menu Figure Copy Template pojawi się menu Copy
Options. W tym oknie wybieramy metodę kopiowania np. Bitmap oraz kolor tła rysunku, np.
Force White Background. Czynności te kończymy wciskając przycisk Apply.
Podaną wyżej procedurę wykonuje się jednokrotnie i powtarza tylko wtedy, gdy chce-
my zmienić jakieś parametry rysowania i kopiowania.
47

Po instrukcji Copy Figure rysunek znajduje się w schowku i jest dostępny w innych pro-
gramach. Np. programie Microsoft Word można go umieścić w dokumencie rozwijając menu
Edycja, wybierając Wklej specjalnie... i – przykładowo – Mapa bitowa. (Nie należy przejmować
się zbytnio informacją, że rysunek jako mapa bitowa zajmuje dużo miejsca w pamięci, gdy
program Microsoft Word dokonuje samoczynnie kompresji danych potrzebnych do odtwo-
rzenia rysunku).
Aktywne okno rysunku zamyka się poleceniem close. Wszystkie otwarte okna zamyka
instrukcja close all. Instrukcje tę warto umieścić na początku programu aby rysunki nie poja-
wiały się we wcześniej otwartych oknach rysunkowych oraz żeby nie mnożyć otwartych
okien rysunkowych przy kolejnych uruchomieniach programu.

4.1.2. Funkcje formatujące rysunek


Ograniczenie się do napisania w programie samej podstawowej funkcji graficznej (np.
plot) powoduje otwarcie okna z rysunkiem, lecz forma rysunku może odbiegać od naszych
oczekiwań. Na rysunku ma bowiem naniesioną tylko skalę, a brakuje takich podstawowych
danych jak nazwy zmiennych lub tytułu rysunku. Zakres zmiennych, który został dobrany
automatycznie może nam również nie odpowiadać. Program MATLAB dysponuje szere-
giem funkcji, które umożliwiają wprowadzenie wspomnianych danych i wykonanie różno-
rodnych manipulacji formatujących rysunek. Funkcje te są zapisywane w programie i reali-
zują odpowiednie operacje graficzne po każdorazowym uruchomieniu programu. Jeżeli na-
szym celem jest jednorazowe wykonanie rysunku, to możemy odpowiednie operacje wykonać
bez wpisywania instrukcji w program, lecz posługując się odpowiednimi oknami przeznaczo-
nymi do wyboru funkcji i ich parametrów. Możliwe jest również stosowanie mieszanej tech-
niki: ustawianie podstawowych parametrów rysunku za pomocą instrukcji i wprowadzanie
dodatkowych zmian przy użyciu specjalnych okien. W pierwszej fazie poznawania program
MATLAB preferowana jest technika mieszana, gdyż liczba i struktura wszystkich potrzeb-
nych funkcji graficznych jest trudna do opanowania. Zważywszy na cel tego skryptu ograni-
czymy się do omówienia kilku najczęściej stosowanych funkcji oraz zaprezentujemy uprosz-
czony sposób modyfikacji rysunków za pomocą okien.
Rysunkowi nadajmy tytuł używając instrukcji:
title(‘nazwa rysunku’)
Instrukcję tę zamieszczamy za instrukcją plot, stem itp. Tekst ujęty w apostrofy pojawia
się nad rysunkiem.
Zakres osi poziomej X i osi pionowej Y dobieramy używając następującej instrukcji:
axis([Xmin Xmax Ymin Ymax])
gdzie Xmin jest liczbą określającą punkt przecięcia osi X z osią Y, Xmax jest maksymalną
wartością na osi X, Ymin jest liczbą określającą punkt przecięcia osi Y z osią X, zaś Ymax jest
maksymalną wartością na osi Y.
Wpisując w oknie Command Window instrukcję help axis można znaleźć wykaz poleceń
związanych z ustawieniem osi wykresu.
Funkcja xlabel służy do opisu osi X. Ma ona następującą formę:
xlabel(‘nazwa zmiennej’)
W analogiczny sposób opisujemy oś Y:
ylabel(‘nazwa zmiennej’)
48

Jeżeli na rysunku znajduje się większa liczba krzywych narysowanych różnym rodza-
jem linii lub różnym kolorem, wówczas przydatna jest legenda opisująca poszczególne
krzywe. Wykorzystuje się do tego celu następującą funkcję:
legend(‘nazwa pierwszej krzywej’, ’nazwa drugiej krzywej’, …,p)
gdzie p jest liczbą od -1 do 4 określającą położenie legendy na rysunku (domyślnie ustawione
jest 0, które umieszcza legendę w prawym górnym rogu).
Do opisu krzywych służy instrukcja funkcja text, której argumentami są pozycja tekstu i
łańcuch zawierający tekst:
text(xt,yt,’tekst’)
Współrzędne xt,yt odnoszą się do skal występujących na rysunku. Kilkukrotne użycie
funkcji text umożliwia naniesienie na rysunku w różnych miejscach dowolnych tekstów (naj-
częściej opisów krzywych).
Przy dużym zakresie zmiennych wygodnie jest sporządzać wykresy w skali logaryt-
micznej. Służą do tego celu trzy funkcje, którymi zastępujemy funkcję plot zachowując w
pełni jej format. Są to:
 loglog(…) – obie osi w skali logarytmicznej o odstawie 10,
 semilogx(…) – oś X w skali logarytmicznej, oś Y w skali liniowej
 semilogy(…) – oś X w skali liniowej, oś Y w skali logarytmicznej.
Polecenie grid powoduje pojawienie się na rysunku siatki. Linie siatki występują w
punktach osi X i Y, które są opisane liczbami. Polecenie grid minor zagęszcza siatkę, a grid off
powoduje jej zniknięcie.

4.1.3. Tworzenie wielu rysunków


Wyniki obliczeń rzadko kiedy mogą być pokazane na jednym rysunku. Zachodzi zatem
potrzeba przy pisaniu programu stosowania instrukcji umożliwiających tworzenie kilku ry-
sunków. Możliwe są trze sytuacje:
 umieszczanie wykresów na oddzielnych rysunkach
 umieszczanie na wspólnym rysunku kilku wykresów z zachowaniem wspólnego
układu współrzędnych
 umieszczanie na jednym rysunku kilku układów współrzędnych
Pierwsza, najprostsza sytuacja, to tworzenie kilku oddzielnych rysunków. Nowy rysu-
nek powstaje w nowym oknie po wpisaniu polecenia figure. Przykładowy ciąg instrukcji po-
wodujących sporządzenie dwóch rysunków wygląda następująco:
plot(x,y,<parametry>)
title(‘pierwszy rysunek’);
axis([...]);
xlabel(‘X’);
ylabel(‘Y’);
<instrukcje>
figure
stem(u,v,<parametry>)
title(‘drugi rysunek’);
axis([...]);
xlabel(‘U’);
ylabel(‘V’);
49

Funkcja plot otwiera pierwsze okno rysunkowe i łącznie z kolejnymi funkcjami powo-
duje wykonanie pożądanego wykresu. Polecenie figure otwiera drugie okno i w nim sporzą-
dzany jest rysunek według funkcji stem (lub innej) i dodatkowych, znajdujących się poniżej
instrukcji. W ten sam sposób można otwierać kolejne okna rysunkowe, które otrzymują ko-
lejne numery. Jeżeli funkcja plot, stem lub inne tego typu nie są poprzedzone poleceniem fig-
ure, to rysunek będzie wykonany w ostatnim otwartym oknie. Poprzedni rysunek będzie au-
tomatycznie usunięty.
Kolejnym rysunkom należy przypisać nazwę, jeżeli chcemy je zapamiętać. Sposób za-
pamiętywania rysunków podano wyżej.
Pierwszy sposób umieszczania na wspólnym rysunku kilku krzywych polega na omó-
wionym wyżej wykorzystaniu funkcji plot z wieloma argumentami. Druga metoda wykorzy-
stuje polecenie hold on. Umieszczenie tego polecenia w programie (lub w oknie Command
Window) po pojawieniu się okna rysunkowego powoduje, że kolejne rysunki będą nakładane
na istniejący. Oto przykład krótkiego programu rysującego dwie funkcje zmiennej zespolonej,
a mianowicie y=exp(j2x) oraz z=xexp(j2x).
x=0:0.001:1;
y=exp(i*2*pi*x);
plot(y,'k')
axis square
title('Funkcje zmiennej zespolonej')
xlabel('Re');ylabel('Im')
set(gcf,'color','white')
grid
z=x.*y;
hold on
plot(z,'k:')
legend('y','z')
Po uruchomieniu programu otrzymujemy wykresy pokazane na rys. 4.4.

Rys. 4.4. Wykresy funkcji zmiennej zespolonej.


W przedstawionym wyżej programie występują dwie instrukcje, których dotąd nie
omawialiśmy. Instrukcja axis square zamienia zwykły format rysunku na kwadratowy. W
zwykłym formacie skale osi X i Y są różne, w wyniku czego figury geometryczne ulegają
zniekształceniu. Aby tego uniknąć i pokazać, że funkcja exp(jx) ma kształt okręgu, wyrów-
nano skale obu osi.
50

Funkcja set(…) zmieniła tło obrzeża rysunku na biały; domyślnie jest obrzeże ma kolor
szary, co w tekście nie jest raczej korzystne. Funkcja set ma szerokie zastosowanie w grafice
programy MATLAB® i jej omówieniem zajmiemy się w dalszej części skryptu.
W jednym rysunku można umieścić kilka układów współrzędnych i wykreślić w każ-
dym z tych układów pewną liczbę krzywych. Służy do tego celu funkcja subplot, która w pod-
stawowym formacie ma trzy parametry:
subplot(m,n,p).
Parametr m wskazuje, w ilu wierszach maja być utworzone rysunku, a parametr n – w
ilu kolumnach. Liczba pól przeznaczonych na rysunki wynosi zatem m·n. Nie w każdym polu
musi być zamieszczony rysunek. Parametr p wskazuje, w którym polu ma znajdować się
określony rysunek. Rysunki są wykonywane według zasad obowiązujących dla pojedynczego
rysunku. Wybierając liczbę rysunków należy pamiętać, że ze zwiększaniem tej liczby maleje
powierzchnia przeznaczona na każdy z rysunków, co czyni je mniej czytelnymi. Poniżej
przedstawiono program sporządzający trzy rysunki w jednym oknie figure.
x=2*pi*(0:0.001:1);
ys=sin(x);
subplot(2,2,1); plot(x,ys)
title('sinus');xlabel('x');ylabel('ys')
axis([0 2*pi -1 1])
yc=cos(x);
subplot(2,2,2); plot(x,yc)
title('cosinus');xlabel('x');ylabel('yc');
axis([0 2*pi -1 1])
yt=tan(x);
subplot(2,2,3); plot(x,yt)
title('tangens');xlabel('x');ylabel('yt')
axis([0 2*pi -10 10])
Powyższy programu sporządza rysunek pokazany na rys. 4.5.

Rys. 4.5. Trzy wykresy funkcji umieszczone na jednym rysunku przy użyciu funkcji subplot.
51

Pola rysunkowe znajdują się w dwóch rzędach i dwóch kolumnach. Wykorzystano z


nich trzy pola i umieszczono w nich trzy wykresy funkcji trygonometrycznych. Czwarty ry-
sunek można umieścić pisząc następującą instrukcję:
subplot(2,2,4);plot(…)

4.1.4. Dobór parametrów rysunku bez użycia instrukcji graficznych


Wspomniano już, że parametry rysunku można dobierać używając instrukcji zapisanych
programie, lub posługując się oknami rozwijanymi w wyniku wybraniu odpowiednich etykiet
z paska narzędziowego rysunku. Powtórzmy, że to drugie rozwiązanie, chociaż prostsze, po-
winno być stosowane do formatowania pojedynczych, nie powtarzających się rysunków.
Jeżeli w wyniku wykonania instrukcji plot, stem itp. pojawi się rysunek, którego wygląd
nie jest zadawalający, wówczas z paska narzędziowego tego rysunku wybieramy Edit i poja-
wia się okno zawierające m.in. trzy ważne etykiety, a mianowicie: Figure Properties..., Axes
Properties..., Current Object Properties...
Po wybraniu Figure Properties pojawia się okno Property Editor- Figure. W pierwszym
okienku Edit Properties for: widoczny jest tekst figure: 1 (lub inny numer otwartego rysunku).
Znajdujące się niżej okienka służą do ustawienia parametrów odnoszących się do całego ry-
sunku. Zazwyczaj ograniczamy się do zmiany koloru tła i nadania oknu nazwy. Nazwę wpi-
sujemy w okno Window Name:. Nie będzie ona widoczna nigdzie poza oknem rysunkowym i
paskiem zadań w programie Windows (wpisuje się ją wyłącznie dla wygody programisty).
Kolor tła wybieramy po rozwinięciu okna Color (najczęściej wybieramy White).
Po rozwinięciu okna Edit Properties for: pojawia się lista obiektów, z których zbudowany
jest rysunek. Im bardziej skomplikowany jest rysunek, tym obiektów jest więcej. Co najmniej
są to dwa obiekty: axes: i line:. Obiekt axes dotyczy osi współrzędnych, zaś obiekt line – linii
wykresu. Jeżeli na rysunku występuję większa liczba osi współrzędnych (co jest możliwe,
lecz rzadko stosowane), lub większa liczba linii wykresów, to są one kolejno ponumerowane.
Wybranie obiektu axes powoduje otwarcie okna z nagłówkiem Property Editor – Axes.
które pokazano na rys. 4.6. Takie samo okno pojawia się po wybraniu z menu Axes Properties
Korzystając z tego okna można ustawić wszystkie pożądane parametry rysunku zwią-
zane z układem współrzędnych. Wybierając kolejni X, Y, a w rysunkach trójwymiarowych
również Z wpisuje my nazwę zmiennej x (Label:) i dobieramy w razie potrzeby właściwe pa-
rametry tego podpisu otwierając okno Properties.... W oknie tym, posiadającym nagłówek
Property Editor – Text można zmienić wysokość czcionki, jej grubości, styl a także położenie
oznaczenia osi X. Położenie zmieniamy w okienku Position:
Domyślnie oznaczenie osi Y występuje w środku tej osi i jest napisane w kierunku pio-
nowy. Można to zmienić wykorzystując okienko Rotation: i wybierając w nim 0.0 i następnie
przesuwając oznaczenie do góry i ewentualnie w bok w okienku Position....
W okienku Limits: po usunięciu oznaczenia Auto uzyskujemy możliwość wpisania za-
kresu osi X. Jest to równoważne instrukcji axis([Xmin X max ...]). W okienku Ticks: w trybie
ręcznym można wpisywać położenie znaczników na osi X, zaś w okienku Labels: – oznacze-
nia znaczników.
W omawianym oknie można także ustawić pożądaną skalę wykresu, co odpowiada in-
strukcjom semilogx, loglog itp.
Jeżeli w oknie Property Editor- Figure w górnym okienku wybierzemy line:, wówczas po-
jawia się okno Property Edition – Line, pokazane na rys. 4.7.
52

Rys. 4.6. Okno do ustawiania parametrów osi rysunku.

Rys. 4.7. Okno do ustawiania parametrów linii.


53

W oknie tym istotne znacznie ma rozwinięcie etykiety Style, widoczne na rysunku. Do-
bieramy w nim styl linii, jej grubość i kolor. Linie można uzupełnić znacznikami (Marker Pro-
perties), których lista znajduje się w okienku Style: Po wybraniu znacznika dobieramy jego
rozmiar (Size:), kolor obramowania (Edge color:) oraz kolor wypełnienia (Face color:). Efekty
wyboru pokazywane są automatycznie w okienku Example.
Jeżeli na rysunku zaznaczymy lewym klawiszem myszy najpierw strzałkę w na pasku
narzędziowym, a potem wybrany obiekt (np. linię wykresu) i wybierzemy z menu Edit pole-
cenie Current Object Properties..., to otworzy się odpowiednie okno dotyczące tego obiektu. Są
to te same okna, które omówiliśmy wyżej.
Inny sposób zmieniania właściwości rysunku polega na użyciu myszki. Jeżeli po na-
prowadzeniu wskaźnika myszki wciśniemy jej lewy klawisz, to wybrany obiekt zostanie za-
znaczony. Po wciśnięciu prawego klawisza pojawia się okienko z listą funkcji i parametrów
właściwych dla danego obiektu. Wybranie Properties... powoduje otwarcie stosownego okna i
dalsze postępowanie nie różni się od opisanego wyżej. Dodatkowo z okna można wybrać:
 Cut– usuwa wszystkie elementy rysunku i przechowuje je w schowku, z którego
mogą być odtworzone po wciśnięciu Paste
 Copy – zachowuje element w schowku w celu jego ponownego użycia
 Paste – umieszcza element znajdujący się w schowku na rysunku
 Clear – usuwa zaznaczony obiekt z rysunku
W zależności od rodzaju zaznaczonego obiektu w oknie pojawia się lista parametrów,
których wartości można zmieniać z pominięciem okna otwieranego przez Properties. Np. w
wypadku linii można zmieniać jej grubość, styl i kolor.
W pasku narzędziowym znajduje się ikona oznaczona jako A, która służy do pisania
tekstu na rysunku. Po wciśnięciu tej ikony (jej tło staje się białe) naprowadzamy wskaźnik
myszy na miejsce, w którym ma być umieszczony tekst, a następnie przyciskamy lewy kla-
wisz myszy. Na pojawiającym się wtedy szarym prostokącie wpisujemy tekst. Formatowanie
tekstu odbywa się tak samo jak formatowanie innych elementów rysunku.
Na pasku narzędziowym rysunku znajdują się także inne ikony, które służą do rysowa-
nia strzałek, linii prostych oraz do powiększania, zmniejszania i obracania wybranych frag-
mentów rysunku. Po przyciśnięciu ikony rysowania strzałki na polu rysunkowym pojawia się
krzyżyk, który ustawiamy myszą w pozycji początku strzałki i po przyciśnięciu lewego klawi-
sza przeciągamy krzyżyk do pozycji końcowej (grot strzałki). Analogicznie rysuje się linie
proste.
Po wciśnięciu ikony powiększenia (oznaczoną +) naprowadzamy kursor myszy na kra-
niec obszaru rysunku, który ma być powiększony. Przeciągając następnie kursor do drugiego
krańca tego obszaru zaznaczamy pole rysunku ulegające powiększeniu. W momencie pusz-
czenia klawisza myszy zaznaczony fragment rysunku zajmuje całą przestrzeń między osiami.
Zmniejszenie powiększonego fragmentu rysunku uzyskuje się po wciśnięciu ikony oznaczo-
nej jako – , naprowadzeniu kursora myszy na pole rysunku i przyciskanie lewym klawiszem
myszy do czasu uzyskania pożądanego rozmiaru rysunku.
Obracanie rysunku jest wykorzystywane w grafice trójwymiarowej.
54

4.2. Grafika trójwymiarowa


Program MATLAB® dysponuje bardzo rozbudowanymi narzędziami do tworzenia ob-
razów trójwymiarowych (patrz Help 3-D Visualization). Nie sposób w skrypcie o rozsądnej ob-
jętości omówić wszystkie możliwości programu w tej dziedzinie. Szczęśliwie, do celów obli-
czeń inżynierskich wystarcza stosowanie podstawowych funkcji grafiki trójwymiarowej i te
przedstawimy w tym podrozdziale.
W celu uporządkowania prezentacji rozpatrzymy kolejno trzy przypadki, a mianowicie:
 wizualizację funkcji zapisanej trzema wektorami
 wizualizację funkcji zapisanej dwoma wektorami i macierzą
 wizualizację powierzchni zapisanej trzema macierzami
Dwa pierwsze przypadki dotyczą funkcji dwóch zmiennych, które – zgodnie z definicją
– przyporządkowują jednoznacznie zmiennym niezależnym jedną i tylko jedną wartość
zmiennej zależnej. Trzeci przypadek dotyczy obok funkcji dwóch zmiennych także po-
wierzchni, które nie są obrazami funkcji. Mogą to być figury geometryczne w rodzaju kuli,
sześcianu itp.

4.2.1. Linie w przestrzeni trójwymiarowej


Poznana wcześniej instrukcja plot ma wersję trójwymiarową plot3. Instrukcja ta umożli-
wia wyznaczanie obrazu linii w przestrzeni trójwymiarowej. Linia jest zapisana przy użyciu
trzech wektorów x,y,z o tej samej długości. Ogólny zapis tej instrukcji ma następującą postać:
plot3(x,y,z,...)
Zmienne x,y,z opisują linię w układzie trzech współrzędnych prostokątnych. W miejsce
kropek można wpisać parametry formatujące linię – w ten sam sposób, jak w funkcji plot.
Możliwe jest również zobrazowanie większej liczby krzywych, a wtedy instrukcja wygląda
następująco:
plot3(x1,y1,z1,...,x2,y2,z2,....,x3,y3,z3,...)
W miejsce kropek wpisujemy parametry danej krzywej.
Jako przykład wykorzystania instrukcji plot3 przedstawimy krótki program wyznacza-
jący dwie spirale przestrzenne.
t=0:pi/100:10*pi;
x1=t.*cos(t);
y1=t.*sin(t);
z1=t;
x2=t.*cos(2*t);
y2=t.*sin(2*t);
z2=t;
plot3(x1,y1,z1,'g',x2,y2,z2)
xlabel('x');ylabel('y');zlabel('z'); %oznaczenia osi
title('spirala') %tytuł
grid on %wstawienie siatki
Wynikiem działania programu są wykresy pokazane na rys.4.8. Rysunek nieznacznie
przeformatowano używając okien Figure Properties, Axes Properties.
55

Rys.4.8. Przestrzenny wykres spiral.

4.2.2. Tworzenie obrazów funkcji dwóch zmiennych


Obrazem funkcji dwóch zmiennych x,y jest powierzchnia, którą tworzą punkty x,y,z
spełniające ogólną zależność
z=f(x,y).
W programie do obliczeń numerycznych jakim jest MATLAB®, zmienne x,y i z są
zmiennymi dyskretnymi, a zatem powierzchnia określona jest tylko w skończonej liczbie
punktów. We współrzędnych prostokątnych zmienne x i y wyznaczają współrzędne punktu na
płaszczyźnie X,Y, a z jest współrzędną wartości funkcji w tym punkcie, czyli wysokością
punktu płaszczyzny względem płaszczyzny X,Y. W nomenklaturze programy MATLAB®,
zmienne x i y tworzą wektory, zaś zmienna z tworzy macierz Z. Wartości elementów tej ma-
cierzy są wyznaczają poszukiwaną powierzchnię, będącą graficzną reprezentacją dyskretnej
funkcji z=f(x,y).
Obraz graficzny funkcji dwóch zmiennych otrzymujemy wykorzystując instrukcje surf
lub mesh. Instrukcja surf daje obraz powierzchni uzyskanej przy użyciu kolorów, których
barwa jest uzależniona od wartości współrzędnej z dla danego punktu x,y. Dodatkowo na po-
wierzchnię naniesiona jest siatka, która łączy wyznaczone punkty tej powierzchni. Instrukcja
mesh tworzy obraz powierzchni za pomocą kolorowej siatki łączącej wyznaczone punkty tej
powierzchni. Pola wewnątrz siatki są białe. Poza tym obie instrukcje funkcjonują podobnie,
chociaż możliwości formatowania rysunku są znacznie większe w odniesieniu do instrukcji
surf.
Sytuacja jest najprostsza, gdy macierz Z(m,n) jest wyznaczona dla wektorów x(n) i y(m)
tworzących równomierną siatkę na płaszczyźnie X,Y. Wówczas położenie punktów płaszczy-
zny jest tożsame z odpowiednimi wierszami i kolumnami macierzy Z. Reguła jest następu-
jąca: wartości w wierszach oznaczają współrzędną x(n), zaś wartości w kolumnach – współ-
rzędną y(m). Obraz funkcji Z(m,n) we współrzędnych prostokątnych otrzymamy pisząc nastę-
pujące instrukcje:
56

surf(Z) lub mesh(Z)


Poniżej pokażemy w surowej wersji obraz graficzny dwuwymiarowej funkcji Gaussa o
następującej postaci:
1
e ( x  y 2 / 4) / 2
2
Z( x, y ) 
2 2

Oto program wyznaczający obrazy graficzne tej funkcji:


x=-4.8:0.2:5;
fx=exp(-x.^2/2);
fy=exp(-x.^2/8)’;
Z=(fy*fx)/(4*pi);
surf(Z)
axis([1 50 1 50 0 0.08])
figure
mesh(Z)
axis([1 50 1 50 0 0.08])
Dwuwymiarową funkcję Gaussa przedstawiono w formie iloczynu dwóch wektorów fx i
fy,przy czym wektor fy jest wektorem kolumnowym. Iloczyn takich dwóch wektorów jest
macierzą, której elementami są iloczyny odpowiednich elementów wektorów. Uniknęliśmy w
ten sposób stosowania obliczeń w pętlach.

Rys. 4.9. Powierzchnie na obu rysunkach wytworzone zostały z 50 wierszy i kolumn


macierzy Z.
Na przedstawionych wykresach współrzędne x i y zostały zastąpione numerami wierszy
i kolumn macierzy Z. Jeżeli skale wykresów chcemy pokazać w sposób jawny, wtedy uży-
wamy instrukcji:
surf(x,y,Z) lub mesh(x,y,Z)
Trójwymiarowy obraz funkcji Gaussa wykonany instrukcją surf.
57

Rys. 4.10. Trójwymiarowy obraz funkcji Gaussa wykonany instrukcją mesh.


Na rysunkach można wprowadzić dodatkowe opisy używając instrukcji xlabel, ylabel,
zlabel i title
Zauważmy, że na obu wykresach najniższym wartościom funkcji przypisany jest kolor
granatowy, następnie niebieski, zielony, żółty, aż po kolor ciemno czerwony, który jest przy-
porządkowany najwyższym wartościom funkcji. Jeżeli instrukcja jest zapisana w sposób
podany w przykładach, to skala kolorów jest dobierana automatycznie.

4.2.3. Dobór kolorów


Skalę kolorów można dobierać według własnych potrzeb wykorzystując instrukcje co-
lormap i caxis. Sposób dobierania kolorów poprzedzimy krótkim opisem zasady tworzenia i
zapisywania skali kolorów w programie MATLAB®. Kolory używane na rysunku zapisywane
są w formie macierzy zbudowanej z trzech kolumn i pewnej liczby wierszy. Domyślnie liczba
wierszy wynosi 64 i każdemu wierszowi odpowiada jeden kolor. Barwa zależy od liczb
umieszczonych w danym wierszu. Liczby te zawierają się w przedziale od 0 do 1 i opisują
intensywność podstawowych trzech kolorów (RGB), których suma daje odpowiednią barwę.
W pierwszej kolumnie zapisana jest intensywność koloru czerwonego, w drogiej zielonego, a
w trzeciej niebieskiego. Na analogicznej zasadzie tworzone są np. kolory w telewizji. Wiersz
zawierający 1 1 1 daje kolor biały, 0 0 0 – czarny, 1 0 0 – czerwony, 0 1 0 – zielony, 0 0 1 –
niebieski. Wiersz zawierający np. 0.5 0.2 0.7 oznacza kolor składający się z
0.5R+0.2G+0.7B.
Wpisanie instrukcji
colormap
zwraca opisaną wyżej macierz odnoszącą się do aktualnego rysunku. Jeżeli macierz ta jest
potrzebna w programie, wówczas piszemy:
Cm=colormap
Macierz Cm jest zapamiętana i można dokonywać jej modyfikacji, których skutkiem są
zmiany kolorów. Można przykładowo zmieniać liczbę wierszy, wycinać niektóre wiersze itp.
58

Jeżeli taką zmodyfikowaną macierz Cmm wstawimy jako argument funkcji colormap, to
zmieni się skala kolorów:
colormap(Cmm)
Można również w razie potrzeby skonstruować własną macierz Cm, zachowując wszak-
że jej strukturę, czyli liczbę kolumn równą 3.
Efekty wprowadzonych zmian można zobrazować używając instrukcji colorbar. Na ak-
tywnym rysunku (lub nowym, gdy nie ma rysunku) pojawia się pionowy słupek z naniesioną
aktualną paletą barw.
Program MATLAB® dysponuje szeregiem standardowych palet barw, które mogą być
użyte na rysunku. W celu wybrania odpowiedniej palety barw piszemy następujące instrukcje:
 colormap jet – domyślna paleta barw używana na zamieszczonych wyżej rysunkach
 colormap hot – ciepłe kolory od czarnego, poprzez czerwony do białego
 colormap cool – zimne barwy od zielonego, poprzez niebieski do fioletowego
 colormap gray – skala szarości
 colormap(‘default’) – przywraca domyślną paletę barw
Poza wymienionymi można użyć także: autumn, bone, colortube, cooper, flag, hsv, pink,
prism, spring, summer i winter.
Każda tak zapisana paleta zawiera 64 kolory. Liczbę kolorów można zmniejszyć lub
zwiększyć w ramach danej palety pisząc np.
jet(10) lub hot(100).
Standardowa paleta zawiera teraz tylko 10 kolorów, a paleta hot - 100 kolorów. Powyż-
sze instrukcje można zapisać również w zwartej formie, jak np.:
colormap(hot(100))
Zmian palety kolorów można dokonywać ręcznie otwierając menu Edit, a w nim Color-
map… Otwiera się wtedy okno Colormap Editor, w którym można wybrać pożądaną paletę
barw. Należy jednak pamiętać, że ustawienia palety uzyskane tą metodą odnoszą się wyłącz-
nie do aktywnego rysunku. Preferowane jest ustawienie palet programowo, gdyż efekt jest
wtedy powtarzalny. Pożyteczne jest wykorzystywania okna Colormap Editor do eksperymen-
talnego doboru palety. Pisząc po wybraniu palety w Command Window instrukcję Cm=colormap
otrzymujemy macierz, którą można wykorzystać w programie.
Paleta barw jest wykorzystywana w ten sposób, że program MATLAB® automatycznie
przypisuje najniższy kolor z palety barw do najmniejszej wartości macierzy Z, a najwyższy
kolor – do największej wartości tej macierzy. Można jednak tę zasadę zmienić używając in-
strukcji caxis. Jest ona podobna do instrukcji axis, która ustala zakres skali wykresu. Składnia
tej funkcji ma postać:
caxis([cmin cmax])
gdzie cmin oznacza najmniejszą wartość macierzy Z, do której przypisany jest najniższy kolor
aktualnej palety barw zaś cmax – najwyższą wartość, do której jest przypasany najwyższy
kolor. Jeżeli zakres wartości macierzy Z zawarty jest w granicach cmin do cmax, to do wyko-
nania wykresu użyta zostanie tylko odpowiednia część pełnej palety barw. W przeciwnym
wypadku wartości macierzy Z mniejsze od cmin oznaczone zostaną kolorem odpowiadającym
cmin, a przekraczające cmax – kolorem przypisanym do cmax.
59

Aktualne wartości cmin i cmax można wyznaczyć następująco:


[cmin,cmax]=caxis
Instrukcja caxis auto cmin i cmax na granicach pełnej paletę barw, zaś instrukcja caxis ma-
nual – zachowuje granice palety barw, gdy na jednym rysunku umieszcza się więcej wykre-
sów, stosując polecenie hold on.
Wykorzystując omówione instrukcje dokonamy modyfikacji wykresu przedstawionego
na rys. 4. W tym celu zmienimy i uzupełnimy kod podany na wstępie tego punktu.
x=-5:0.2:5;
y=x;
fx=exp(-x.^2/2);
fy=exp(-y.^2/8)';
Z=(fy*fx)/(4*pi);
surf(x,y,Z)
axis([-5 5 -5 5 0 0.08])
colormap(cool(32))
caxis([0.01 0.1])
colorbar
Zmin=min(min(Z))
Zmax=max(max(Z))

Program zwraca wartość minimalną i maksymalną macierzy Z


Zmin =
1.3030e-008
Zmax =
0.0796
oraz sporządza wykres pokazany na rys. 4.11.

Rys. 4.11. Trójwymiarowy obraz funkcji Gaussa wykonany przy użyciu instrukcji surf, colormap,
caxis i colorbar.

Na pionowym pasku widoczna jest pełna paleta barw w tonacji zimnej (cool). Składa się
ona z 32 kolorów. Ponieważ Zmin<cmin, więc obszar powierzchni o wartościach mniejszych
60

od cmin=0.01 jest oznaczony najniższym kolorem z palety barw. Z drugiej strony Zmax<cmax,
a zatem nie jest wykorzystana pełna paleta barw.

4.2.4. Ustawianie położenia układu współrzędnych


Na rysunku widoczny jest rzut prostopadły układu współrzędnych, wyznaczonego w
przestrzeni przez osie X,Y,Z na płaszczyznę rysunku. Kształt powierzchni przedstawianej
funkcji zależy od samej funkcji, lecz także od usytuowania układu współrzędnych względem
powierzchni rysunku. Nie zawsze usytuowanie to jest wygodne, gdyż część powierzchni
funkcji jest przesłaniana przez inne jej fragmenty. W takiej sytuacji pożądana jest możliwość
zmiany położenia układu współrzędnych względem płaszczyzny rysunku, lub – inaczej mó-
wiąc – względem obserwatora. Oko obserwatora (ang. viewpoint), zgodnie z zasadami rzutu
prostopadłego znajduje się (teoretycznie) na prostej prostopadłej do powierzchni rysunku i
przechodzącej przez środek układu współrzędnych. Kąty między ową prostą, a osiami układu
współrzędnych opisują położenie tego układu względem powierzchni rysunku.
W programie MATLAB® używa się kątów azymutu i elewacji, które pokazano na rys.
4.12.

Z
Y

X
elewacja

azymut

Rys. 4.12. Usytuowanie układu współrzędnych względem obserwatora.

Standardowo, kąt azymutu wynosi –37.50, a kąt elewacji +300 i przy tak położonym
układzie współrzędnych wykonane są wszystkie, zamieszczone wyżej, rysunki.
Ustawienie układu współrzędnych zmienia instrukcja:
view(az,el) lub view([az,el])
gdzie az oznacza kąt azymutu (w stopniach), a el – kąt elewacji.
Położenie prostej, na której leży punkt obserwacji można również ustawić podając
współrzędne jednego z punktów prostej x,y,z:
view([x,y,z])
Instrukcja view(2) ustawia obserwatora na osi Z i uzyskujemy dwuwymiarowy obraz
przestrzeni, zaś instrukcja view(3) ustawia układ współrzędnych w standardowej pozycji.
61

Na pasku narzędziowym okna Figure znajduje się ikona w kształcie okręgu, która służy
do ręcznej zmiany położenia układu współrzędnych. Po wciśnięciu przycisku z tą ikoną na-
leży naprowadzić znacznik myszy na pole obrazu i - trzymając wciśnięty lewy klawisz –
przesuwać znacznik do momentu uzyskania pożądanego położenia układu współrzędnych.
Położenie obserwatora przy istniejącym ustawieniu układu współrzędnych można wyznaczyć
zapisując następującą funkcję:
[az,el]=view
Wartości te można wykorzystać w pisanym programie do pożądanego, niestandardo-
wego ustawienia układu współrzędnych.
Program MATLAB® dysponuje bardzo rozbudowanym zestawem narzędzi służących do
ustawiania położenia obserwatora względem układu współrzędnych, a także do ciągłej zmia-
ny tego położenia. Efekty działania tych narzędzi są podobne do funkcjonowania kamery fo-
tograficznej i filmowej. Nie ma tu miejsca na omawianie tych narzędzi, dlatego wspomnimy
jedynie o jednej z licznych możliwości, a mianowicie o pasku narzędziowym Camera Toolbar,
który rozwija się z menu View, znajdującym się w oknie Figure. Posługując się ikonami znaj-
dującymi się na tym pasku, Czytelnik może samodzielnie sprawdzić i wykorzystać możliwo-
ści programu MATLAB® w zakresie grafiki trójwymiarowej.

4.2.5. Efekty oświetlania rysunków trójwymiarowych


Rysowanej powierzchni można nadać bardziej przestrzenny charakter stosując jej
oświetlenie. Na powierzchni widoczne są wówczas jaśniejsze plamy i cienie. Program MA-
TLAB® umożliwia oświetlanie powierzchni z różnych źródeł światła oraz ustawienie źródła w
dowolnej pozycji względem układu współrzędnych. Narzędzia do oświetlania rysunku znaj-
dują się na pasku narzędziowym w menu View, Camera Toolbar, w menu Tool, Camera Motion,
Orbit Scene Light, a także Edit, Figure Properties, Edit Properties for: surface. W ostatnim przy-
padku otwiera się okno, w którym można dobrać różne rysowanej parametry powierzchni, a w
tym dotyczące oświetlenia. Do programowego ustawienia oświetlenia służy kilka instrukcji,
które pokrótce omówimy.
Instrukcja camlight służy do ustawienia źródła światła w określonym położeniu wzglę-
dem obserwatora (kamery). I tak
 camlight headlight – ustawia źródło światła w pozycji kamery
 camlight right - ustawia źródło światła na prawo i nad kamerą
 camlight- jak wyżej
 camlight left - ustawia źródło światła na lewo i nad kamerą
 camlight(az,el) - ustawia źródło odchylone od kierunku kamerą o kąty az (azy-
mutu) i el (elewacji), wyrażone w stopniach
Komendy te można zapisywać w formie funkcji, np. camlight(‘right’,...). W miejsce kro-
pek można wpisać jeden z dwóch parametrów, a mianowicie ‘local’ lub ‘infinite’. Parametr ‘local’
ustawia źródło światła blisko układu współrzędnych i promienie światła tworzą wtedy
wiązkę. Parametr ‘infinite’ ustawia źródło światła w nieskończonej odległości od układu współ-
rzędnych i wówczas promienie światła są równoległe.
Instrukcja
lightangle(az,el)
ustawia źródło światła względem układu współrzędnych w ten sam sposób, jak view(az,el)
odnosząca się do obserwatora.
62

Instrukcja lighting służy do wyboru algorytmu, który jest stosowany przez program MA-
TLAB® do uzyskania efektów oświetlenia. Mamy cztery możliwości do wyboru:
 – przypisuje odpowiedni kolor do każdej elementarnej płaszczyzny, z
lighting flat
których utworzona jest rysowana powierzchnia
 lighting gouraud –interpoluje kolory wewnątrz płaszczyzn, co daje lepszy efekt
przy rysowaniu krzywych powierzchni
 lighting phong – postępuje jak wyżej, przy czym interpolacja dotyczy każdego
piksela,
a więc rysowanie trwa dłużej.
 lighting none – wyłącza źródło światła
Instrukcja material pozwala dobrać materiał, z którego zbudowana jest oświetlana po-
wierzchnia pod względem właściwości odbijających światło. Są to:
 material shiny – materiał połyskliwy
 material dull – materiał matowy
 material metal - metal
 material default – domyślny, automatyczny dobór materiału

4.2.6. Inne metody formatowania rysunku


Przedstawione wyżej instrukcje nie wyczerpują możliwości, które daje program MA-
TLAB® w zakresie grafiki trójwymiarowej. Możliwości te są opisane w Help w rozdziale 3-D
Visualization. Wspomnimy tu jedynie o ustawieniu parametrów rysunku bezpośrednio w in-
strukcjach surf i mesh. Można mianowicie uzupełnić argumenty tych funkcji przez nazwy pa-
rametrów i ich wartości. Przykładowo instrukcja surf o rozszerzonym argumencie ma ogólną
formę:
surf(x,y,Z,’nazwa parametru’,wartość parametru,’nazwa parametru’, wartość parametru,...)
Listę wszystkich parametrów i ich wartości, którymi są z reguły ciągi znaków, można
znaleźć w Help/Functions-Alphabetical List/Surface Properties.
Inna metoda, której nie zalecamy początkującym użytkownikom programu MATLAB ®,
używa do ustawiania parametrów rysunku funkcji set. Składnia tej funkcji jest następująca:
set(h,’nazwa parametru’,wartość parametru,’nazwa parametru’, wartość parametru,...)
Litera h oznacza identyfikator obiektu graficznego, którego dotyczyć będą podane pa-
rametry. Może to być liczba (np. numer rysunku) lub wektor, w którym poszczególne liczby
identyfikują rysunek i jego elementy. Identyfikator jest ustalany przez program MATLAB ®.
Można go znaleźć pisząc:
h=findobj
Jeżeli mamy zamiar wprowadzać parametry aktualnego rysunku, wtedy w miejsce iden-
tyfikatora wpisuje się gcf. Gdy chcemy zmienić parametry osi, wtedy w miejsce h wpisujemy
gca.
Nazwy parametrów i ich wartości dla aktualnego rysunku lub obiektu na rysunku otrzy-
mujemy pisząc:
V=get(h)
gdzie h jest identyfikatorem rysunku lub obiektu graficznego.
63

Jeżeli chcemy znać wartości określonego parametru, wtedy wykorzystujemy następu-


jącą instrukcję:
v=get(h,’nazwa parametru’)
Wykaz parametrów i ich wartości można znaleźć w Help/Functions-Alphabetical
List/Surface Properties.
Do wymienionych wyżej funkcji powrócimy jeszcze omawiając Graficzny Interfejs
Użytkownika (GUI).
Na zakończenie przedstawimy program rysujący wykres funkcji dwóch zmiennych, w
którym zastosowano część omówionych wyżej instrukcji. Wyznaczymy mianowicie po-
wierzchnię opisaną funkcją:
Z=[sin(x)/x][sin(y)/y]
Program wykreślający powierzchnię tej funkcji ma następującą postać:
x=-2*pi:pi/50:2*pi; % Wektor wierszowy zmiennej x
y=2*x'; % Wektor kolumnowy zmiennej y
fx=sin(x+eps)./(x+eps); % Wektor wierszowy funkcji zmiennej x
fy=sin(y+eps)./(y+eps); % Wektor kolumnowy funkcji zmiennej y
Z=(fy*fx); % Macierz funkcji dwóch zmiennych
surf(x,y,Z,'linestyle','none') % Wykres powierzchni Z pozbawiony siatki

axis([-2*pi 2*pi -4*pi 4*pi -0.5 1]) % Ustawienie zakresu osi wykresu
title('Funkcja dwóch zmiennych') % Tytuł wykresu
xlabel('x','position', [10.2 -5 -1.05]) % Opis osi wykresu i ustawienie położenia napisu
ylabel('y','position', [-5 15.5 -0.72])
zlabel('Z','position', [-5 15 1],'rotation',0)
view(-45,40) % Ustawienie kątów azymutu i elewacji obserwatora
colormap jet % Ustawienie palety barw
caxis([-0.5 1]) % Ustawieni wartości zmiennej Z dla najniżej
i najwyższej barwy
camlight(10,-5) % Ustawienie kątów azymutu i elewacji źródła światła
lighting phong % Określenie metody interpolacji barw
material shiny % Określenie materiału powierzchni
set(1,'color','white') % Ustawienie koloru obrzeża rysunku

Rys. 4.13. Wykres funkcji dwóch zmiennych.


64

4.2.7. Obrazy figur trójwymiarowych


Dotychczas zajmowaliśmy się obrazami graficznymi funkcji dwóch zmiennych, w któ-
rych – zgodnie z definicją funkcji – każdej parze zmiennych niezależnych x,y przyporządko-
waną jest tylko jedna wartość zmiennej Z. Istnieją powierzchnie, których nie można opisać
funkcją, np. powierzchnia sześcianu, kuli itp. W geometrii analitycznej opisane są one równa-
niami lub układami równań. Do wyznaczania obrazu takich powierzchni wykorzystuje się w
programie MATLAB specjalne instrukcje, które teraz pokrótce zaprezentujemy.
W odróżnieniu od wyżej omówionych argumentów funkcji surf i mesh, do rysowania
powierzchni, które mogą lecz nie muszą być obrazem funkcji, używamy trzech argumentów
będących macierzami. Zapis instrukcji ma teraz następującą postać:
surf(X,Y,Z,...) lub mesh(X,Y,Z)
Macierz X zbudowana jest w ten sposób, że każdy jej wiersz jest kopią wektora x.
Liczba wierszy N jest równa długości wektora y. Macierz Y składa się z jednakowych kolumn,
które są kopiami wektora y. Liczba kolumn N jest równa długości wektora x. Macierz Z ma
wymiar [M,N].
Jeżeli zdefiniowane są wektory x i y, to macierze X i Y tworzy się używając instrukcji:
[X,Y]=meshgrid(x,y)
Oto prosty przykład:
>> y=0:2:8;
>> x=0:-1:-6;
>> [X,Y]=meshgrid(x,y)

X=

0 -1 -2 -3 -4 -5 -6
0 -1 -2 -3 -4 -5 -6
0 -1 -2 -3 -4 -5 -6
0 -1 -2 -3 -4 -5 -6
0 -1 -2 -3 -4 -5 -6

Y=
0 0 0 0 0 0 0
2 2 2 2 2 2 2
4 4 4 4 4 4 4
6 6 6 6 6 6 6
8 8 8 8 8 8 8

Zauważmy, że wartości w obu macierzach są współrzędnymi siatki prostokątnej utwo-


rzonej na płaszczyźnie Z=0. Każdemu punktowi tej siatki przyporządkowana jest odpowiednia
wartość zmiennej niezależnej, którą jest macierz Z. Wartość ta jest wysokością punktu nad
płaszczyzną Z=0. Ponieważ jednemu punktowi na płaszczyźnie Z=0 przyporządkowana jest
tylko jedna wartość macierzy Z, a zatem Z jest funkcją. Mimo innego zapisu, omawiane tu
instrukcje nie różnią się w istocie od podanych w poprzednich punktach.
Macierzowy zapis argumentów funkcji surf i mesh otwiera jednak możliwości rysowa-
nia dowolnych powierzchni, nie tylko będących obrazem funkcji dwóch zmiennych. W tym
celu należy zrezygnować z funkcji meshgrid i utworzyć inne macierze X,Y,Z. Macierze te po-
winny opisywać rzuty punktów na płaszczyzny i/lub osie układu współrzędnych. Wszystkie
trzy macierze muszą mieć ten sam wymiar. Ten sam wymiar musi mieć także macierz C,
która opisuje kolory na rysunku. Ponieważ macierze muszą mieć ten sam wymiar, więc
65

można je przedstawić jako funkcje dwóch parametrów, np. m,n : X(m,n),Y(m,n), Z(m,n), C(m,n).
Parametry m,n mogą być kątami we współrzędnych sferycznych lub kątem i promieniem we
współrzędnych cylindrycznych.
Zamieszczony niżej krótki program ilustruje sposób tworzenia obrazu trójwymiarowego
figury, która nie może być wyrażoną funkcją dwóch zmiennych. Jest to figura, która powstała
w wyniku obrotu funkcji x=25+z2 wokół osi Z. Pokazano ją na rys. 4.14.
theta=pi*(-20:20)/20;
h=(-5:10)';
X=(25+h.^2)*sin(theta);
Y=(25+h.^2)*cos(theta);
Z=h*ones(1,41);
colormap winter
surf(X,Y,Z)

Rys. 4.14. Trójwymiarowy obraz figury obrotowej.

4.3. Graficzny interfejs użytkownika


4.3.1. Ogólna charakterystyka
Graficzny interfejs użytkownika jest narzędziem ułatwiającym wprowadzania zmian w
programie i jednocześnie umożliwiającym wygodny dostęp do wyników obliczeń w formie
graficznej i numerycznej.
Używając programu MATLAB do obliczeń numerycznych lub do symulacji pracy
układów bądź systemów piszemy skrypt zawierający wszystkie niezbędne instrukcje realizu-
jące postawione zadanie. W takim skrypcie wszystkie dane, parametry, funkcje, operacje gra-
ficzne itp. są określone i nie ulegają zmianie przy każdorazowym uruchomieniu programu.
Chcąc cokolwiek zmienić w napisanym skrypcie musimy wpisać inne instrukcje lub wyko-
rzystać instrukcję input. Program natrafiając na tę instrukcję żąda od użytkownika wprowa-
dzenia określonej danej, którą może być np. wartość parametru. Przy większej liczbie para-
metrów jest to kłopotliwe, gdyż wymaga każdorazowo wpisywania wszystkich, także powta-
rzających się wartości. Tę niedogodność eliminuje graficzny interfejs użytkownika GUI (ang.
66

Graphical User Interface). Narzędzie to tworzy rysunek w formie planszy, na której mogą
znajdować się przyciski, klucze, suwaki, listy parametrów, pola wykresów itp. które obsłu-
guje się myszą lub wpisuje dane z klawiatury. Skutkiem każdej zmiany nastaw jest wykona-
nie odpowiednich operacji i ekspozycja wyników w formie graficznej, numerycznej lub łań-
cuchów znaków. W sumie odpowiednio zaprojektowana plansza GUI przypomina płytę czo-
łową przyrządu pomiarowego, np. oscyloskopu.
Planszę graficznego interfejsu użytkownika projektuje się stosunkowo łatwo używając
środowiska GUIDE (ang. GUI Design Environment). Wybiera się mianowicie myszą potrzebne
elementy z menu znajdującego się na planszy projektowej i umieszcza na planszy GUI, która
będzie obsługiwana po napisaniu programu przez użytkownika. Efektem tych operacji poza
planszą z naniesionymi elementami jest specjalny program utworzony automatycznie przez
GUIDE z rozszerzeniem .m oraz rysunek z rozszerzeniem .fig. Oba skrypty można umieścić w
katalogu work lub utworzonym własnym folderze.
Utworzony program z rozszerzeniem .m należy nazwać i zapamiętać, a nadana nazwa
będzie jednocześnie nazwą funkcji i nazwą rysunku. Taki skrypt definiuje zatem nową funk-
cję, a konsekwencją tego jest to, że zmienne w ramach funkcji są zmiennymi lokalnymi (nie
występują poza funkcją).
Skrypt definiujący funkcję zawiera szereg instrukcji, które nie powinny być zmieniane
przez programistę (definiują one planszę z jej elementami) oraz pewną liczbę instrukcji zapi-
sanych wstępnie jako komentarze. Po usunięciu znaku % oraz po niezbędnych uzupełnieniach
posłużą one do wykonania pożądanych operacji realizujących zadania programu. Nie wszyst-
kie z tych instrukcji muszą być wykorzystane. Oczywiście, poza omawianymi instrukcjami
zachodzi z reguły konieczność wprowadzenia innych, potrzebnych instrukcji.
Omawiany tu program może współpracować z innymi programami zapisanymi jako od-
dzielne pliki z rozszerzeniem .m. Ponieważ program GUI jest funkcją, to występujące w nim
zmienne nie są widoczne w innych programach i na odwrót. Przekazywanie zmiennych z pro-
gramu GUI do innych programów i w kierunku odwrotnym odbywa się przez specjalną bazę
danych, w której zawarte są wszystkie parametry obiektów znajdujących się na planszy użyt-
kownika.
Ogólne informacje o graficznym interfejsie użytkownika zakończymy uprzedzeniem, że
przedstawione dalej omówienie obejmuje jedynie niewielki fragment jego możliwości. Może
jednakże być pomocne w pokonaniu pierwszych kroków opanowania tego bardzo użytecz-
nego narzędzia.

4.3.2. Projektowanie planszy GUI


Proces projektowania planszy GUI rozpoczynamy od specyfikacji zadań, które ma ona
spełniać w tworzonym programie. Do zadań tych dobieramy elementy planszy, których listę i
realizowane funkcję podamy dalej. Elementy te rozmieszczamy na szkicu planszy, który wy-
konujemy odręcznie na kartce. Dysponując wstępnym szkicem planszy otwieramy narzędzie
do projektowania GUI, pisząc:
>>guide
Otwiera się okno GUIDE Quick Start do uruchomienia narzędzia GUIDE. Pokazano je na
rys. 4.15.
67

Rys. 4.15. Okno otwierające narzędzie GUIDE do projektowania planszy GUI


Jeżeli rozpoczynamy tworzenie nowej planszy, wybieramy Create New Gui i Blank GUI.
Jeżeli chcemy kontynuować prace z istniejącą planszą, wtedy wybieramy Open Existing GUI i
w oknie zaznaczamy na liście poszukiwany program, po czym wciskamy przycisk Open. W
jednym i drugim wypadku pojawia się okno do projektowania planszy, przy czym w pierw-
szym wypadku ma ono nazwę untitled.fig., zaś w drugim wcześniej nadaną nazwę i rozszerze-
nie .fig. Pustą planszę pokazano na rys. 4.16.

Rys. 4.16. Okno do projektowania planszy graficznego interfejsu użytkownika.


68

W pliku z rozszerzeniem .fig znajduje się program, który rysuje plansze GUI. Program
ten jest tworzony automatycznie przez narzędzie GUIDE. Każdorazowa zmiana naniesiona na
planszy projektowej powoduje stosowaną zmianę tego programu.
Z menu File wybieramy Save As... i wpisujemy nazwę pliku, która będzie jednocześnie
nazwą programu (funkcji) z rozszerzeniem .m. Po wciśnięciu Zapisz, pojawia się plansza z
nadaną właśnie nazwą i możemy przystąpić do umieszczania wybranych elementów na plan-
szy. Są one widoczne w lewej kolumnie rysunku. Na górze kolumny znajduje się strzałka,
która służy wyłącznie do oznaczania i wybierania elementów planszy. Pozostałe ikony przed-
stawiają kolejno:
 Push Button – przycisk – wciśnięcie myszą tego przycisku powoduje jednokrotną
reakcję programu, np. uruchomienie określonej procedury,
 Toggle Button– przełącznik dwustanowy – w stanie wciśniętym (podświetlonym)
realizuje pewną procedurę, a w stanie zwolnionym – inną
 – przycisk dwustanowy – działa jak Toggle Button, lecz jest zwykle
Radio Button
używany w grupie i wtedy można spowodować, że włączenie jednego przycisku
powoduje wyłączenie pozostałych
 Checkbox – przycisk dwustanowy – używany do wyboru pewnej akcji; zwykle
stosuje się kilka takich przycisków do wyboru jednej lub kilku niezależnych ak-
cji
 – okienko tekstowe – służy do edycji tekstu emitowanego przez pro-
Edit Text
gram lub do wpisywania tekstu przez użytkownika
 – okienko tekstowe – w oknie tym wpisuje się stałe teksty informa-
Static Text
cyjne; program nie reaguje na tekst
 – suwak – przesuwanie musza manipulatora zmienia wartość przypisanej
Slider
do suwaka zmiennej
 Frame – ramka – służy do obramowania zespołu elementów na planszy w celu
zaznaczenia ich związku funkcjonalnego
 – przycisk wielostanowy – zawiera listę elementów (łańcuchów), z któ-
Listbox
rych można wybrać jeden lub kilka
 Popup Menu – zestaw przełączników dwustanowych w formie listy funkcjonują-
cych jak przełączniki Toggle Button; zastępuje zestaw przełączników Radio Button
 Axes – osie – wyznacza położenie i wielkość rysunku umieszczonego na planszy
Położenie i wielkość każdego elementu można zmieniać myszą. Do zmian innych pa-
rametrów elementu służy Property Inspektor, który otwiera się przez oznaczenie elementu le-
wym klawiszem myszy i wciśnięciu prawego klawisza. Otwiera się wówczas okno z użytecz-
nymi instrukcjami służącymi do usuwania, kopiowania, wklejania i wykonania innych opera-
cji odnoszących się do zaznaczonego elementu. Na liście znajduje się również napis Property
Inspector, którego wciśnięcie otwiera okno zawierające wszystkie parametry danego elementu.
Najczęściej nie ma potrzeby dokonywania większych zmian owych parametrów. Ograni-
czamy się zwykle do zmiany nazwy elementu (String), zmiany nazwy zmiennej przypisanej do
elementu (Tag), doboru koloru tła (BackgroundColor), koloru czcionki (ForegroundColor), wy-
sokości czcionki (FontSize) i kroju czcionki (FontName). Wszystkie wprowadzone zmiany są
automatycznie zapamiętane i obowiązują przy każdorazowym otwarciu rysunku.
69

Po umieszczeniu wszystkich elementów na planszy, nadaniu im pożądanego wyglądu i


nazwy wybieramy z menu Tools polecenie Run. Pojawia się wtedy okno zawierające zapro-
jektowaną planszę. Można na nim zaobserwować wyniki naszego projektu i dokonać zauwa-
żonych poprawek (tylko w oknie do projektowania, oznaczonym jako ...fig).
W oknie przeznaczonym do projektowania planszy wciskamy teraz ikonę M-file Editor.
Pokazuje się wtedy nowe okno zatytułowane tak jak plansza i posiadające rozszerzenie .m.
Jest to wspomniany wcześniej szkic programu, który należy dostosować do naszych potrzeb i
uzupełnić o wszystkie potrzebne instrukcje.

4.3.3. Podstawy programowania graficznego interfejsu użytkownika GUI


Plik zawierający szkic programu GUI składa się z następujących ważnych części:
 W pierwszej linii widoczna jest instrukcja definiująca funkcję, którą definiuje
omawiany plik. Ma ona nazwę przypisaną w czasie projektowania planszy.
 Szereg kolejnych linii zawiera krótkie informacje o funkcji. Są one edytowane
jeżeli w oknie Command Window wpiszemy help <nazwa planszy GUI>.
 W kolejnych wierszach wpisane są instrukcje dotyczące każdego pliku GUI. Nie
należy ich zmieniać, ani usuwać (z wyjątkiem komentarzy). Po tych instrukcjach
występuje komentarz DO NOT EDIT. Następnie widoczne są wiersze zawierające
standardowe funkcje dotyczące danych wejściowych i wyjściowych kończące
się instrukcją varargout{1} = handles.output. Bez wyraźnej potrzeby nie należy do-
konywać w nich zmian.
 Zawartość dalszych wierszy zależy od liczby i rodzajów elementów umieszczo-
nych na planszy. Każdemu elementowi przypisana jest jedna lub dwie funkcje.
Są to funkcje wewnętrzne, a więc komunikacja między nimi jest możliwa tylko
w określony sposób, który omówimy dalej. Przypominamy, że zmienne w ra-
mach funkcji są lokalne, a więc nie są widoczne poza nią. Definicji tych funkcji
nie należy zmieniać. Funkcja poprzedzona jest komentarzem dotyczącym spo-
sobu jej wykonywania. Za definicją funkcji występuje szereg wierszy zawierają-
cych wzory instrukcji, które może programista przekształcić w „prawdziwe” in-
strukcje usuwając znak % i je odpowiednio uzupełniając. Znajdują się tam rów-
nież wskazówki dla programisty, które można usunąć po zapoznaniu się z ich
treścią. Jeżeli wewnątrz funkcji znajdują się instrukcje (bez znaku %), to należy
je pozostawić bez zmian.
Podstawy programowania omówimy na prostym przykładzie polegającym na użyciu
przycisku Push Button do włączenia programu prostych obliczeń. Przycisk ten nazwiemy
START. Kolejne czynności są następujące:

 W oknie Command Window piszemy


>> guide
 W oknie GUIDE Quick Start wybieramy Blank Gui (Default)
 W untitled1.fig wybieramy File, Save As...
 W oknie Save As... wpisujemy nazwę planszy (pliku) np. example1
 Następuje zmiana nazwy okna do projektowania na example1.fig
 Oznaczamy myszą ikonę Push Button i przeciągamy ją na środek planszy
 Przyciskamy prawy klawisz myszy i z menu wybieramy Property Inspector
70

 W BackgroundColor ustawiamy kolor tła wciskając kolorową ikonę, Definiuj kolory


niestandardowe>> i suwakiem wybieramy kolor jasnoszary
 W wierszu FontSize wpisujemy 12
 W wierszu String wpisujemy START
 W wierszu Tag wpisujemy start
 Myszą powiększmy przycisk do pożądanych rozmiarów
 W menu File wciskamy Save
 W menu Tools przyciskamy Run
 Pojawia się zaprojektowana plansza, której widok pokazano na rys. 4.17.

Rys.4.17. Widok zaprojektowanej planszy GUI.


Od tego momentu można przystąpić do pisania programu. W tym celu na pasku narzę-
dziowym planszy projektowej wciskamy ikonę M-file Editor. Pojawia się wtedy okno, zatytu-
łowane example1.m, a w oknie tym następujący program.
function varargout = example1(varargin)
% EXAMPLE1 M-file for example1.fig
% EXAMPLE1, by itself, creates a new EXAMPLE1 or raises the existing
% singleton*.
%
% H = EXAMPLE1 returns the handle to a new EXAMPLE1 or the handle to
% the existing singleton*.
%
% EXAMPLE1('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in EXAMPLE1.M with the given input arguments.
%
% EXAMPLE1('Property','Value',...) creates a new EXAMPLE1 or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before example1_OpeningFunction gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to example1_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
71

% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help example1

% Last Modified by GUIDE v2.5 20-Jul-2007 12:53:13

% Begin initialization code - DO NOT EDIT


gui_Singleton = 0;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @example1_OpeningFcn, ...
'gui_OutputFcn', @example1_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin & isstr(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before example1 is made visible.


function example1_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to example1 (see VARARGIN)

% Choose default command line output for example1


handles.output = hObject;

% Update handles structure


guidata(hObject, handles);

% UIWAIT makes example1 wait for user response (see UIRESUME)


% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = example1_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure


varargout{1} = handles.output;

% --- Executes on button press in start.


function start_Callback(hObject, eventdata, handles)
% hObject handle to start (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)

Przedstawiony wyżej program zawiera omówione wyżej elementy, z których większość


to informacje i wskazówki. Niezbędne elementy tego programu przytoczone są poniżej.
72

function varargout = example1(varargin)


gui_Singleton = 0;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @example1_OpeningFcn, ...
'gui_OutputFcn', @example1_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin & isstr(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
function example1_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
function varargout = example1_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function start_Callback(hObject, eventdata, handles)

Wszystkie wiersze są niezbędne i nie należy ich zmieniać i usuwać. Ostatni wiersz za-
wiera funkcję start_Callback, która reaguje na każdorazowe wciśnięcie przycisku START. Za-
uważmy, że nazwa tej funkcji zawiera tekst wpisany jako Tag w Property Inspector. Funkcje
takie o nadanych im nazwach pojawią się w programie, w którym wystąpią także inne ele-
menty na planszy GUI. Struktura funkcji jest stała i ma postać pokazaną w przykładzie. hObjet
jest uchwytem (identyfikatorem) danego obiektu, eventdata jest zarezerwowane dla dalszego
rozwoju GUI i nie jest obecnie używane, handles to zasób danych związanych z danym obiek-
tem. W strukturze handles umieszcza się dane, które będą widoczne poza funkcją.
W przypadku Push Button reakcją na wciśnięcie tego przycisku jest wykonywanie
wszystkich instrukcji zapisanych za function start_Callback(hObject, eventdata, handles).
Przykładowo, jeżeli do powyższego programu dopiszemy
x=1:10;
figure
stem(x)
to każdorazowe wciśnięcie przycisku START spowoduje pojawienie się kolejno numerowa-
nego rysunku zawierające dziesięć próbek o wartościach od 1 do 10.

4.3.4. Użycie przełącznika Toggle Button i okna edycyjnego Edit Text.


Przełącznika użyjemy do pomiaru czasu stoperem, a wynik pokażemy w oknie edycyj-
nym. Postępując jak poprzednio umieszczamy na planszy przełącznik, który nazwiemy stoper
oraz okno edycyjne i stałe napisy. Planszę tę zapisujemy pod nazwą example2.fig. Widok plan-
szy pokazano na rys. 4.18.
Poniżej zamieszczono część programu, z którego usunięto powtarzającą się część stałą
oraz wszystkie komentarze i zbędne instrukcje. Stała część programu jest taka sama, jak w
poprzednim przykładzie (z wyjątkiem nazwy funkcji).
function stoper_Callback(hObject, eventdata, handles)
73

function czas_CreateFcn(hObject, eventdata, handles)


Instrukcja zapisana w pierwszym wierszu definiuje funkcję do zwracani efektów wci-
śnięcia lub zwolnienia przełącznika STOPER. Druga funkcja ustawia parametry okna edycyj-
nego, a w tym m.in. tekst, który powinien się pojawić w oknie.
Ten krótki program należy uzupełnić o instrukcje, które zapewnią realizację pożąda-
nych zadań, czyli w naszym wypadku – pomiar czasu. Są to następujące instrukcje:

Rys. 4.18. Plansza z przełącznikiem Toggle Button i oknem edycyjnym Edit Text.

function stoper_Callback(hObject, eventdata, handles)


stan=get(hObject,'value');
if stan==1
tic
t=0;
elseif stan==0
t=toc;
end
ts=num2str(t);
set(handles.czas,'string',ts)

function czas_CreateFcn(hObject, eventdata, handles)


Instrukcja zapisana w drugim wierszu zwraca aktualną wartość przełącznika. Parametr
hObject identyfikuje aktualny obiekt, który jest nazwany w funkcji Callback jako hObject. Pa-
rametr ‘value’ w przełączniku Toggle Button przyjmuje wartość 1, gdy przycisk jest wciśnięty i
wartość 0, jeżeli jest on zwolniony. Zmienna stan przyjmuje zatem wartość 1 lub zero, w za-
leżności od stany przełącznika. W trzecim wierszu sprawdzamy, czy klucz jest włączony.
Jeżeli jest to prawda, włączamy licznik czasu, który w programie MATLAB uruchamia się
instrukcją tic. Zmienną t ustawiamy w momencie włączenia klawisza STRAT na wartość 0.
Tekst wyświetlany w oknie edycyjnym musi być koniecznie w formacie łańcucha znaków
‘string’. Konieczną jest zatem zamiana zmiennej liczbowej t na łańcuch. Operację tę wykonuje
instrukcja num2str. W tym wypadku zwraca ona łańcuch ts=‘0’. Następna instrukcja umieszcza
ten łańcuch w oknie edycyjnym. Parametrami funkcji set są handles.czas, który jest odwoła-
74

niem do funkcji czas zdefiniowanej w następnym wierszu, nazwa parametru ‘string’ i wartość
tego parametru ts. W momencie wciśnięcia przełącznika START w oknie edycyjnym pojawia
się zatem 0.
Od tego momentu program odlicza czas, aż do chwili zwolnienia przełącznika START.
Wartość stan jest wtedy równa 0, a zatem realizowana jest instrukcja t=toc. Ta standardowa
instrukcja programu MATLAB zatrzymuje zegar i zwraca jego wartość. Wartość ta jest wy-
świetlana w polu edycyjnym w wyniku działania omówionych wyżej instrukcji.
Podany program ilustruje sposób wykorzystywania ważnych funkcji get i set. Pierwsza
z nich służy do pozyskiwania parametrów, zaś druga do ich wprowadzania. Inny sposób ich
użycia pokazuje następny przykład użycia okna edycyjnego. W jednym oknie będziemy wpi-
sywać zmienną x, a w drugim podamy wartość funkcji y=log(x). Zaprojektowaną planszę po-
kazano na rys. 4.19.

Rys.4.19. Plansza z oknami edycyjnymi Edit Text.


Fragment programu realizującego opisane wyżej zadanie ma następującą postać:
function x_CreateFcn(hObject, eventdata, handles)

function x_Callback(hObject, eventdata, handles)


x=str2double(get(hObject,'String'));
if x<=0
set(handles.y,'string','x musi być >0')
else
y=log10(x);
ys=num2str(y);
set(handles.y,'string',ys)
end

function y_CreateFcn(hObject, eventdata, handles)


Instrukcje w pierwszym i ostatnim wierszu konfigurują dwa okna edycyjne. Funkcja w
drugim wierszu definiuje funkcję, która w strukturze handles zawiera tekst wpisany do okna
edycyjnego nazwanego x. Instrukcja w trzecim wierszy zwraca tekst wpisany w oknie edycyj-
75

nym (get(hObkect,’string’) i zamienia go na wartość liczbowa (str2double). Następnie spraw-


dzamy, czy wartość x jest ujemna. Jeżeli tak, to wpisujemy do okna edycyjnego y tekst ‘x musi
być >0’. W przeciwnym wypadku obliczamy wartość logarytmu, zamieniamy go na łańcuch i
pisujemy do okna edycyjnego y.

4.3.5. Użycie przełącznika Radio Button i okna edycyjnego Edit Text.


Sposób użycia przełącznika Radio Button zilustrujemy na przykładzie wyznaczania
wartości czterech funkcji trygonometrycznych dla jednego kąta podawanego przez użytkow-
nika. W tym celu, używając narzędzia GUIDE zaprojektujemy planszę pokazaną na rys. 4.20.

Rys. 4.20. Przykład zastosowania przycisków Radio Button.


Poniżej zamieszczono części programu wykonującego podane wyżej zadania.
function x_CreateFcn(hObject, eventdata, handles)
function x_Callback(hObject, eventdata, handles)
x=str2double(get(hObject,'String'))
handles.x=x;
guidata(hObject, handles);

function fsin_Callback(hObject, eventdata, handles)


stan= get(hObject,'Value');
if stan==1
set(handles.fcos,'value',0)
set(handles.ftg,'value',0)
set(handles.fctg,'value',0)
x=handles.x;
y=sin(pi*x/180);
ys=num2str(y);
set(handles.y,'string',ys)
end

function fcos_Callback(hObject, eventdata, handles)


stan=get(hObject,'Value');
76

if stan==1
set(handles.fsin,'value',0)
set(handles.ftg,'value',0)
set(handles.fctg,'value',0)
x=handles.x;
y=cos(pi*x/180);
ys=num2str(y);
set(handles.y,'string',ys)
end

function ftg_Callback(hObject, eventdata, handles)


stan=get(hObject,'Value')
if stan==1
set(handles.fsin,'value',0)
set(handles.fcos,'value',0)
set(handles.fctg,'value',0)
x=handles.x;
y=tan(pi*x/180);
ys=num2str(y);
set(handles.y,'string',ys)
end

function fctg_Callback(hObject, eventdata, handles)


stan=get(hObject,'Value')
if stan==1
set(handles.fsin,'value',0)
set(handles.fcos,'value',0)
set(handles.ftg,'value',0)
x=handles.x;
y=1/tan(pi*x/180);
ys=num2str(y);
set(handles.y,'string',ys)
end

function y_CreateFcn(hObject, eventdata, handles)


Pierwszy fragment programu służy do wprowadzania zmiennej x. W stosunku do po-
przednich przykładów nowością są dwie instrukcje, a mianowicie handles.x=x oraz gu-
idata(hObject, handles). Pierwsza z nich zapisuje zmienną x jako element struktury handles. zaś
druga instrukcja zapamiętuje ten element w zbiorze handles. W ten sposób umożliwia dostęp
do tej zmiennej wewnątrz innych funkcji.
Cztery kolejne fragmenty o jednakowej składni służą do ustawiania przełączników
Radio Button oraz do wykonania obliczeń i wpisania ich wyników w oknie edycyjnym y, zde-
finiowanym ostatnią instrukcją. W każdym z fragmentów sprawdzamy najpierw stan prze-
łącznika. Jeżeli jest on wciśnięty (stan==0), wtedy ustawiamy pozostałe przełączniki w stan
wyłączenia (‘value’,0). Następnie pobieramy ze zbioru handles zmienną x (x=handles.x), wyko-
nujemy obliczenie związane z danym przełącznikiem i wpisujemy wynik do okna edycyjnego
y.
Wzajemne uzależnienia stanu przełączników można zrealizować przy użyciu innych
instrukcji, podanych w Help. W tym skrypcie staramy się ograniczyć liczbę instrukcji do nie-
zbędnego minimum i dlatego posługujemy się znaną już funkcją set.
77

4.4.6. Użycie Popup Menu


Zestaw przełączników Radio Button można zastąpić narzędziem Popup Menu. Aby po-
kazać różnice w oprogramowaniu zaprojektujemy planszę, w której w powyższym przykła-
dzie zastąpimy tylko przełączniki Radio Button elementem Popup Menu.
Projektując plansze, po umieszczeniu elementu Popup Menu, należy w oknie Property
Inspector wybrać parametr String i wpisać w oknie w kolejnych wierszach tekst widoczny na
rys. 4.21.

Rys. 4.21. Plansza wykorzystująca Popup Menu (rozwinięte menu).


Program używający Popup Menu jest nieco prostszy do poprzedniego. Wybór wiersza z
listy przypisuje parametrowi ‘value’ wartość, która jest równa numerowi wiersza. Sprawdzając
zatem wartość stan=get(hObject,’value’) możemy wykonać odpowiednie obliczenie i wpisać
jego wynik do okna edycyjnego y. Wybór jednego wiersza wyklucza automatycznie możli-
wość wyboru pozostałych, co poprzednio wymagało napisania odpowiednich instrukcji.
function x_CreateFcn(hObject, eventdata, handles)
function x_Callback(hObject, eventdata, handles)
x=str2double(get(hObject,'String'))
handles.x=x;
guidata(hObject, handles);

function popupmenu1_CreateFcn(hObject, eventdata, handles)


function popupmenu1_Callback(hObject, eventdata, handles)
stan=get(hObject,'Value');
if stan==1
x=handles.x;
y=sin(pi*x/180);
ys=num2str(y);
set(handles.y,'string',ys)
elseif stan==2
x=handles.x;
y=cos(pi*x/180);
ys=num2str(y);
78

set(handles.y,'string',ys)
elseif stan==3
x=handles.x;
y=tan(pi*x/180);
ys=num2str(y);
set(handles.y,'string',ys)
else
x=handles.x;
y=1/tan(pi*x/180);
ys=num2str(y);
set(handles.y,'string',ys)
end

function y_CreateFcn(hObject, eventdata, handles)

4.3.6. Użycie Listbox i Axes


Element Listbox służy do wyboru jednej lub kilku akcji (bądź parametrów) spośród wy-
kazu umieszczonego przez programistę w okienku. Przykładowo, akcja może polegać na wy-
kreśleniu jednej lub kilku funkcji sin(x), cos(x), sin(2x), cos(3x). Nazwy tych akcji wpisuje się w
oknie String w Property Inspector, wywołanym po umieszczeniu elementu Listbox na planszy
projektowej. Jeżeli chcemy dopuścić możliwość jednoczesnego uruchomienia kilku akcji, to
w Property Inspector wpisujemy w Max liczbę naturalną większą od Min (np. Max=4, Min=0).
Wyboru akcji dokonuje się myszą, a przy oznaczaniu większej liczby akcji – myszą i
klawiszami Shift i Ctrl. Na planszy pokazanej na rys. 4.22 zaznaczono w ten sposób sin(x) i
cos(2x).

Rys. 4.22. Zastosowanie Listbox do wykreślania wybranych funkcji.


Jeżeli dopuszcza się wybór więcej niż jednej akcji, to należy bezwzględnie dodać przy-
cisk Push Button, opisany na planszy jako RYSUJ. Wynika to ze sposobu reagowaniu Listbox
na wybór akcji (parametru) umieszczonej na liście. Otóż funkcja Callback zmienia stan po
każdorazowym wciśnięciu myszy. Jeżeli wybieramy najpierw sin(x), a potem (używając Ctrl)
cos(2x), to najpierw stan informuje o włączeniu sin(x) i może to uruchomić niepotrzebnie od-
79

powiednią akcję. Wciśnięcie potem cos(2x) ponownie uruchamia obie akcje. Aby uniknąć
tego niekorzystnego efektu, akcję uruchamiamy dopiero po ustawieniu całej listy.
Element Axes umieszczony na planszy otwiera okno do rysowania wykresów. Można
dobrać jego położenie i rozmiar w ten sam sposób, jak pozostałych elementów GUI. Element
axes nie ma odzwierciedlenia w programie z rozszerzeniem .m. Wykonywanie wykresów po-
lega na wpisaniu do tego programu instrukcji plot, stem, surf itp. Wszelkie napisy, skale itp.
wykonują instrukcje zapisane za plot, stem, surf, mesh itp.
Na planszy można umieścić kilka rysunków. Instrukcje plot, stem i inne muszą być
wtedy poprzedzone adresem rysunku (osi). Jeżeli kolejne osi nazwane są automatycznie
axes1, axes2, ..., to program do umieszczania wykresów na kolejnych rysunkach ma następu-
jącą strukturę:
axes(handles.axes1)
plot(x,y)
axes(handles.axes2)
stem(x,y)
................
Program do wykreślania czterech funkcji zamieszczono poniżej.
varargout{1} = handles.output;

%Wyznaczanie funkcji

x=2*pi*(0:0.01:1)
y1=sin(x);
y2=cos(x);
y3=sin(2*x);
y4=cos(2*x);
Y=[y1;y2;y3;y4]; % Macierz zawierająca w czterech wierszach wartości funkcji
handles.x=x; % Zapis zmiennej x w strukturze handles
handles.Y=Y; % Zapis macierzy Y w strukturze handles
guidata(hObject, handles);

% Oprogramowanie Listbox

function listbox1_CreateFcn(hObject, eventdata, handles)

function listbox1_Callback(hObject, eventdata, handles)


stan=get(hObject,'Value'); % Wektor z numerami funkcji
handles.stan=stan; % Umieszczenie wektora stan w strukturze handles
guidata(hObject, handles);

% Oprogramowanie Push Button

function start_Callback(hObject, eventdata, handles)


stan=handles.stan; % Odzyskiwane wektora stan ze struktury handels
S=size(stan); % Wyznaczanie długości nd wektora stan
nd=S(1,2);
x=handles.x; % Odzyskiwane zmiennej x ze struktury handels
Y=handles.Y; % Odzyskiwane macierz Y ze struktury handels
reset(gca) % Usuwanie poprzedniego wykresu
for n=1:N % Odczytywanie wartości w wektora stan
w=stan(1,n);
plot(x,y(w,:)) % Wykres wiersza w macierzy Y
hold on % Zachowywanie wykresu
end
axis([0 2*pi -1 1]) % Zakres osi wykresu
80

xlabel('x') % Opis osi x

Za ostatnią linią standardowej części programu GUI, którą zapisano dla przypomnienia
w pierwszym wierszu, znajduje się szereg instrukcji wykonujących obliczenia wartości funk-
cji. Z wartości tych funkcji tworzymy macierz Y. Obliczeń dokonujemy w tym miejscu, aby
były wykonane jednokrotnie, po uruchomieniu programu. Umieszczenie ich w ramach jakiejś
funkcji spowodowałoby ich powtarzanie po każdej akcji związanej z tą funkcją.
Wyniki obliczeń umieszczono w strukturze handles, aby były dostępne w obrębie in-
nych funkcji.
Zmienna stan w oprogramowaniu Listbox jest wektorem o długości równej liczbie wy-
branych funkcji. Elementami tego wektora są liczby od 1 do 4, odpowiadające położeniu
funkcji na liści. Przy zaznaczeniu sin(x) i cos(2x) wektor stan = [1 4]. Wektor stan umiesz-
czamy w strukturze handles, aby można z niego skorzystać w ramach funkcji Push Button,
nazwanej tu start.
W ramach funkcji Push Button (start) realizowany jest wybór wykresów i ich wykreśla-
nie. Najpierw odczytujemy wektor stan, następnie znajdujemy jego długość, która jest po-
trzebna do ustalenia liczby operacji w pętli. W kolejnych dwóch wierszach pobieramy warto-
ści zmiennej x i macierz Y ze struktury handles.
Do umieszczania kilku wykresów na jednym rysunku służy zapisana dalej instrukcja
hold on. Aby uniknąć nakładania nowych wykresów na umieszczone wcześniej zapisano in-
strukcję reset(gca), która usuwa zawartość aktualnego rysunku (osi). Funkcja gca (skrót ang.
get current axes) zwraca uchwyt (adres) aktualnego rysunku (osi). W pętli odczytujemy ko-
lejne wartości wektora stan i rysujemy wykres wiersza wektora Y o odczytanym numerze.
Instrukcja hold on – jak wspomniano wyżej – powoduje rysowanie kolejnych wykresów na
tym samym rysunku.
Poza pętlą określamy zakres osi wykresów i oznaczamy oś poziomą jako x.

4.3.7. Zastosowanie suwaka Slider


Suwak Slider służy do ciągłej, ręcznej zmiany pewnego parametru. Spośród rozmaitych
jego zastosowań pokażemy przykład użycia go do realizacji funkcji zoom. Na jednym ry-
sunku pokażemy funkcję:
sin(n)
y(n)  cos(10n)
n

w przedziale -10n+10.
Na drugim rysunku wykres ten będzie powiększany wokół środka wykresu, czyli wokół
n=0.
Wartość parametru ‘Value’ funkcji slider_Callback zależy od położenia suwaka. Standar-
dowy zakres zmian wynosi od Min=0 (lewe położenie suwaka) do Max=1 (prawe położenie
suwaka. Wartości te można zmienić w Property Inspektor w wierszach Min i Max. Zmiany poło-
żenia suwaka można dokonywać przyciskając strzałki lub przesuwając myszą suwak (zmiana
precyzyjna) lub przyciskając myszą na puste pole (zmiana zgrubna). Standardowo zmiana
strzałkami lub suwakiem dokonywana jest z krokiem 1% zakresu, z zmian zgrubna z krokiem
10% zakresu. Można to zmienić wpisując inne wartości x, y w SliderStep w Property Inspector.
Położenie spoczynkowe suwaka wynosi standardowo 0 i można je zmienić wpisując inną
wartość parametru Value. W naszym przykładzie użyliśmy ustawień domyślnych (standardo-
81

wych) z wyjątkiem wpisania Max=0.9 i zmiany tła suwaka. Po tych zabiegach plansza ma
postać pokazaną na rys. 4.23.

Rys.4.23. Użycie suwaka Slider do realizacji funkcji zoom.

Fragment programu realizującego opisane wyżej zadanie przedstawia się następująco:


% Obliczenia i wykonanie górnego rysunku

n=-10:0.001:10;
y=sin(pi*(n+eps)).*cos(10*pi*n)./(pi*(n+eps));
handles.y=y;
guidata(hObject, handles);
axes(handles.axes1)
plot(n,y)
axes(handles.axes2) %Odwołanie do dolnego rysunku
plot(n,y) % Początkowa postać dolnego rysunku

% Realizacja funkcji zoom na dolnym rysunku

function slider1_CreateFcn(hObject, eventdata, handles)

function slider1_Callback(hObject, eventdata, handles)


z=get(hObject,'Value'); % Wynik położenia suwaka
y=handles.y;
nd=1+round(z*10000)
ng=20001-round(z*10000)
skala=-10.001+(nd:ng)/1000;
axes(handles.axes2) % Odwołanie do dolnego rysunku
plot(skala,y(nd:ng)); % Wykonanie dolnego rysunku
nmin=min(skala); % Górna granica skali rysunku
nmax=max(skala); % Górna granica skali rysunku
axis([nmin nmax -1 1]) % Ustalenie skali na osi wykresu
82

Wartość zmiennej z opisuje położenie suwaka i zmienia się od 0 do 0.9. Po każdej


zmianie położenia suwaka wykonują się zamieszczone niżej instrukcje. Od wartości z uzależ-
niono dolny i górny zakres przedziału, z którego będą pobierane dane z wektora y do sporzą-
dzenia wykresu. Od wielkości tego przedziału zależy skala wykresu, która jest dostosowana
do oznaczeń występujących na górnym rysunku. Znaczenie pozostałych instrukcji podano w
komentarzach do programu.
83

5. IMPORT I EKSPORT DANYCH


5.1. Wprowadzenie
Program MATLAB może działać autonomicznie wykonując obliczenia na danych ge-
nerowanych wewnątrz programu i podając wyniki obliczeń w formie liczbowej lub graficznej.
Dane do obliczeń mogą być również wprowadzane do programu przez użytkownika za po-
mocą klawiatury. Wiemy, że istnieje także możliwość kopiowania rysunków z program MA-
TLAB do innych programów, np. MICROSOFT WORD. Kopiować można także teksty
występujące w oknach programu MATLAB używając standardowych procedur środowiska
WINDOWS. W niektórych sytuacjach możliwości te nie są jednak wystarczające z punktu
widzenia użytkownika. Często zachodzi potrzeba użycia danych pomiarowych, sygnałów i
innego rodzaju danych zgromadzonych w innych programach. Dane takie można przetwarzać
w programie MATLAB symulując np. pracę pewnych układów lub systemów lub wykonu-
jąc określone analizy. Przy dużej liczbie danych ich wprowadzanie do programu MATLAB
z klawiatury byłoby czasochłonne lub wręcz niemożliwe. W takich sytuacjach program MA-
TLAB oferuje specjalne procedury importu danych. Wynikiem obliczeń wykonywanych w
programie mogą być również zbiory o dużej objętości, zawierające np. sygnały o długim cza-
sie trwania. Sygnały te mogą być wykorzystywane w innych programach. Dobrym przykła-
dem jest przetwarzanie sygnałów mowy, które efekty należy przekazać do programu umożli-
wiającego ich odsłuch. Realizują to procedury eksportu danych.
W dalszej części rozdziału omówimy podstawowe metody importu i eksportu danych,
które mogą być przydatne Czytelnikowi w trakcie samodzielnego rozwiązywania niezbyt
trudnych zadań programistycznych.

5.2. Eksport i import danych w formacie binarnym


W formacie binarnym zapisujemy i odczytujemy dane liczbowe w formie plików o roz-
szerzeniu .mat. Do zapisu danych liczbowych używana jest funkcja save:
Instrukcja
save nazwa_pliku
zapisuje w pliku nazawa_pliku wartości liczbowe wszystkich zmiennych występujących w
przestrzeni roboczej. Program C samoczynnie dodaje do nadanej nazwy pliku rozszerzeniem
.mat. Oto przykład
clear % Usuwa wszystkie zmienne z przestrzeni roboczej
x=1:100;
y=x.^2;
save funkcja_kwadratowa;
W katalogu Work pojawia się plik o nazwie funkcja_kwadratowa.mat zawierający warto-
ści zmiennych x i y. Dane te można wprowadzić ponownie do przestrzeni roboczej używając
funkcji load. W tym celu zapisujemy następujące instrukcje:
clear % Usuwa wszystkie zmienne z przestrzeni roboczej
who % Polecenie podaje zawartość przestrzeni roboczej (jest pusta)
load funkcja_kwadratowa.mat % Zapisuje zawartość pliku w przestrzeni roboczej
who % Polecenie sprawdzenia zawartości przestrzeni roboczej
x % W oknie Command Window ukazują się wartości x
y % W oknie Command Window ukazują się wartości x
84

Jeżeli po nazwie pliku umieści się wykaz zmiennych to tylko te zmienne zostaną zapi-
sane w pliku.
clear
x=1:4; y=x.^2; z= 1./x;
save proba x z
Poleceniem load proba ładujemy zmienne zapisane w pliku proba.mat do przestrzeni ro-
boczej programu MATLAB.
clear;
load proba
who %Sprawdzanie aktualnej zawartości przestrzeni roboczej
Program zwraca:
Your variables are:
x y
Zmienne są teraz dostępne w przestrzeni roboczej i mogą być odpowiednio przetwa-
rzane.

5.3. Zapisywanie i czytanie danych w formacie tekstowym


Zmienne z przestrzeni roboczej mogą być zapisane w pliku tekstowym, co umożliwia
korzystanie z nich w innych programach. Dokonuje się tego poleceniem save nazwa_pliku
symbole_zmiennych -ascii.
clear
x=1:100; y=x.^2; z= 1./x;
save tekst x y -ascii
Zmienne x i y zostają zapisane w pliku tekstowym o nazwie tekst. Do nazwy pliku
można dołączyć rozszerzeni .txt. Plik znajduje się w katalogu Work. Można go umieścić w
innym katalogu zmieniając ścieżkę w Current Directory.
Załadowanie tego pliku do pamięci powoduje powstanie jednej zmiennej o nazwie tekst
w postaci prostokątnej macierzy zawierającej w pierwszym wierszu zmienną x a w drugim
zmienną y.
Plik ten może być wczytany np. w programie EXCEL. Uzyskuje się wówczas zapis w
postaci dwóch wierszy o wartościach x i y.
Zawartość pliku tekst wpisujemy do przestrzeni roboczej programu MATLAB nastę-
pującą instrukcją:
load tekst
Należy z naciskiem podkreślić że w przestrzeni roboczej nie występują teraz zmienne x
i y, co sprawdzamy pisząc:
clear
load tekst
x
Undefined function or variable 'x'.
Wartości zmiennej x lub y można wprowadzić do przestrzeni roboczej używając in-
strukcji
x=tekst(1,:);
y=tekst(2,:);
85

5.4. Eksport i import plików dźwiękowych


W programie MATLAB można tworzyć pliki dźwiękowe i dokonywać ich zapisu w
formacie wav.
Plik dźwiękowy można stworzyć z dowolnego jednokolumnowego wektora. Dokonuje
się tego poprzez zapisanie tego wektora poleceniem wavwrite. Wektor powinien zawierać
liczby wyłącznie z przedziału <–1 1 >. Liczby wykraczające poza ten przedział zostaną przy-
cięte na poziome odpowiednio –1 albo1.
Dla przykładu podany zostanie sposób stworzenia dwusekundowego dźwięku o często-
tliwości 800 Hz, próbkowanego z częstotliwością 44100 Hz.
t=(1:2*44100)/44100; %Wektor momentów tworzenia próbek
f=800; % Częstotliwość sygnału
x=sin(2*pi*f*t)’; %Wektor kolumnowy sygnału
wavwrite(x,44100,16,‘ton’) %Zapis sygnału w pliku ton
Sygnał został zapisany w formacie 16-to bitowym.
Jeżeli wektor x istnieje w przestrzeni roboczej, to można odsłuchać sygnał dźwiękowy
poleceniem
sound(x, 44100,16)
Podanie w poleceniu tylko sound(x) spowoduje odtworzenie dźwięku przy częstotliwo-
ści próbkowania 8kHz i z dynamiką 16bitów.
Do programu MATLAB można importować pliki dźwiękowe typu wav. Maja one po-
stać wierszowego lub kolumnowego wektora. Aby po wczytaniu uzyskać pełną informację o
wartościach próbek dźwięku, częstotliwości próbkowania oraz dynamice należy użyć nastę-
pującej instrukcji:
[x,a,b]=wavread(nazwa pliku,N)
W rezultacie poszczególne zmienne będą zawierały:
x - wierszowy (kolumnowy) wektor próbek,
b - częstotliwość próbkowania,
c - dynamika próbek (w bitach).
N - liczba próbek (opcjonalna)
Proces czytania plików można zaprogramować z możliwością wyboru myszą. Poniżej
podano przykład takiego programu
[FN,PN]=uigetfile('*.wav','Wybierz plik do obróbki');
if any(PN)==1
[x,fp,bits]=wavread(char([PN,FN]));
end
Pojawia się okno zatytułowane Wybierz plik do obróbki, w którym można myszą wybrać
interesujący nas plik z rozszerzeniem .wav. Zawartość tego pliku zostanie wczytana do prze-
strzeni roboczej w formie wektora x.
Program MATLAB ma obszerny zestaw funkcji i instrukcji związanych z importem i
eksportem danych. W szczególności dotyczą one importu i eksportu funkcji, obiektów gra-
ficznych, Internetu, kompresji danych, plików dźwiękowych i plików wideo, formatowania,
otwierania, zamykania i konwersji plików, obsługi portu szeregowego itp. Kompletny wykaz
tych instrukcji można znaleźć pisząc: help iofun
86

CZĘŚĆ II. ZASTOSOWANIA PROGRAMU MATLAB


87

6. METODY NUMERYCZNE W ZASTOSOWANIU DO FUNKCJI CIĄGŁYCH


Przedstawione dotychczas operacje matematyczne dotyczyły nieciągłych zbiorów licz-
bowych, którymi zajmuje się dział matematyki zwanej matematyką dyskretną. W innych
działach matematyki, np. w analizie matematycznej, równaniach różniczkowych, geometrii
analitycznej itp. rozpatruje się relacje na zbiorach ciągłych. Pojawiają się w nich zagadnienia,
których rozwiązania analityczne są niemożliwe, lub ich uzyskanie jest bardzo skompliko-
wane. Stosuje się wtedy metody numeryczne, które dają przybliżone rozwiązania liczbowe.
Program MATLAB dysponuje licznymi procedurami z zakresu metod numerycznych, któ-
rych niewielką część przedstawimy w tym podrozdziale.
Charakterystyczną cechą pokazanych dalej metod numerycznych jest to, że odnoszą się
one do funkcji określonych na zbiorach ciągłych. Wymaga to z reguły zdefiniowania takiej
funkcji nim zastosujemy do nie metody numeryczne.

6.1. Wielomiany
Wielomian N-tego stopnia jest ciągłą funkcja jednej zmiennej o następującym zapisie:
WN ( x, a)  a(1)xN  a(2)xN1  ...  a(n)xNn 1  ...  a(N)x  a(N  1)

Jak widać wielomian jest jednoznacznie zdefiniowany przez wartości współczynników


a(n), które mogą być liczbami rzeczywistymi lub zespolonymi.
Innym sposobem definiowania wielomianu jest podanie wartości jego pierwiastków.
Wielomian N-tego stopnia ma N pierwiastków rzeczywistych bądź zespolonych, które ozna-
czymy jako r(n). Powyższy wielomian można wtedy zapisać jako:
W( x, r )  a(1)[ x  r(1)]  [ x  r(2)]  ...  [ x  r(n)]  ...  [ x  r(N)]

Jeżeli znane są pierwiastki wielomianu to funkcja


a=poly(r)
wyznacza wartości współczynników a(n) poczynając od a(1), kończąc na a(N+1).
Pokażemy to na następującym przykładzie:
>> r=[-1 0 1 2 ];
>> a=poly(r)
a=
1 -2 -1 2 0
Zdefiniowany w ten sposób wielomian ma postać:
W( x, a)  x 4  2x 3  x 2  2x

Funkcja
r=roots(a)
wyznacza pierwiastki wielomianu. Dla podanego wyżej wielomianu, zdefiniowanego współ-
czynnikami a(n) mamy:
>> r=roots(a)
r=
0
-1.0000
2.0000
1.0000
88

Podany niżej wielomian ma pierwiastki zespolone. Funkcja roots podaje je w następują-


cej formie:
W( x, a)  x 3  6x 2  21x  26

>> a=[1 -6 21 -26]


>> r=roots(a)
r=
2.0000 + 3.0000i
2.0000 - 3.0000i
2.0000
Wartości wielomianu w punkcie x lub dla wektora bądź macierzy x wyznacza funkcja
W=polyval(a,x)
Przykładowo:
>> W=polyval(a,[2+i*3 0])
W=
0 -26
co jest oczywiste, gdyż pierwsza wartość zmiennej jest pierwiastkiem wielomianu, a druga
daje współczynnik przy zerowej potędze.

6.2. Funkcje wymierne zmiennej zespolonej


Funkcją wymierną nazywamy iloraz wielomianów BM(s,b) i AN(s,a):
BM (s, a) b(1)sM  b(2)sM1  ...  b(m)sMm 1  b(M  1)

A N (s, b) a(1)sN  a(2)sN1  ...  a(n)sNn 1  a(N  1)

Funkcje wymierne mają szerokie zastosowanie w analizie i syntezie obwodów i syste-


mów, gdyż opisują m.in. transmitancję układów liniowych. Analiza transmitancji wymaga
często znajomości zer i biegunów funkcji wymiernych. W celu ich wyznaczenia powyższą
funkcję wymierną można zapisać w następującej postaci:
BM (s, b) r(1) r(2) r(N)
   ...   K(s, k )
A N (s, a) s  p(1) s  p(2) s  p(N)

gdzie r(n) są residuami, p(n) – biegunami funkcji, a K(s,k) – wielomianem stopnia M-N+1. Jeżeli
M=N-1, to wielomian K(s,k) nie występuje.
Jeżeli pewien n-ty biegun występuje U-krotnie, czyli p(n)=p(n+1)=…=p(n+U-1), wówczas
w powyższym wzorze mamy:
BM (s, b) r(1) r(n) r(n  1) r(n  U) r(N  U)
  ...   ...  ...   K(s, k )
A N (s, a) s  p(1) s  p(n) [s  p(n)] 2
[s  p(n)] U s  p(N  U)

Program MATLAB® dysponuje funkcją residue, która wyznacza residua r, bieguny p i


współczynniki k, jeżeli funkcji wymiernej opisanej współczynnikami b i a. Zapis tej funkcji
jest następujący:
[R,P,K]=residue(B,A)
Wektory B i A zawierają współczynniki b i a wielomianu w liczniku i mianowniku.
Funkcja zwraca wektor R zawierający kolejne residua r, wektor P – kolejne bieguny p, a
wektor K – kolejne współczynniki k wielomianu K(s,k).
Weźmy jako przykład funkcję:
89

B 2 ( s) 6s2  46s  86
 3
A 3 (s) s  12s2  47s  60

Oto program wyznaczający residua i bieguny tej funkcji:


>> B=[6 -46 86];
>> A =[1 -12 47 -60];
>> [R,P,K]=residue(B,A)
R=
3.0000
2.0000
1.0000
P=
5.0000
4.0000
3.0000
K=
[]
Zgodnie z przewidywaniami wektor K jest pusty, gdyż stopień wielomianu w liczniku
jest o jeden mniejszy od stopnia mianownika.
Można łatwo sprawdzić, że wyznaczone bieguny są zerami mianownika:
>> P=roots(A)
P=
5.0000
4.0000
3.0000
Dla tych wartości s rozpatrywana funkcja osiąga nieskończoność.
W technice większe znaczenie mają funkcje wymierne o biegunach zespolonych. Wy-
znaczmy residua i bieguny takiej funkcji, np.:
B 3 ( s) 6s3  34s2  80s  60
 4
A 4 (s) s  8s3  32s2  48s  36

Definiujemy tą funkcję i wyznaczamy jej poszukiwane wartości:


>> B =[6 -34 80 -60];
>> A =[1 -8 32 -48 36];
>> [R,P,K]=residue(B,A)
R=
2.0000 - 0.0000i
2.0000
1.0000 + 0.0000i
1.0000 - 0.0000i
P=
3.0000 + 3.0000i
3.0000 - 3.0000i
1.0000 + 1.0000i
1.0000 - 1.0000i
K=
[]
Wszystkie bieguny są tu zespolone, a dodatkowo parami sprzężone.
Zamieszczony niżej program sporządza trójwymiarowy wykres rozpatrywanej funkcji,
który pokazano na rys. 6.1.
% OBLICZENIA
A= [1 -8 32 -48 36]; % wektor współczynników wielomianu mianownika
90

B=[6 -34 80 -60]; % wektor współczynników wielomianu mianownika


res=0:0.005:5; % część rzeczywista zmiennej s
ims=-5:0.005:5; % część urojona zmiennej s
[X,Y]=meshgrid(res,ims); % część rzeczywista X i urojona S w formie macierzowej
S=X+i*Y; % macierz zmiennej s
L=polyval(B,S); % wartości licznika
M=polyval(A,S); %wartości mianownika
W=abs(L./M); % wartości bezwzględne funkcji wymiernej

% GRAFIKA
% Operacje ograniczenia wykresu do wartości 10
P=W<10; % Macierz pomocnicza wyznaczająca elementy spełniające
nierówność
WP=W.*P; % Macierz wartości spełniających nierówność
R=W>=10; % Macierz pomocnicza wyznaczająca elementy spełniające
nierówność
WO=WP+R*10; % Macierz przeznaczona do reprezentacji graficznej
% Wykres
surf(res,ims,WO,'linestyle','none')
xlabel('re(s)');ylabel('im(s)')
camlight(10,-5)
lighting phong

Rys. 6.1. Wykres funkcji wymiernej zmiennej zespolonej s.


Przy wykonaniu powyższego wykresu pojawiają się dwa problemy, które wymagają
komentarza. Po pierwsze należy utworzyć macierz zmiennej zespolonej s tak, aby w kolum-
nach występowały kolejne wartości części rzeczywistej zmiennej s, a w wierszach – części
urojone. Wykorzystano do tego celu funkcję meshgrid, którą stosuje się w grafice trójwymia-
rowej. Działanie tej funkcji ilustruje prosty przykład:
>> x=[1:4];
>> y=[-2:2];
>> [X,Y]=meshgrid(x,y)
91

X=
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
Y=
-2 -2 -2 -2
-1 -1 -1 -1
0 0 0 0
1 1 1 1
2 2 2 2
>> S=X+i*Y
S=
1.0000 - 2.0000i 2.0000 - 2.0000i 3.0000 - 2.0000i 4.0000 - 2.0000i
1.0000 - 1.0000i 2.0000 - 1.0000i 3.0000 - 1.0000i 4.0000 - 1.0000i
1.0000 2.0000 3.0000 4.0000
1.0000 + 1.0000i 2.0000 + 1.0000i 3.0000 + 1.0000i 4.0000 + 1.0000i
1.0000 + 2.0000i 2.0000 + 2.0000i 3.0000 + 2.0000i 4.0000 + 2.0000i
Po drugie, wartości funkcji w biegunach są równe nieskończoności, co uniemożliwia
sporządzenie wykresu. Obcięto więc funkcję na poziomie 10, co realizują instrukcje zamiesz-
czone w programie. Z przebiegu wykresu należy domyślać się, że występujące na nim „ko-
miny” dążą do nieskończoności.
Funkcja
[B,A]=residue(R,P,K)
zwraca wartości współczynników wielomianu w liczniku i w mianowniku, analogicznie jak
funkcja poly w odniesieniu do wielomianów.

6.3. Miejsca zerowe, minima i maksima funkcji


Bardzo częstym problemem w matematyce jest znalezienie miejsc zerowych funkcji
f(x),czyli rozwiązania równania f(x)=0. Jeżeli metody analityczne zawodzą, można się uciec
do metod numerycznych. Wyniki są co prawda przybliżone, lecz błąd można zmniejszyć
zwiększając liczbę operacji wykonywanych przez program. Analogiczne problemy pojawiają
się przy poszukiwaniu minimów i maksimów funkcji.
W ogólności wyznaczanie zer funkcji ciągłych metodami numerycznymi nie jest zada-
niem prostym. Dlatego program MATLAB dysponuje tylko jedną funkcją fzero, która wy-
znacza miejsce zerowe punktu w otoczeniu wskazanego punktu x0, leżącego w pobliżu miej-
sca zerowego. Jak widać wymaga to wstępnego oszacowania położenia punktu zerowego
funkcji, co jest pewnym utrudnieniem. Pokażemy to na przykładzie wielomianu:
y  x 3  4x 2  x  6 .

W celu znalezienia przybliżonych położeń miejsc zerowy wykonujemy wykres tej funk-
cji, który pokazano na rys. 6.2.
92

Rys. 6.2. Wykres wielomianu trzeciego stopnia.


Załóżmy, że oszacowaliśmy następujące położenia miejsc zerowych: x01=-1.1, x02=1.9,
x03=3.2. Oszacowania tego dokonaliśmy specjalnie z widocznymi błędami wyłącznie w celach
dydaktycznych.
Do wyznaczenia miejsc wykorzystamy funkcję:
x=fzero(y,x0)
w której poszukiwanie miejsce zerowe oznaczono jako x, przybliżone położenie miejsca ze-
rowego jako x0, zaś y jest funkcją ciągłą wymagającą zdefiniowania. W podanym niżej pro-
gramie do zdefiniowania funkcji y użyjemy instrukcji inline. Można również wpisać bezpo-
średnio w miejsce y wyrażenie definiujące funkcje, ujmując je w apostrofy ‘y’.
y=inline('x.^3-4*x.^2+x+6') % definicja funkcji
x01=fzero(y,-1.1) % pierwsze miejsce zerowe
x02=fzero(y,1.9) % drugie miejsce zerowe
x03=fzero(y,3.2) % drugie miejsce zerowe
y=
Inline function:
y(x) = x.^3-4*x.^2+x+6
x01 =
-1
x02 =
2
x03 =
3.0000
Posługując się metodami analizy matematycznej można wyznaczyć zera, Mają one na-
stępujące współrzędne: x1=-1, x2=2 i x3=3. Wyznaczmy zatem błędy obliczeń numerycznych:
dx01=x01+1
dx02=x02-2
dx01=x03-3
dx01 =
0
dx02 =
93

0
dx03 =
4.4409e-016
Jak widać, dwa pierwsze miejsca zerowe zostały wyznaczone z pełną dokładności osią-
ganą w programie MATLAB zaś trzeci – z bardzo małym błędem.
Jeżeli chcemy zawęzić przedział, w którym poszukiwane jest miejsce zerowe, wtedy
zamiast liczby x0 podajemy granice przedziału, np.:
>> x01=fzero(y,[-1.1 -0.9])
x01 =
-1
Znając przebieg funkcji (np. z jej wykresu), można napisać program, który sam wyzna-
czy przybliżone położenie miejsc zerowych. Oto przykład takiego programu:
y=inline('x.^3-4*x.^2+x+6'); %definicja funkcji
x=-2:0.1:4; % wektor zmiennej x
yn=y(x); % wektor dyskretnej funkcji y
yu=yn<0; % wyznaczanie przedziałów, w których funkcja jest ujemna
yo=abs(diff(yu)); % różniczkowanie powyższej funkcji
no=find(yo); % numery przybliżonych miejsc zerowych
xo=x(no) % wartości przybliżonych miejsc zerowych
x01=fzero(y,xo(1)) % pierwsze miejsce zerowe
x02=fzero(y,xo(2)) % drugie miejsce zerowe
x03=fzero(y,xo(3)) % trzecie miejsce zerowe
Kolejne operacje na funkcji ilustruje rys. 6.3.

Rys. 6.3. Przybliżone wyznaczanie miejsc zerowych.


Do wyznaczania minimów i maksimów służą funkcje:
x=fmin(y,x1,x2)
x=fminbnd(y,x1,x2)
x=fmins(y,xm)
94

Pierwsze z tych funkcji wyznaczają minimum funkcji y (jeżeli istnieje) w przedziale


(x1,x2).W drugiej funkcji podaje się wektor xm zawierający wartości zmiennej x, w pobliżu
których spodziewamy się minimów.
W rozpatrywanym wyżej przykładzie minimum funkcji leży pomiędzy pierwszymi
miejscami zerowymi. Wyznaczamy je więc następująco:
xmin=fminbnd('x.^3-4*x.^2+x+6',2,3)
xmin =
2.5352

Położenie minimum obliczone analitycznie wynosi xmin  (4  13 ) / 3 . Sprawdźmy, z


jaką dokładnością zostało ono wyznaczone numerycznie:
dxmin=xmin-(4+sqrt(13))/3
dxmin =
9.8251e-007
Do wyznaczenia maksimum funkcji posługujemy się również funkcjami fmin, fminbnd i
fmins,
przy czym zmieniamy najpierw maksimum na minimum przez zmianę znaku funkcji.
Mamy zatem:
y=inline('-(x.^3-4*x.^2+x+6)')
xmax=fminbnd(y,-1,2)
ymax=-y(xmax)
dxmax=xmax-(4-sqrt(13))/3
Program zwraca:
xmax =
0.1315
ymax =
6.0646
dxmax =
-5.9908e-006
Zauważmy, że w przykładzie rozpatrywaną funkcją jest wielomian. Miejsca zerowe
wielomianu można wyznaczyć prościej jako:
>> xo=roots(a)
xo =
3.0000
2.0000
-1.0000
Opisana wyżej metoda dotyczy wszystkich funkcji definiowanych wyrażeniami mate-
matycznymi, np. funkcji trygonometrycznych, wykładniczych, logarytmicznych i ich kombi-
nacji.

6.4. Całkowanie numeryczne


Całkowanie numeryczne dotyczy wyłącznie całek oznaczonych. Jeżeli całka ma okre-
ślone, stałe granice, to jej wynikiem jest liczba. Gdy jedna z granic jest zmienną, to wynikiem
całkowania numerycznego jest ciąg liczbowy. Ciąg ten ma wartości zbliżone do wartości
całki w określonych punktach. Numerycznie, co oczywiste, nie można otrzymać wzoru na
całkę nieoznaczoną.
Najprostszą metodą całkowania numerycznego jest zastąpienie go operacją sumowania.
W tym celu należy funkcję ciągłą zastąpić funkcją dyskretną i dokonać sumowania wartości
95

tej funkcji. Czym mniejszy jest odstęp między wartościami niezależnej zmiennej dyskretnej,
tym wynik sumowania jest bardziej zbliżony do wartości całki. Oto prosty przykład.
Obliczmy wartość następującej całki:
1


y  sin(x )dx .
0

Z rozwiązania analitycznego wynika, że wartość tej całki wynosi y=2/π.


Dzielimy przedział całkowania na N równych części i zastępujemy nieskończenie mały
przyrost dx przez przyrost skończony x, którego wielkość jest długością przedziału całkowa-
nia podzieloną przez N. W naszym wypadku x=1/N. Powyższą całkę zastępujemy następującą
sumą:
N


1
y sin(n / N) , gdzie n=1,2,3,…,N
N n 1

Powyższe obliczenia wykonywane są przez podany niżej program.


N=input(‘N=’)
n=1:N;
y=sum(sin(pi*n/N)/N % „całkowanie” numeryczne
dy=1-pi*y/2 % względny błąd obliczeń
Dla N=10 błąd względny wynosi 8.2 10-3, a dla N=100 maleje do 8.2 10-5. Jak widać, na-
wet przy stosunkowo małej liczbie przedziałów, błąd metody w tym wypadku jest niewielki.
Nie jest to jednakże regułą, zwłaszcza gdy funkcja zmienia się szybko w przedziale całkowa-
nia.
MATLAB dysponuje dwiema funkcjami całkowania numerycznego, a mianowicie
funkcją quad i funkcją quad8. Pierwsza z nich wykorzystuje metodę Simsona, a druga ośmio
przedziałową metodę Newtona-Cotesa. Podstawowy zapis obu funkcji jest następujący:
y=quad(f,a,b)
gdzie f jest nazwą funkcji, zaś a i b są granicami całkowania.
Funkcja f musi być określona na zbiorze ciągły, co oznacza, że każdej dowolnej zmien-
nej w granicach całkowania a,b musi być przyporządkowana jednoznacznie wartość funkcji.
Funkcja f może być definiowana na dwa sposoby, a mianowicie może to być funkcja
zapisana jako plik z rozszerzeniem .m, lub przy wykorzystaniu funkcji inline. W pierwszym
wypadku wstawiamy w miejsce f łańcuch z nazwą funkcji, np. ‘sin’ lub @sin. Jeżeli całkowana
funkcja nie znajduje się w zbiorze plików, wówczas można ją zdefiniować. Całkowana wyżej
funkcja sin(πx) nie jest standardową funkcją, a więc trzeba ją zdefiniować. Oto odpowiednie
instrukcje:
function [f]=sinfun(x)
f=sin(pi*x) % Uwaga: zdefiniowaną funkcję należy umieścić w folderze work jako sinfun.m
y=quad(‘sinfun’,0,1)
dy=1-pi*y/2
Błąd względny wynosi dy=1.8 10-9, a więc jest znacznie mniejszy od otrzymanych po-
przednio. Wykorzystując funkcję quad8 uzyskujemy jeszcze bardziej dokładny wynik, gdyż
błąd jest równy 5.4 10-14.
Zapis funkcji quad lub quad8 można uzupełnić o dodatkowe parametry, a mianowicie
quad(f,a,b,tol,trace). W miejsce tol należy wpisać zakładaną tolerancję obliczeń (domyślnie
10-3), a w miejsce trace dowolną liczbę różną od zera. Funkcje quad i quad8 wykonują wtedy
96

wykresy zawierający punkty, w których dokonywana jest interpolacja funkcji odpowiednim


wielomianem.
Zamiast definiowania nowej funkcji można wykorzystać funkcję inline, która ma nastę-
pujący zapis ogólny:
f=inline(‘wzór’,’arg1’,arg2’,…)
W łańcuchu wpisujemy wyrażenie (wzór) opisujący całkowaną funkcję. Wzór ten może
zawierać argumenty arg1, arg2,…, które w zapisie wzoru będą traktowane jako zmienne lub
parametry. Posługiwanie się funkcją inline ilustruje następujący przykład:
f=inline(‘sin(pi*x)’);
y=quad(f,0,1)
y=
0.6366

6.5. Równania różniczkowe


Program MATLAB umożliwia numeryczne rozwiązywanie równań różniczkowych
trzech typów, a mianowicie:
 zwyczajnych równań różniczkowych pierwszego rzędu i ich układów (funkcje
ode od ang. ordinary differential equation)

 zwyczajnych równań różniczkowych pierwszego rzędu i ich układów z


funkcjami opóźnionymi (funkcje dde od ang. delay differential equation)
 cząstkowych równań różniczkowych (funkcje pdepe od ang. partial differential
equation)
Ograniczymy się tu do pokazania metody rozwiązywania zwyczajnych równań różnicz-
kowych, które mają szerokie zastosowania techniczne, a z drugiej strony nie są zbyt skompli-
kowane. Funkcje ode rozwiązują układy następujących równań różniczkowych:
dy1
 f1 ( t, y1, y 2 ,...y n )
dt
dy 2
 f2 ( t, y1, y 2 ,...y n )
dt
....................................
dyn
 fn ( t, y1, y 2 ,...y n )
dt
Do rozwiązania takiego układu równań można użyć jednej z następujących funkcji typu
ode: ode45, ode23, ode113, ode15s, ode23s, ode23t i ode23tb. Poszczególne funkcje różnią się
metodami rozwiązywania układów równań i pewnymi innymi szczegółami, które tu pomi-
niemy. Wszystkie te funkcje mają następującą podstawowa strukturę:
[T,Y] = ode(odefun,tspan,y0,options,p1,p2...)
gdzie
 T jest wektorem kolumnowym zmiennej niezależnej t
 Y jest
macierzą zawierającą wyniki rozwiązań (wartości funkcji y1, y2,...yn w
punktach t; wartości te są umieszczone w kolumnach 1, 2, ...,n)
 ode jest nazwą funkcji z podanej wyżej listy
 odefun jest wektorem kolumnowym zawierającym definicje funkcji f1, f2,...,fn
97

 tspanjest wektorem [to tk] zawierającym granice przedziału zmiennej t, w któ-


rych wyznaczane jest rozwiązanie układu równań; przy większej liczbie elemen-
tów oznaczają one punkty, w których wyznaczane są rozwiązania
 y0 jest wektorem zawierającym wartości początkowe [y1(t0) y2(t0),..., yn(t0)]
 pozostałe parametry są opcjonalne.
Sposób posługiwania się omówionymi funkcjami pokażemy na kilku prostych przykła-
dach zaczerpniętych z układów elektrycznych. Zaczniemy od wyznaczenia przebiegu prądu w
układzie RL, pokazanym na rys. 6.4.

i(t) L

u(t) R

Rys. 6.4. Obwód elektryczny RL.


Równanie różniczkowe opisujące prąd i(t) w tym układzie ma następującą postać
di
L  Ri  u( t )
dt
Rozwiążemy najpierw to równanie przy założeniu, że u(t)=0 dla t>0, a prąd w momencie
czasu t=0 jest równy i(0)=I0. W praktyce jest to przypadek, gdy w momencie t=0 wyłączamy
stałe napięcie U0 podawane wcześniej do wejścia układu i wtedy I0=U0/R. Równanie to
zapiszemy w formie przyjętej w funkcjach ode.
di
 (R / L)i ,
dt
co jest w ogólnej formie odpowiednikiem zapisu
dy dy
 Py lub  f ( t, y )
dt dt
Zmienna t jest w tym wypadku domyślna.
Nadajemy parametrowi P wartość liczbową i definiujemy funkcję nazwaną w zapisie
funkcji jako odefun. Jak wiadomo, =L/R jest stałą czasową układu. Niech R=1k, a L=10 mH.
Stała czasowa układu wynosi więc 10-5 s, a parametr P=1/=105. Chcemy znać przebieg prądu
w czasie dłuższym od stałej czasowej np. 510-5 s, w związku z tym tspan=[0 5*10^-5]. Jeżeli
U0=1V, wtedy I0=10 A. Dane te umożliwiają rozwiązanie równania różniczkowego. Za-
-3

stosujemy funkcję ode23, która rozwiązuje równania metodą Runge-Kutta.


>> f=inline('-10^5*I','t','I')
f=
Inline function:
f(t,I) = -10^5*I
>> [t,I]=ode23(f,[0 5*10^-5],10^-3);
>> plot(t,I)
>> xlabel('t [s]');ylabel('I [A]')
98

i otrzymujemy rozwiązanie w formie graficznej widocznej na rys. 6.5.

Rys. 6.5. Przebieg prądu w układzie RL.


Wartości funkcji program wyznaczył tylko w 13 punktach. Jeżeli chcemy zwiększyć ich
liczbę wtedy piszemy np. [0;10^-6:5*10^-5] i wyniki otrzymamy w 51 punktach.
Otrzymany wynik jest zgodny z teorią, gdyż analityczne rozwiązanie ma postać:
U0 t
I( t )  exp( ).
R L /R
Na rysunku różnice są niewidoczne.
Należy zwrócić uwagę na sposób definiowania funkcji f (odefun). Konieczne jest poda-
nie zmiennych t i I we właściwej kolejności, gdyż funkcja ode interpretuje właściwie tylko
funkcje o zapisie f(t,y).
Rozpatrywane wyżej równanie jest równaniem jednorodnym i dlatego nie pojawiła się
w jawnej formie zmienna t w zapisie funkcji odefun. Podamy teraz przykład rozwiązywania
równania niejednorodnego. Założymy mianowicie, że układ pokazany na rys. 6.4 jest pobu-
dzany napięciem sinusoidalnym o częstotliwości f0= 1 MHz i amplitudzie napięcia U0=1V. Na-
pięcie to przyłożono w momencie czasu t=0. W momencie tym prąd nie płynął przez układ.
Zadaniem naszym jest wyznaczenie przebiegu napięcia na oporności R.
Równanie opisujące prąd w układzie ma więc następującą postać:
dI
L  RI  U0 sin(2f0 t ) .
dt
W celu nadania mu właściwej formy piszemy:
dI R U
  I  0 sin(2f0 t )
dt L L
i wstawiamy wyznaczone wcześniej wartości liczbowe
dI
 105 I  10 2 sin(2106 t ) .
dt
99

Następujący program wyznacza rozwiązanie tego równania.


f=inline('-10^5*I+10^2*sin(4*pi*10^5*t)','t','I')
f=
Inline function:
f(t,I) = -10^5*I+10^2*sin(4*pi*10^5*t)
>> [t,I]=ode23(f,[0:10^-7:5*10^-5],0);
>> U=I*10^3 % Napięcie U=I·R
>> plot(t,U,'k')
>> xlabel('t [s]');ylabel('U [V]')
Przebieg napięcia pokazano na rys. 6.6.

Rys. 6.6. Przebieg napięcia na oporności R.


Równania różniczkowe wyższych rzędów rozwiązuje się jako układ równań pierwszego
rzędu, który podano na początku tego punktu. Pokażemy to na przykładzie równania drugiego
rzędu, opisującego szeregowy układ rezonansowy, którego schemat przedstawia rys. 6.7.

i(t) L C

Rys. 6.7. Schemat szeregowego obwodu rezonansowego.


Jednorodne równanie różniczkowe tego obwodu ma postać:
d2i di 1
L 2
R  i  0
dt dt C
Po podzieleniu równania stronami, i podstawieniu i=y1 można je zapisać jako:
100

d2 y1 R dy1 1
2
  y1  0
dt L dt LC
Oznaczamy
dy1
y2 
dt
Po podstawieniu tej zależności do równania różniczkowego otrzymujemy
dy 2 R 1
 y2  y1  0
dt L LC
Powyższym równaniom nadajmy formę układu równań dostosowaną do wymogów
funkcji ode.
dy1
 y2
dt
dy2 1 R
 y1  y 2
dt LC L
Parametrom RLC należy nadać teraz wartości liczbowe. Dobierzemy je tak, aby często-
tliwość rezonansowa f0=10 KHz, a dobroć Q=5 Przyjmując dodatkowo, że R=1 , otrzymu-
jemy:
QR 5 4
L  10 [H]
2f0 2

oraz
1 1 5
C  10 [F]
( 2)2 f02L 

Mamy wtedy
R 2 4 1
 10 oraz  ( 2)2108
L 5 LC
Po wstawieniu tych wartości do układu równań różniczkowych otrzymujemy:
dy1
 y2
dt
dy2 2
 ( 2)2108 y1  104 y 2
dt 5
Kolejnym krokiem jest zdefiniowanie funkcji odefun. Funkcja ta musi być zapisana w
formie wektora kolumnowego, przy czym w pierwszym wierszu jest zdefiniowana funkcja
dotycząca pierwszego równania, w drugim – drugiego itd., jeżeli mamy więcej równań. W
zapisie funkcji należy używać oznaczeń y(1), y(2) ..., gdyż wyniki są zapisywane w macierzy y
i konieczne jest wskazanie miejsca usytuowania y1, y2 w tej macierzy.
Warunki początkowe muszą być zapisane w formie wektora kolumnowego; w pierw-
szym wierszu y1(0), a w drugim y2(0). Przyjmiemy, że prąd początkowy wynosi y1(0)=1 A, a
jego pochodna y2(0)=0.
Funkcję odefun, po jej nazwaniu, można zdefiniować jako funkcję z rozszerzeniem .m i
umieścić ją w katalogu work. Można także użyć funkcji inline, co uczynimy w tym przykła-
dzie. Program rozwiązujący nasze równanie różniczkowe ma wtedy następujący zapis:
101

f=inline('[y(2);-(2*pi)^2*10^8*y(1)-2*pi* 10^4*y(2)/5]','t','y') %średnik wskazuje, że mamy wektor


kolumnowy
f=
Inline function:
f(t,y) = [y(2);-(2*pi)^2*10^8*y(1)-2*pi* 10^4*y(2)/5]
[T,Y]=ode23(f,[0 10^-3],[1;0]);
plot(T,Y(:,1),'k') % wykres rozwiązania (umieszczone jest w pierwszej kolum-
nie macierzy Y)
o=exp(-10^4*pi/5*T); % teoretyczny przebieg obwiedni
hold on
plot(T,o,'k') % wykres obwiedni

Rys. 6.8. Przebieg prądu w szeregowym obwodzie RLC wymuszony prądem początkowym i(0)=1A.
W następnym przykładzie pokażemy, w jaki sposób można wyznaczyć przebieg prądu
w rozpatrywanym wyżej obwodzie, gdy jest on pobudzany napięciem sinusoidalnym u(t) o
częstotliwości f1=0.5f0 i amplitudzie U0=1 V. Napięcie to jest dołączane w momencie czasu t=0.
Obwód taki jest pokazany na rys. 6.9.

i(t) L C

u(t) R

Rys. 6.9. Obwód rezonansowy pobudzany napięciem u(t).


Równanie różniczkowe układu pokazanego na rysunku ma następującą postać:
di 1 
L  Ri   idtI  u( t )
dt C0
102

Aby nadać mu formę równania używaną w funkcjach ode, należy obustronnie je zróż-
niczkować. Zakładając, że u(t)=U0sin(2f1t) oraz oznaczając i=y1 otrzymujemy:
d2 y1 R dy1 1 U
2
  y1  2f1 0 cos( 2f1t ) .
dt L dt LC L
Dalej postępujemy, jak w poprzednim przykładzie. Oznaczając
dy1
 y2
dt
i podstawiając nową zmienną do równia różniczkowego mamy:
dy2 1 R U
 y1  y 2  2 0 cos( 2f1t )
dt LC L L
Dwa ostatnie równania tworzą układ równań różniczkowych, który można rozwiązać
używając funkcji ode. Zachowując wartości LC z poprzedniego przykładu i zmniejszając
wartość R czterokrotnie otrzymujemy ostatecznie:
dy1
 y2
dt

dy2 2 4 (2)2 8
 ( 2)2108 y1  10 y 2  10 cos( 10 4 t )
dt 20 10
Przy zerowych warunkach początkowych program rozwiązujący niejednorodne równa-
nie różniczkowe przedstawia się następująco:
f=inline('[y(2);-(2*pi)^2*10^8*y(1)-2*pi* 10^4*y(2)/20+(2*pi)^2*10^8*cos(pi*10^4*t)/10]','t','y')
f=
Inline function:
f(t,y) = [y(2);-(2*pi)^2*10^8*y(1)-2*pi* 10^4*y(2)/20+(2*pi)^2*10^8*cos(pi*10^4*t)/10]
[T,Y]=ode23(f,[0 2*10^-3],[0;0]);
plot(T,Y(:,1),'k')

Rys. 6.10. Przebieg prądu w szeregowym obwodzie rezonansowym pobudzonym napięciem sinuso-
idalnym o częstotliwości różnej od częstotliwości rezonansowej.
103

Po włączeniu napięcia sinusoidalnego występuje stan przejściowy, w którym na prąd o


częstotliwości pobudzenia nakłada się odpowiedź obwodu o jego częstotliwości rezonanso-
wej. W stanie ustalonym częstotliwość prądu jest równa częstotliwości przyłożonego napię-
cia.
Jeżeli częstotliwość pobudzenia jest równa częstotliwości rezonansowej, to po modyfi-
kacji funkcji f(t,y) otrzymujemy:
f=inline('[y(2);-(2*pi)^2*10^8*y(1)-2*pi* 10^4*y(2)/20+(2*pi)^2*10^8*cos(2*pi*10^4*t)/5]','t','y')
f=
Inline function:
f(t,y) = [y(2);-(2*pi)^2*10^8*y(1)-2*pi* 10^4*y(2)/20+(2*pi)^2*10^8*cos(2*pi*10^4*t)/5]
>> [T,Y]=ode23(f,[0 2*10^-3],[0;0]);
>> plot(T,Y(:,1),'k')

Rys. 6.11. Przebieg prądu w szeregowym obwodzie rezonansowym pobudzonym napięciem sinuso-
idalnym o częstotliwości równej częstotliwości rezonansowej.
104

7. GENERACJA, ANALIZA I PRZETWARZANIE SYGNAŁÓW


7.1. Sygnały analogowe i dyskretne
W systemach elektronicznych, telekomunikacyjnych i informatycznych do przesyłania
informacji używane są sygnały. Z fizycznego punktu widzenia sygnałami są zmiany napięcia,
prądu lub innych wielkości fizycznych zachodzące w czasie według ustalonych reguł, które
wiążą te wielkości z informacją. Z matematycznego punktu widzenia sygnały takie mogą być
opisane funkcjami, których argumentem jest czas. W każdym momencie czasu określona jest
wielkość sygnału. Ze względu na fizyczne realia można również zakładać, że są to funkcje
ciągłe, ale dla potrzeb teoretycznych założenie takie nie jest konieczne. W celu ułatwienia
analizy przyjmuje się często, że sygnały nie są ograniczone w czasie, co oczywiście odbiega
od rzeczywistości. Analizę sygnałów ułatwia także niekiedy pozbawienie ich fizycznego wy-
miaru i przyjmowanie, że funkcje opisujące sygnały są bezwymiarowe. Ogólnie sygnały takie
nazywamy sygnałami analogowymi, a układu i systemy, w których występują i są przetwa-
rzane – analogowymi.
W ostatnich dziesięcioleciach dużego znaczenia nabrały sygnały dyskretne, co wiąże się
z powszechnym stosowaniem techniki komputerowej i realizowanych w komputerach obli-
czeniach numerycznych. W odróżnieniu od sygnałów analogowych, wartości liczbowe opi-
sujące sygnał są określone tylko w pewnych punktach czasu, najczęściej odległych o stały
przedział czasu. W pozostałych punktach osi czasu sygnały dyskretne są nieokreślone, co nie
znaczy, że mają wartość zerową.
Sygnały dyskretne otrzymuje się najczęściej w wyniku próbkowania rzeczywistych sy-
gnałów analogowych. Próbkowanie polega na mierzeniu wartości sygnału s(t) w określonych
punktach czasu. Najczęściej próbkowanie odbywa się w sposób okresowy, a wówczas można
go zapisać jako:
s(n)=s(nTs)
gdzie n jest numerem kolejnej próbki sygnału, a Ts – odstępem czasu między sąsiednimi prób-
kami, czyli okresem próbkowania.
Sygnał s(n) jest sygnałem dyskretnym. Kolejne próbki sygnału zapisujemy jako s(1),
s(2), s(3),....Należy zwrócić uwagę, że w zapisie sygnału dyskretnego nie występuje okres
próbkowania Ts, co pozbawia sygnał dyskretny odniesienia do fizycznej skali czasu. W kon-
sekwencji analiza i przetwarzanie takiego sygnału odbywa się również bez związku z rzeczy-
wistym czasem. Próbki sygnału stanowią zatem jedynie elementy ciągu liczbowego. Uzy-
skane wyniki nie są jednoznaczne i mogą dotyczyć całego zbioru sygnałów, którego odzwier-
ciedleniem jest jeden ciąg próbek. Pokażemy to na przykładzie sygnału sinusoidalnego
s(t)=sin(2f0 t+). Jeżeli sygnał taki poddamy próbkowaniu z okresem Ts, to otrzymamy nastę-
pujący sygnał dyskretny:
s(n)=sin(2f0/Tsn+)= sin(2an+)
Wszystkie sygnały, w których f0/Ts=a przechodzą w jednakowe sygnały dyskretne.
Analiza i przetwarzanie sygnału s(n) dotyczy zatem wszystkich sygnałów analogowych speł-
niających podany warunek. Chcąc odnieść wyniki obliczeń do rzeczywistego sygnału cią-
głego musimy znać okres próbkowania Ts (lub częstotliwość próbkowania Fs=1/Ts).
Aby informacja zawarta w sygnale analogowym została w pełni zachowana w sygnale
dyskretnym, konieczne jest spełnienie dwóch warunków:
 sygnał analogowy musi mieć ograniczone widmo,
105

 częstotliwość próbkowania musi być większa do podojonej częstotliwości


granicznej widma sygnału.
Jest to tzw. kryterium Nyquista. Sygnały stosowane w praktyce nigdy nie mają ograni-
czonego widma, a zatem kryterium Nyquista nie jest w ścisłym sensie nigdy spełnione. Mu-
simy więc pogodzić się z faktem, że wyniki obliczeń numerycznych nie są w pełni zgodne z
rzeczywistością. Można jednak zadbać, aby błędy obliczeń były na tyle małe, żeby bez nega-
tywnych skutków mogły być zaniedbane. Ważna jest nade wszystko świadomość, że błędy
takie występują w symulacji sygnałów i w procesie ich przetwarzania. Podkreślmy, że ich
źródłem nie jest tylko skończona dokładność obliczeń, lecz także i przede wszystkim dyskre-
tyzacja (próbkowanie) sygnałów.
W teorii sygnałów dyskretnych można zakładać, że liczba próbek sygnałów jest nie-
skończenie wielka, co odpowiada założeniu o nieskończonym czasie trwania sygnału cią-
głego. Jednakże w obliczeniach numerycznych wykorzystujących sygnały dyskretne liczba
próbek musi być ograniczona. W konsekwencji obliczenia numeryczne dotyczą często, lecz
nie zawsze, jedynie fragmentu sygnału. Należy o tym pamiętać, gdy chcemy wyniki obliczeń
numerycznych uogólnić na sygnał o nieograniczonym czasie trwania. W szczególności odnosi
się to do analizy widmowej sygnałów. Jest to także jedną z przyczyn, że nie jest spełnione
kryterium Nyquista. Z teorii sygnałów wiadomo bowiem, że sygnał o skończonym czasie
trwania ma nieograniczone widmo.

7.2. Generacja sygnałów impulsowych


Wszystkie sygnały występujące w rzeczywistych układach i systemach są ciągłe. Jed-
nakże w celu uproszczenia ich analizy rozpatruje się sygnały zwane impulsowymi, a zalicza
się do nich takie sygnały, w których następują bardzo szybki zmiany wartości. W punktach
szybkiej zmiany wartości pochodna sygnału ma bardzo duże wartości bezwzględne lub
szybko zmienia znak.
Zajmiemy się najpierw prostym sygnałem impulsowym w postaci impulsu prostokąt-
nego o wysokości U i czasie trwania ti. Impuls taki pokazano na rys. 8.1.

s(t)

ti t

Rys.7.1. Impuls prostokątny


Aby impuls ten przetransponować w dziedzinę sygnałów dyskretnych należy dokonać
jego próbkowania. W tym celu trzeba wybrać okres próbkowania Ts oraz ustalić liczbę próbek
N. Jak wiadomo, widmo tego impulsu jest nieograniczone, a zatem – ściśle rzecz biorąc –
kryterium Nyquista nie może być spełnione. Wybieramy zatem taki okres próbkowania, aby
błędy były akceptowalnie małe. Wskazówką jest tu wiedza o kształcie widma impulsu prosto-
kątnego. Wiadomo, że znaczna część energii sygnału zawarta jest w części widma ograniczo-
nego częstotliwościami fg=1/ti. Częstotliwość tą można uznać w pierwszym przybliżeniu jako
106

częstotliwość graniczną widma. Wtedy okres próbkowania powinien spełniać nierówność


Tsti/2. Tak łagodne kryterium spełnia już umieszczenie tylko trzech próbek w ramach czasu
trwania impulsu. Zauważmy, że wszystkie impulsy prostokątne o czasie trwania spełniającym
nierówność 3Ts  ti  4Ts miałyby wtedy jednakową reprezentację dyskretną. Nie można się
więc spodziewać dobrej dokładności dalszych obliczeń. Jedyną drogą do poprawy tej dokład-
ności jest skracanie okresu próbkowania. Jeżeli chcemy, aby czas trwania impulsu odwzoro-
wany został z dokładności około 10%, wtedy należy przyjąć Tsti/10, z dokładnością 1% –
Tsti/100 itp.
Drugim problemem jest ustalenie liczby próbek N, która powinna być oczywiście więk-
sza od liczby próbek mieszczących się w impulsie. Zauważmy, że gdyby liczba próbek była
mniejsza lub równa liczbie próbek zawartych w impulsie, to sygnał dyskretny odpowiadałby
sygnałowi stałemu, czyli zgubilibyśmy informację o czasie trwania impulsu. Konieczne jest
zatem wstawienie pewnej liczby próbek zerowych. Liczba tych próbek jest w zasadzie do-
wolna, lecz powinna być starannie dobrana z punktu widzenia potrzeb dalszej analizy. I tak
należy wziąć pod uwagę, że po przejściu sygnału przez filtry ulega on na ogół opóźnieniu i
wydłużeniu, czyli pojawia się w zakresie próbek zerowych oryginalnego sygnału. Poza tym
należy wziąć pod uwagę sprawę czytelności widma, która zależy od ilości jego próbek, a ta
jest równa liczbie próbek N. Dlatego korzystne jest przyjęcie możliwie dużej liczby próbek
zerowych, a tym samym liczby próbek N.
Jako ilustrację powyższych rozważań rozpatrzmy impuls o czasie trwania ti=9.3 ms i
amplitudzie U=2 V. Przyjmijmy, że okres próbkowania wynosi Ts=1 ms, a liczba próbek N=20.
Odpowiedni sygnał dyskretny generują następujące instrukcje:
p=2*ones(1,10);
o=zeros(1,10);
s=[p o];

skala=0:19;
stem(skala,s)
axis([0 20 0 4])
xlabel('n');ylabel('s(n)')
Impuls złożono z dwóch ciągów, a mianowicie z ciągu p zawierającego 10 próbek o
wartości 2 i z ciągu 10 próbek zerowych. Pokazano go na rys.
Zauważmy, że utworzony w ten sposób impuls prostokątny jest dyskretnym odpowied-
nikiem nieskończonej liczby analogowych impulsów prostokątnych, z których pobrano z
pewnym okresem 20 próbek. Jeżeli wiemy, że okres próbkowania wynosi Ts=1 ms, to zbiór
impulsów analogowych ulega znacznej redukcji. Nie mniej jest on nadal nieskończenie
liczny, gdyż zawiera wszystkie impulsy o czasie trwania spełniających nierówność: 9 ms
ti<10 ms.
W ten sam sposób można zapisywać w formie dyskretnej impulsy o różnych kształtach.
Pokażemy dla przykładu instrukcje generujące impuls trójkątny.
pn=(0:5)/5;
po=(4:-1:1)/5;
o=zeros(1,10);
s=[pn po o];
skala=0:19;
stem(skala,s)
axis([0 20 0 2])
xlabel('n');ylabel('s(n)')
107

Rys. 7.2. Dyskretny impuls prostokątny.

Rys. 7.3. Dyskretny impuls trójkątny.


Wykorzystując utworzone w opisany sposób pojedyncze impulsy można łatwo wygene-
rować ich ciągi o zadanej długości. Jeżeli ciąg nie jest zbyt długi, to tworzymy go przez
„sklejanie”. Przykładowo, ciąg zawierający pięć impulsów prostokątnych wytwarzamy pisząc
następujące instrukcje:
p=2*ones(1,10);
o=zeros(1,10);
s=[p o];
s5=[s s s s s];
108

Gdy pożądany ciąg ma być bardzo długi, to do jego generacji można wykorzystać pętlę.
Poniżej zamieszczone instrukcje generują falę prostokątną utworzoną z pojedynczego impulsu
prostokątnego s(n). Okres fali zawiera 20 próbek, a cały ciąg składa się z 10 okresów.
p=2*ones(1,10);
o=zeros(1,10);
s=[p o]; % Pojedynczy impuls prostokątny
s10=zeros(1,200); % Rezerwacja pamięci
for m=1:10;
s10(1+20*(m-1):m*20)=s-1 % Odjęcie 1 powoduje, że wartość średnia sygnału wynosi 0
end
skala=0:199; % Wykres
stem(skala,s10)
axis([0 200 –2 2]
xlabel(‘n’); ylabel(‘s10(n)’)
Zapis argumentu funkcji s10 powoduje, że wartości ciągu s o długości 20 próbek są
wpisywane w kolejnych cyklach na pozycje 1:20, 21:40, 41:60 itd.

Rys. 7.4. Dyskretna fal a prostokątna.


Do generacji omówionych wyżej sygnałów można wykorzystać funkcje rectpuls, tripuls i

square, którymi dysponuje program MATLAB . I tak, funkcja rectpuls(t,ti) generuje próbki
impulsu prostokątnego o czasie trwania ti, w punktach czasu wyznaczonych przez wektor t.
W odróżnieniu od omawianego wyżej impulsu prostokątnego, funkcja rectpuls odnosi się do
impulsów symetrycznych względem t=0.
Dla przykładu pokazanego na rys. odpowiednie instrukcje mają następującą postać:
t=-10:10;
s=2*rectpuls(t,9.3);
Program zwraca sygnał dyskretny
s = [0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0]
Zawiera on 9 próbek niezerowych, a więc o jedna mniej, niż sygnał w rozpatrywanym
wcześniej przykładzie. Wynika to z innych momentów pobierania próbek. Jeżeli przesuniemy
momenty próbkowania, to otrzymamy dziesięć próbek:
109

t=-9.5:9.5;
s=2*rectpuls(t,9.3);
s = [0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0]
Ten sam sygnał analogowy może mieć, jak widać dwie różne reprezentacje dyskretne
nawet przy tej samej częstotliwości próbkowania.
Analogicznie działa funkcja tripuls. Funkcja square generuje falę prostokątna pokazaną
na rys. Różnica polega na tym, że argumentem funkcji square jest wektor, którego wartości są
podawane w radianach, analogicznie jak w funkcji sinus.
t=0:199;
s=square(2*pi*t/20);
Do generacji ciągu impulsów można użyć funkcji pulstran, której pełny opis znajduje się
pliku help pulstran. Omówimy tu tylko jedną, najbardziej użyteczną, wersję tej funkcji. Ma ona
następującą składnię:
pulstran(t,d,p)
Należy utworzyć wektor t, który zawiera numery próbek sygnału oraz wektor d, który
zawiera numery próbek wyznaczających okres powtarzania impulsu. Wektor p zwiera próbki
impulsu, który ma być powtarzany z okresem zadanym wektorem d. Ilustrują to przykład, w
którym wygenerujemy ciąg pięciu impulsów o zadanym kształcie i okresie próbkowania.
Okres próbkowania jest dowolny, ale ustalony.
t=1:100;
t=0:100;
d=(0:4)*20;
p=[0 1 2 3 2 1 0 -1 -2 -3 -2 -1 0];
s=pulstran(t,d,p);
Wykres ciągu próbek pokazano na rys. 7.5.

Rys. 7.5. Ciąg impulsów trójkątnych.


110

Jak wynika z zapisanych wyżej instrukcji i jest widoczne na rysunku, impuls ma dłu-
gość 13 próbek, a okres jego powtarzania zawiera 20 próbek. Rzeczywiste czasy otrzymu-
jemy mnożąc te liczby przez okres próbkowania Ts.
Ciąg próbek impulsu można wygenerować w dowolny sposób, np. korzystając ze stan-
dardowych funkcji typu rectpuls, ones, sin, exp itp.
Na zakończenie omawiania sygnałów impulsowych wspomnijmy, że impuls Diraca ge-
nerują instrukcje
s=zeros(1,N); s(1)=1
a impuls jednostkowy
s=ones(1,N)
gdzie N jest liczbą próbek analizowanego lub przetwarzanego sygnału.

7.3. Dyskretna reprezentacja sygnałów ciągłych


7.3.1. Sygnały deterministyczne
Rozpatrzymy tu sygnały harmoniczne, zmodulowane sygnały wąskopasmowe i pewne
sygnały dolnopasmowe. Rozpoczniemy od sygnału harmonicznego s(t)=sosin(2f0t+). Jeżeli
sygnał taki jest nieograniczony w czasie, to górna częstotliwość graniczna jego widma jest
równa częstotliwości f0. Zgodnie z twierdzeniem Nyquista wystarczy próbkować ten sygnał z
częstotliwością Fs=1/Ts>2fo. W celu przejścia w dziedzinę sygnałów dyskretnych ciągły czas t
zastępujemy czasem dyskretnym t=nTs=n/Fs, gdzie n jest liczbą całkowitą. Sygnał dyskretny
ma wtedy następujący zapis:
s(n)=sosin[2(f0/Fs)n+ ].
Iloraz f0/Fs jest „częstotliwością sygnału dyskretnego”, która – zgodnie z twierdzeniem
Nyquista – nie powinna być większa od 0.5. Czym mniejsza jest ta „częstotliwość”, tym wię-
cej próbek sygnału mieści się w okresie funkcji sinus.
W obliczeniach numerycznych nie możemy badać sygnału w nieskończonym czasie, jak
to czyni się często w obliczeniach analitycznych. Konieczne jest zatem określenie pożąda-
nego „czasu obserwacji”, co sprowadza się do wybrania liczby próbek N. Czas obserwacji
wynosi wtedy NTs.
Poniżej podano instrukcję generujące dyskretny sygnał sinusoidalny o zadanych para-
metrach oraz zamieszczono rysunek ilustrujący przebieg tego sygnału.
%DANE
so=2; % Amplituda [V]
fo=4*10^3; % Częstotliwość [Hz]
fi=30; % Faza [deg]
to=10^-3; % Czas obserwacji [s]
Fs=80*10^3; % Częstotliwość próbkowania [Hz]
%OBLICZENIA
fi=fi*pi/180; % Faza [rad]
N=to*Fs; % Numer ostatniej próbki
n=0:N; % Wektor numerów próbek (czasu dyskretnego)
s=so*sin(2*pi*fo/Fs*n+fi); % Sygnał dyskretny
%WYKRES
t=n/Fs*10^3; % Wektor skali czasu
stem(t,s) % Wykres sygnału dyskretnego
xlabel('t [ms]'); ylabel('s(t) [V]') % Opisy osi wykresu
axis([0 1 -2.5 2.5]) % Granice osi
111

Rys. 7.6. Dyskretny sygnał sinusoidalny.


Zauważmy, że liczba próbek sygnału wynosi N+1, gdyż zwyczajowo sygnał rozpoczyna
się od momentu czasu t=0. Jeżeli chcemy mieć liczbę próbek N, to piszemy:
n=1:N; % Wektor numerów próbek (czasu dyskretnego)
s=so*sin(2*pi*fo/Fs*(n-1)+fi); % Sygnał dyskretny
t=(n-1)/Fs*10^3; % Wektor skali czasu
W analogiczny sposób generuje się inne sygnały ciągłe, np. sygnał z modulacją ampli-
tudy, zapisany jako:
s(t)=so[1+msin(2fmt+m)]sin(2fot+o)
Zgodnie z podaną wyżej zasadą, sygnał taki zapisujemy w formie dyskretnej jako:
s(n)=so[1+msin[2(fm/Fs)n+m)]sin[2(fo/Fs) n+o)
Program generujący dyskretny sygnał sinusoidalny zmodulowany amplitudowo sygna-
łem sinusoidalnym ma następującą postać:
%DANE
so=2; % Amplituda [V]
fo=8*10^3; % Częstotliwość sygnału nośnego [Hz]
fio=30; % Faza [deg]
fm=10^3 % Częstotliwość sygnału modulującego [Hz]
fim=60; % Faza sygnału modulującego [deg]
m=0.4 % Głębokość modulacji
to=4*10^-3; % Czas obserwacji [s]
Fs=160*10^3; % Częstotliwość próbkowania [Hz]
%OBLICZENIA
fio=fio*pi/180; % Faza [rad]
fim=fim*pi/180; % Faza [rad]
N=to*Fs; % Numer ostatniej próbki
n=0:N; % Wektor numerów próbek (czasu dyskretnego)
s=so*(1+m*sin(2*pi*fm/Fs*n+fim)).*sin(2*pi*fo/Fs*n+fim); % Sygnał dyskretny

Wygenerowany sygnał pokazano na rys. 7.7.


112

Rys. 7.7. Dyskretny sygnał z modulacją amplitudy.


Program MATLAB dysponuje funkcją modulate, która generuje kilka rodzajów sy-
gnałów zmodulowanych. Składnia tej użytecznej funkcji jest następująca:
s=modulate(x,fo,Fs,metoda,opcja)
Poszczególne argumenty funkcji mają niżej podane znaczenie:
x – wektor zawierający próbki sygnału modulującego,
fo – częstotliwość sygnału nośnego,
Fs – częstotliwość próbkowania,
metoda – rodzaj modulacji,
opcja – opcjonalna liczba lub wektor występujące w niektórych rodzajach mo-
dulacji.
Domyślnie zakłada się, że próbki sygnału modulującego x są pobierane z częstotliwo-
ścią Fs. Liczba próbek wygenerowanego sygnału s jest równa liczbie próbek sygnału modu-
lującego x. W modulacjach analogowych sygnałem nośnym jest sygnał kosinusowy bez prze-
sunięcia fazy. Mamy do wyboru następujące rodzaje modulacji, które wpisujemy w miejsce
parametru metoda:
‘am’ –modulacja amplitudy z dwiema wstęgami bocznymi bez sygnału nośnego (opcja
nie występuje),
‘amdsb-sc’ – inne oznaczenie modulacji podanej wyżej
‘amdsb-tc’ – dwuwstęgowa modulacja amplitudy z sygnałem nośnym (wpisując na pozy-
cji opcja liczbę xm ustalamy głębokość modulacji zgodnie ze wzorem
s(n)=[x(n)-xm]cos[2(fo/Fs)n]; aby nie wystąpiło przemodulowanie należy
tak dobrać xm, aby xm<min(x)),
‘amssb’ – modulacja jednowstęgowa (opcja nie występuje),
‘fm’ – modulacja częstotliwości (wpisując w miejsce opcji liczbę kf ustalamy głębokość
modulacji
113

‘pm’ – modulacja fazy(opcja kp ustala głębokość modulacji fazy, który podamy w


p. 6.),
‘qam’ – kwadraturowa modulacja amplitudy( w miejscu opcja należy koniecznie wsta-
wić wektor xc o długości wektora x; wektor xc wyznacza składową kwadratu-
rową sygnału zmodulowanego według wzoru
s(n)=xcos[2(fo/Fs)n]+xcsin[2(fo/Fs)n].
Poza wymienionymi wyżej rodzajami modulacji, funkcja modulate generuje również sy-
gnały z modulacją impulsową:
‘pwm’ – modulacja szerokości impulsu (opcja ‘centered’ ustawia impulsy centralnie
względem okresu nośnej),
'ppm' – modulacja położenia impulsu (opcja może być wartością liczbową z przedziału
(0,1), która wyznacza szerokość impulsu względem okresu częstotliwości no-
śnej).
Przykłady generacji sygnałów przy użyciu funkcji modulate pokażemy w punkcie doty-
czącym analizy widmowej sygnałów dyskretnych.
W zapisie funkcji modulate występuje wektor x, który jest dyskretną reprezentacją cią-
głego lub impulsowego sygnały modulującego. Często sygnałami modulującemu są sygnały
dolnopasmowe, takie jak sygnał mowy lub muzyki, sygnał wizyjny itp. Sygnały tego typu nie
mają zapisu analitycznego, a zatem nie mogą być wygenerowane metodami opisanymi wyżej.
Jeżeli chcemy w programie MATLAB wykorzystywać takie sygnały, musimy dokonać rze-
czywistego próbkowania sygnałów analogowych za pomocą przetwornika analogowo-cyfro-
wego i zarejestrowane pliki zaimportować do naszego programu. Można także posługiwać się
wcześniej przetworzonymi plikami cyfrowymi zarejestrowanymi na różnych nośnikach lub
dostępnymi w internecie. Sposoby importowania takich plików omówiono w rozdziale 5.
Wspomniane wyżej sygnały mogą być oczywiście również bezpośrednio przetwarzane
w środowisku MATLAB.

7.3.2. Sygnały losowe


Specyficznymi sygnałami ciągłymi są szumy, które występują w układach elektronicz-
nych i kanałach telekomunikacyjnych. Można je próbkować tak jak wspomniane wyżej sy-
gnały dolnopasmowe i importować do programu MATLAB. Można również w badaniach
symulacyjnych posługiwać się szumami dyskretnymi generowanymi w tym programie. Jak
już wiemy, do generacji szumów, a ściślej mówiąc do generacji dyskretnych sygnałów loso-
wych służą funkcje rand i randn. Przypomnijmy, że pierwsza z nich generuje losowo liczby z
przedziału (0,1), które mają jednostajny rozkład prawdopodobieństwa, a druga – liczby o roz-
kładzie normalnym, o wartości średniej równej zeru i dyspersji równej jedności. Na rys. 7.8
pokazano po 100 próbek obu dyskretnych sygnałów losowych.
114

Rys. 7.8. Dyskretny sygnał losowy o rozkładzie: a) jednostajnym, b) normalnym.


Pojawia się pytanie, w jaki sposób należy traktować wygenerowane liczby, aby stano-
wiły one reprezentację dyskretną procesu (sygnału, szumu) ciągłego. Otóż liczby te można
traktować jako próbki procesu ciągłego pobierane z częstotliwością Fs (taką samą, jak sygnał
użyteczny). Zgodnie z twierdzeniem Nyquista widmo tego procesu jest ograniczone od góry
częstotliwością Fs/2. Jest to pewne ograniczenie, gdyż teoretycznie zakłada się, że szum biały
ma widmo nieograniczone. Jeżeli jednak konsekwentnie uwzględniamy to ograniczenie, to
nie ma ono negatywnych skutków na wynik obliczeń i symulacji.
W p. 3.4.2 podano trzy funkcje wyznaczające podstawowe parametry procesów stochas-
tycznych, a mianowicie funkcje mean, std i var. W zamieszczonym niżej krótkim programie
pokażemy sposób posługiwania się tymi funkcjami w odniesieniu do szumu białego.
szum=2*randn(1,100); % Szum o odchyleniu standardowym sigma=2
srednia=mean(szum) % Wartość średnia
srednia =
-0.2540
sigma=std(szum) % Odchylenie standardowe
sigma =
1.8894
wariancja=var(szum) % Wariancja
wariancja =
3.5698
Jak widać, średnia wartość szumu nie jest równa zeru, odchylenie standardowe różni się
od założonej wartości sigma=2, a wariancja nie jest równa 4. Przyczyną tych niezgodności jest
fakt, że wyznaczone wartości są jedynie estymatorami parametrów szumu. Wartości tych es-
tymatorów powinny zmierzać do rzeczywistych wartości parametrów procesu, gdy liczba
próbek rośnie. Zwiększmy zatem 100-krotnie liczbę próbek i powtórzmy powyższe oblicze-
nia.
szum=2*randn(1,10000); % Szum o odchyleniu standardowym sigma=2
srednia=mean(szum) % Wartość średnia
srednia =
0.0054
sigma=std(szum) % Odchylenie standardowe
115

sigma =
2.0018
wariancja=var(szum) % Wariancja
wariancja =
4.0071
Zgodnie z przewidywaniami, wartości estymatorów zbliżyły się znacznie do wartości
oczekiwanych. Wynika stąd praktyczny wniosek, że gdy chcemy w obliczeniach numerycz-
nych uzyskiwać wyniki zbliżone do teoretycznych, to należy generować szum o możliwie
dużej liczbie próbek.
Program MATLAB dysponuje funkcjami umożliwiającymi wyznaczanie Rozkładów
gęstości prawdopodobieństwa zmiennych losowych. Są to mianowicie funkcje hist i histc. Je-
żeli zmienna losowa (np. szum) dana jest wektorem x, wówczas funkcja
hist(x)
wyznacza histogram zmiennej losowej i wykonuje jego wykres. Działanie tej funkcji polega
na znalezieniu wartości minimalnej i maksymalnej zmiennej x i podzieleniu przedziału ogra-
niczonego tymi wartościami na 10 równych przedziałów. Następnie oblicza się ile wartości
zmiennej y mieści się w poszczególnych przedziałach. Wyznaczone w ten sposób liczby są
wartościami histogramu, pokazywanymi na rysunku. W tej najprostszej formie funkcją hist
jest mało użyteczna ze względu na małą liczbę przedziałów zmiennej x. Liczbę przedziałów
można zmienić pisząc:
hist(x,P),
gdzie P jest pożądaną liczbą przedziałów.
Zapisując funkcję hist w postaci:
[h,xn]=hist(x,P)
otrzymujemy wartości histogramu h oraz wektor xn. Zawiera on kolejne wartości środków
przedziałów, w których zliczane są wartości zmiennej losowej x mieszczące się w tych prze-
działach.
Podobnie działa funkcja histc, której składania jest następująca:
h=histc(x,xe)
Wektorem xe zapisuje się kolejne wartości krańców przedziałów, w których zliczane są
zawarte w nich wartości zmiennej losowej x.
Omówione wyżej funkcje umożliwiają wyznaczenie przybliżonych rozkładów gęstości
prawdopodobieństwa p(x). Jak wiadomo rozkład prawdopodobieństwa spełnia równanie:

 p(x)dx  1 .


W obliczeniach numerycznych powyższą całkę można zastąpić sumą:


 

 p( x )dx   p(n)x  1 ,
n 


gdzie x jest odległością między próbkami x=x(n+1)-x(n).


Z opisanej wyżej zasady tworzenia histogramu wynika, że


1
h(n)  1 ,
N n 
116

gdzie N jest liczbą próbek zmiennej losowej x.


Porównując powyższe wzory otrzymujemy:
 

 
1
h(n)  p(n)x ,
N n  n 

a stąd mamy:
1
p(n)  h(n) .
Nx
Ponieważ x=(xmax-xmin)/P, więc ostatecznie otrzymujemy:
P
p(n)  h(n) .
N( x max  x min )

W obliczeniach numerycznych granice sumy są ograniczone, lecz wynik sumowania nie


zmienia się, gdyż wartości histogramu poza granicami są zerowe. Nie mniej ostateczny wynik
jest obarczony błędem ze względu na skończoną liczbę próbek N. Błąd ten maleje ze wzro-
stem liczby N.
Jako przykład podamy sposób numerycznego wyznaczania rozkładu gęstości prawdo-
podobieństwa szumu o rozkładzie normalnym, zapisanym wzorem:
1 x2
p( x )  exp( ).
2 2 2

Instrukcje realizujące to zadanie są następujące:


sigma=2; % Wartość odchylenia standardowego
N=10^6; % Liczba próbek
P=200; % Liczba przedziałów
x=sigma*randn(1,N); % Generacja zmiennej losowej (szumu)
[h,xn]=hist(x,P); % Histogram
dx=(max(x)-min(x))/P; % Przedział zmiennej losowej
p=h/(N*dx); % Rozkład gęstości prawdopodobieństwa
plot(xn,p) % Wykres
pa=exp(-xn.^2/(2*sigma^2))/(sqrt(2*pi)*sigma); % Rozkład gaussowski
hold on
plot(xn,pa,'k') % Wykres
117

Rys.7.9. Rozkład gęstości prawdopodobieństwa szumu białego wyznaczony numerycznie i


analitycznie.

7.4. Dyskretna transformacja Fouriera


7.4.1. Definicja i podstawowe własności
Rozpatrywane dotychczas sygnały były funkcjami czasu. Bardzo często wygodnie jest
przedstawiać, analizować i przetwarzać sygnały w dziedzinie częstotliwości. Sygnały przed-
stawione w tej dziedzinie mają często prostszą i łatwiejszą do interpretacji postać. Ponadto
niektóre operacje na sygnałach wykonuje się prościej i szybciej w dziedzinie częstotliwości.
Dotyczy to nie tylko przekształceń analitycznych, lecz również przetwarzania sygnałów w
praktycznych układach i systemach elektronicznych. Stało się to możliwe i skuteczne wraz z
pojawieniem się komputerów, a następnie wyspecjalizowanych procesorów sygnałowych.
Jeżeli chcemy dokonywać analizy i przetwarzania sygnałów w dziedzinie częstotliwo-
ści, pierwszym i niezbędnym krokiem jest transformacja sygnału w tę dziedzinę. Jak wiemy,
w obliczeniach analitycznych wykorzystuje się w tym celu przekształcenia Fouriera, szeregi
Fouriera, przekształcenie Laplace’a bądź przekształcenie Z. W obliczeniach numerycznych
stosuje się powszechnie dyskretne przekształcenie Fouriera (ang. Discrete Fourier Transform
– DFT). Algorytmy realizujące w sposób bardzo szybki to przekształcenie noszą nazwę szyb-
kiej transformacji Fouriera (ang. Fast Fourier Transform – FFT). Dyskretną transformację
Fouriera wykorzystuje się jako narzędzie do przybliżonego wyznaczania ciągłych transformat
Fouriera, zwłaszcza w odniesieniu do sygnałów (np. losowych), których ciągłych transformat
nie można wyznaczyć analitycznie. Jednak przede wszystkim jest ona użyteczna w cyfrowym
przetwarzaniu sygnałów.
Należy wyraźnie i z naciskiem podkreślić, że traktowanie dyskretnej transformacji Fo-
uriera jako przybliżonej formy transformacji ciągłej wymaga starannego przemyślenia, zasto-
sowania określonych zabiegów i na koniec ostrożnej interpretacji. Pokażemy to dalej na kilku
przykładach.
Dyskretna transformacja Fouriera wywodzi się z ciągłej transformacji Fouriera sygna-
łów dyskretnych. Jak wiemy, widmo sygnałów dyskretnych jest ciągłe i okresowe. Dyskretne
118

przekształcenia Fouriera dotyczy także sygnałów dyskretnych (lub ściślej – ciągów liczbo-
wych), jest okresowe, ale również dyskretne. Jak we wszystkich obliczeniach numerycznych,
dyskretna transformata Fouriera jest wyznaczania zawsze ze skończonej liczby próbek sy-
gnału (z ciągów o ograniczonej długości). Jeżeli nieograniczony sygnał ciągły jest próbko-
wany i do obliczenia dyskretnej transformaty Fouriera bierze się ograniczoną liczbę próbek,
to z oczywistych względów widmo dyskretne nie może zawierać informacji o pominiętych
fragmentach sygnału. Może zatem (lecz nie zawsze musi) różnić się od widma ciągłego wy-
znaczonego dla całego sygnału.
W programie MATLAB funkcja wyznaczająca dyskretne widmo X wektora x ma za-
pis:
X=fft(x)
a wartości wektora X wyznaczane są z następującego wzoru:
N
(n  1)(k  1)
X(k )   x(n) exp[ j2
n1
N
],

gdzie N jest liczbą elementów wektora x oraz k=1,2,...,N.


Jak widać, liczba prążków widma X(k) jest zawsze równa liczbie elementów wektora
x(n) (próbek sygnału).
W konwencji przyjętej w programie MATLAB, pierwszy prążek widma jest równy
sumie wszystkich elementów wektora x. Jest więc proporcjonalny do wartości średniej ciągu
(składowej stałej sygnału). Należy o tym pamiętać interpretując wyniki obliczeń.
Odwrotną, dyskretną transformatę Fouriera wyznacza funkcja
x=ifft(X)
według poniższego wzoru:
N
(n  1)(k  1)

1
x(n)  X(k ) exp[j2 ]
N n1 N

Funkcja o zapisie
Xm=fft(x,M)
zwraca widmo dyskretne ciągu x o długości N uzupełnionego zerami do długości M>N.
Funkcja o zapisie
xm=ifft(X,M)
wyznacza ciąg o długości M, który jest okresowym rozszerzeniem ciągu x.
Dla zilustrowania działania funkcji fft i ifft wyznaczymy dyskretne widmo impulsu pro-
stokątnego:
x=[1 1 1 1 1 0 0 0 0 0];
X=fft(x)
X=
5 1 - 3.0777i 0 1 - 0.7265i 0 1 0 1 + 0.7265i 0 1 + 3.0777i
>> x=ifft(X)
x=
1 1 1 1 1 0 0 0 0 0
Widzimy, że prążki widma są liczbami zespolonymi. Zauważamy ponadto pewną sy-
metrię w wartościach liczbowych prążków. Polega ona na tym, że „symetryczne” prążki są
względem siebie sprzężone (mają odwrotne znaki przy częściach urojonych). Potwierdza się
119

również fakt, że odwrotna transformata odtwarza ciąg oryginalny. Spostrzeżenia te ilustruje


zmieszczony niżej rysunek.

Rys.7.10. Dyskretne widmo impulsu prostokątnego (real(X) – składowa rzeczywista, imag(X) –


składowa urojona, abs(X) – moduł, angle(X) – faza w radianach).

Pomijając prążek o numerze n=1 (składowa stała) i traktując prążek o numerze n=5 jako
„oś symetrii” widzimy, że część rzeczywista i moduł widma są parzyste, a część urojona i fa-
za – nieparzyste. Jest to stała własność widma dyskretnego obowiązująca dla wszystkich cią-
gów rzeczywistych. Można to zapisać jako:
X(m)=X*(N-k+2) k=2,...,N/2-1 dla N parzystych
lub X(m)=X*(N-k+2) k=2,...,(N+1)/2 dla N nieparzystych
Argumentami funkcji fft i ifft mogą być również ciągi zespolone i dla takich ciągów po-
wyższa własność nie obowiązuje.
W funkcjach fft i ifft liczba prążków widma jest ograniczona do liczby próbek N. Jeżeli
znieśli byśmy to ograniczenie i obliczali widmo dla prążków o numerach dodatnich i ujem-
nych aż do nieskończoności, to zauważylibyśmy, że widmo jest okresowe, a długość okresu
wynosi N. Można to łatwo sprawdzić wstawiając do wzory na transformatę dyskretną zamiast
k numer mN+k. Wyznaczane widma można zatem traktować jako jeden okres widma okreso-
wego. Widmo okresowe byłoby dyskretnym odpowiednikiem ciągłego widma sygnałów dys-
kretnych.

8.4.2. Widmo dyskretne a widmo ciągłe


Wspomniano wyżej, że dyskretna transformata Fouriera może być używana do nume-
rycznego wyznaczania ciągłego widma sygnałów. Omówimy teraz warunki, przy których
widmo dyskretne dostatecznie dokładnie odwzorowuje widmo ciągłe sygnałów analogowych.
Na początku należy wyraźnie stwierdzić, że pełne odwzorowanie widma jest niemożliwe je-
dynie w szczególnych wypadkach. Jest to możliwe tylko wtedy, gdy widmo sygnałów jest
ograniczone. Jest to jednak kryterium konieczne lecz niewystarczające. Na ogół musimy za-
120

tem pogodzić się z faktem wystąpienia pewnych rozbieżności, które mogą być akceptowane
w obliczeniach inżynierskich.
Zmienną w omówionym wyżej widmie dyskretnym są numery prążków oznaczone li-
terą k. Należy w pierwszej kolejności pokazać związek pomiędzy numerem prążka, a rzeczy-
wistą częstotliwością sygnału. Przyjmijmy, że sygnał s(t) jest próbkowany z częstotliwością
Fs, czyli, że odstęp między sąsiednimi próbkami wynosi Ts. Transformatę Fouriera takiego
sygnału można zapisać jako:
 
S( f )   s(t) exp( j2ft)dt   s[n  1)T ] exp[ j2f (n  1)T ]dt
 
s s

gdyż moment czasu t=0 odpowiada próbce o numerze n=1. Jeżeli sygnał zawiera tylko N pró-
bek, to powyższą całkę można zastąpić suma:
N
S( f )  t  s(n) exp[ j2f (n  1)T ]
n1
s

Przypomnijmy teraz definicję funkcji fft:


N
(n  1)(k  1)
S(k )   s(n) exp[ j2
n1
N
]

Porównując oba wzory dochodzimy do wniosku, że powinna być spełniona równość ar-
gumentów funkcji wykładniczych. Po oczywistych uproszczeniach mamy więc:
k 1
fTs 
N
lub
k 1
f (k )  Fs
N
Jest to zależność, która numerom prążków widma dyskretnego przypisuje rzeczywistą
częstotliwość sygnału próbkowanego z częstotliwością Fs. Maksymalna częstotliwość f(N) jest
równa:
N 1
f (N)  Fs
N
Ponieważ maksymalna częstotliwość sygnału musi być mniejsza od Fs/2, więc numery
prążków odpowiadające dodatnim częstotliwościom widma muszą spełniać nierówność3:
N
k 1
2
Prążki widma o wyższych numerach odnoszą się do ujemnych częstotliwości widma
sygnału analogowego zgodnie ze wzorem:
N  k 1
f (k )   Fs
N

3
Dla parzystych N należy przyjąć, że maksymalna wartość k=N/2+1.
121

Aby otrzymać widmo ciągłe we właściwej skali należy prążki widma dyskretnego po-
mnożyć przez t, czyli przez Ts, gdyż taki jest w skali częstotliwości odstęp prążków widma
dyskretnego.
Odległość między sąsiednimi prążkami widma dyskretnego (rozdzielczość widma) wy-
nosi:
Fs 1 1
f    ,
N NTs t0

gdzie t0 jest czasem obserwacji sygnału, czyli czasem, w którym zbierane są jego próbki.
Zamieszczony poniżej program wyznacza widmo dyskretne impulsu prostokątnego o
czasie trwania T=10 ms i wysokości 2 V. Sygnał jest próbkowany z częstotliwością Fs= 1 kHz.
Czas obserwacji sygnału wynosi t0=200 ms. Sygnał impulsowy ma nieograniczone widmo, a
więc – ściśle rzecz biorąc – nie można wyznaczyć częstotliwości Nyquista. Wyniki muszą dać
jedynie przybliżony przebieg widma.

%DANE
T=10*10^-3; % Czas trwania impulsu
Fs=10^3; % Częstotliwość próbkowania
to=200*10^-3; % Czas obserwacji
V=2; % Amplituda

%GENERACJA SYGNAŁU
M=round(T*Fs); % Liczba próbek w impulsie
N=round(to*Fs); % Liczba próbek w czasie obserwacji
s=zeros(1,N); % Próbki zerowe
s(1:M)=2; % Próbki w impulsie

%WYZNACZANIE WIDMA DYSKRETNEGO


X=fft(s); % Widmo dyskretne
kmax=floor(N/2+1) % Maksymalny numer próbki prawej
Xp=X(1:kmax); % Prawa część widma
Xl=X(kmax+1:N); % Lewa część widma
S=[Xl Xp]/Fs; % Widmo

%WYKREŚLANIE WIDMA DYSKRETNEGO


f=(-N/2+1:N/2)*Fs/N; % Skala częstotliwości
stem(f,abs(S)) % Wykres modułu widma dyskretnego

%WYKREŚLANIE WIDMA CIĄGŁEGO


figure
St=V*T*sin(pi*T*f+eps)./(pi*T*f+eps); % Widmo ciągłe
plot(f,abs(St),'k') % Wykres modułu widma ciągłego
hold on
plot(f,abs(S),'k') % Wykres obwiedni modułu widma dyskretnego

Instrukcje zapisane w segemencie %WYZNACZANIE WIDMA DYSKRETNEGO


można zastąpić dwiema instrukcjami, a mianowicie:
X=fft(s); % Widmo dyskretne
S=fftshift(X); % Widmo dyskretne, symetryczne względem zera

Instrukcja fftshift(X) zwraca bowiem widmo X w formie symetrycznej względem często-


tliwości f=0, która jest używana w odniesieniu do widma ciągłego. Akceptowany jest również
skrótowy zapis:
S=fftshift(fft(s));
122

Na rys. 7.11 pokazano moduł dyskretnego widma impulsu. Na następnym rysunku wi-
doczna jest obwiednia modułu widma dyskretnego oraz widmo ciągłe tego impulsu, wyzna-
czone teoretycznie. Jak widać, występuje różnica pomiędzy obu widmami. Jest ona spowo-
dowana „przeciekiem” w widmie dyskretnym, a ten z kolei jest skutkiem nieograniczonego
widma impulsu prostokątnego. Różnica obu widma może być zmniejszana przez zwiększenie
częstotliwości próbkowania Fs. Jeżeli chcemy zachować rozdzielczość widma, to należy pro-
porcjonalnie zwiększyć liczbę próbek, czyli zachować czas obserwacji. W rozpatrywanym
przypadku jest to równoważne wstawieniu dodatkowych próbek zerowych.

Rys. 7.11. Moduł widma dyskretnego impulsu prostokątnego.

Rys. 7.12. Moduł widma impulsu prostokątnego: a) obwiednia widma dyskretnego, b) widmo ciągłe.
123

7.4.3. Widma sygnałów o nieograniczonym czasie trwania


Widmo dyskretne wyznaczane jest zawsze ze skończonej liczby próbek. Problem poja-
wia się wtedy, gdy interesujący nas sygnał ma nieograniczony czas trwania (np. sygnał sinu-
soidalny, szumowy, wąskopasmowy itp.). Obliczone widmo dyskretne dotyczy wtedy tylko
wybranego fragmentu sygnału, a więc może różnić się w istotny sposób od widma ciągłego
całego sygnału. Wyjaśnimy to na przykładzie sygnału sinusoidalnego. Pokażemy, że wybór
przedziału obserwacji w istotny sposób wpływa na przebieg widma dyskretnego tego sygnału.
Pokażemy również sposób zmniejszenia wpływu przedziału obserwacji na kształt widma.
Weźmy pod uwagę sygnał
s(t )  s 0 sin(2f 0 t  )

którego t częstotliwość f0 jest znana. Można wtedy dobrać częstotliwość próbkowania i czas
obserwacji w taki sposób, aby widmo dyskretne było wiernym odzwierciedleniem widma
ciągłego sygnału o nieskończonym czasie trwania. Przyjmijmy mianowicie, że Fs=10f0 oraz,
że liczba próbek N obejmuje całkowitą liczbę okresów sygnału sinusoidalnego, np. N=4 T0/Ts =
4Fs/f0. Wyznaczymy widmo sygnału przy założeniu, że faza  jest przypadkowa. Program
wyznaczający widmo dyskretne przedstawiono niżej.
%DANE
fo=100; % Częstotliwość sygnału [Hz]
Fs=10*fo; % Częstotliwość próbkowania [Hz]
fi=2*pi*rand(1,1) % Faza [rad]
so=1; %Amplituda
%OBLICZENIA
N=4*Fs/fo; % Liczba próbek
n=0:N-1; % Numery próbek
s=so*sin(2*pi*fo*n/Fs+fi); %Sygnał sinusoidalny
S=fft(s); % Widmo dyskretne
%WYKRESY
f=n*Fs/N; % Skala częstotliwości [Hz]
subplot(2,2,1);stem(f,real(S)); % Część rzeczywista widma
subplot(2,2,2);stem(f,imag(S)); %Część urojona widma
subplot(2,2,3);stem(f,abs(S)); % Moduł widma
subplot(2,2,4);stem(f,unwrap(angle(S))); % Faza widma
Na rys. 7.13 widoczne są poszczególne składowe widma dyskretnego w formie graficz-
nej używanej w programie MATLAB. Zamiast numerów próbek wstawiono jedynie rzeczy-
wistą skalę częstotliwości.
Widmo nieograniczonego sygnału ciągłego zawiera dwa impulsy Diraca o „amplitu-
dzie” zespolonej zależnej od fazy, występujące na częstotliwościach 100 Hz i – 100 Hz. Jak
widać, w widmie dyskretnym mamy główny prążek na częstotliwości 100 Hz i drugi prążek
na częstotliwości 900 Hz. Zgodnie z podaną wyżej interpretacją można uznać go jako prążek
występujący na częstotliwości –100 Hz. Przebieg fazy widma wynika z błędów obliczeń nu-
merycznych i nie powinien być w tym wypadku brany pod uwagę. Właściwą wartość przesu-
nięcia fazy występuje tylko na częstotliwości 100 Hz i 900 Hz
124

Rys.7.13 . Widmo dyskretne sygnału sinusoidalnego.


Tak dobra zgodność widma dyskretnego z widmem nieograniczonego sygnału ciągłego
jest jednakże przypadkiem szczególnym. Wynika ona z przyjętych założeń, a mianowicie z
okresowości sygnału i czasu obserwacji, który jest wielokrotnością okresu sygnału. Wystar-
czy, że jedno z tych założeń nie jest spełnione, a widmo dyskretne różni się od widma sygnału
ciągłego. W praktycznych zastosowaniach bardzo rzadko sygnał jest okresowy i równie
rzadko znamy jego częstotliwość. Przeciwnie, często częstotliwość (lub ogólniej widmo) sy-
gnału jest poszukiwanym parametrem. Skazani jesteśmy zatem na arbitralny dobór czasu ob-
serwacji i częstotliwości próbkowania. Skutki zmiany czasu obserwacji przy zachowanej czę-
stotliwości próbkowania pokazano na rys. 7.14. W zamieszczonym wyżej programie zwięk-
szono jedynie liczbę próbek N o jedną.

Rys. 7.14. Widmo dyskretne sygnału sinusoidalnego.


125

Widzimy, że obok prążków widma występujących na właściwych częstotliwościach


pojawiły się dodatkowe prążki, których widmo sygnału nieograniczonego nie zawiera. Są one
skutkiem ograniczonego czasu obserwacji sygnału. Ponadto duże prążki widma nie występują
dokładnie na częstotliwości 100 Hz i 900 Hz, co można sprawdzić powiększając odpowiedni
fragment rysunku lub edytując skalę częstotliwości. Podobne efekty wystąpią, gdy zmienimy
częstotliwość próbkowania.
Na podstawie tego prostego przykładu można przewidywać, że w ogólnym przypadku
widmo dyskretne może różnić się w sposób istotny od widma ciągłego sygnałów nieograni-
czonych w czasie. Aby zminimalizować te różnice, przy ustalonej częstotliwości próbkowania
należy wydłużać czas obserwacji i stosować tzw. okna. Zwiększenie czasu obserwacji po-
zwala z większą dokładnością określić częstotliwość prążków widma, zaś użycie okien po-
woduje zmniejszenie poziomu fałszywych prążków widma. Jest to szczególnie przydatne gdy
wyznaczamy widma dyskretne sumy sygnałów o znacznie różniących się amplitudach.
Widmo mniejszego sygnału może być wtedy zamaskowane przez fałszywe prążki widma
sygnału większego.
Program MATLAB dysponuje następującymi oknami:
bartlett - okno Bartletta
barthannwin - zmodyfikowane okno Bartletta-Hanninga
blackman - okno Blackmana
blackmanharris - okno Blackmana-Harrisa (1)
bohmanwin - okno Bohmana
chebwin - okno Czebyszewa
flattopwin - okno Flat Top
gausswin - okno Gaussa
hamming - okno Hamminga
hann - okno Hanna
kaiser - okno Kaisera
nuttallwin - okno Blackmana-Harrisa (2)
parzenwin - okno Parzena
rectwin - okno prostokątne
tukeywin - oknoTukey’a
triang - okno trójkątne
Składnia funkcji okna ma postać:
w=funkcja(N,P)
gdzie N jest liczbą próbek, a P – parametrem (tylko w oknie Czebyszewa).
Na rys. 7.15. przedstawiono wykresy czterech wybranych funkcji okna dla N=41.
126

Rys. 7.15. Funkcje okien.


Przebiegi funkcji okien są na ogół podobne i mają zbliżone własności. Spośród pokaza-
nych na rysunku wyróżnia się okno Bartletta (jest to okno trójkątne, ale nieznacznie różni się
od okna triang). Okno to jest stosunkowo rzadko stosowane. Wszystkie okna zmniejszają
(choć w różnym stopniu) poziom fałszywych prążków widma. Negatywnym skutkiem ich
użycia jest rozmycie „prawdziwych” prążków widma. Na ogół, gdy dane okno silnie redukuje
poziom fałszywych prążków, to wprowadza większe rozmycie widma. Szczegółową charakte-
rystykę okien można znaleźć w specjalistycznej literaturze.
% DANE
N=100; % Liczba próbek
n=0:N-1; % Ciąg próbek
fo=97; % Częstotliwość sygnału
Fs=1000; % Częstotliwość próbkowania
fi=2*pi*rand(1,1); % Faza sygnału
% OBLICZENIA
s=sin(2*pi*fo*n/Fs+fi); % Sygnał sinusoidalny
w=hamming(N)'; % Okno Hamminga
sw=s.*w; % Sygnał mnożony przez okno
S=fft(s); % Widmo sygnału
Sw=fft(sw); % Widmo sygnału z oknem
% WYKRESY
t=n/Fs % Skala czasu
f=n*Fs/N; % Skala częstotliwości
subplot(2,2,1); plot(t,s,'k')
subplot(2,2,2); plot(t,sw,'k')
subplot(2,2,3); stem(f,abs(S),'k')
subplot(2,2,4); stem(f,abs(Sw),'k')
127

Rys. 7.16. Wpływ okna na dyskretne widmo sygnału.

7.5. Filtracja sygnałów dyskretnych


7.5.1. Filtracja w dziedzinie częstotliwości
Filtracja stosowana jest w celu zmiany widma sygnałów, a najczęściej – w celu wyeli-
minowania jego zbędnych składowych. Filtracja może być dokonywana w dziedzinie często-
tliwości lub czasu. Filtracja w dziedzinie czasu polega na bezpośrednich operacjach na wid-
mie, np. na usunięciu niepożądanych prążków. Może być ona doskonała w tym sensie, że
zbędne prążki widma są eliminowane całkowicie, co w filtracji w dziedzinie czasu nie jest
możliwe. Ceną za tą doskonałość jest konieczność wykonywania bardziej złożonych operacji
na sygnale, a mianowicie:
 obliczenie dyskretnej transformaty Fouriera sygnału
 wykonanie operacji na widmie
 obliczenie odwrotnej transformaty Fouriera.
Dyskretna transformata Fouriera dotyczy zawsze określonej, skończonej liczby próbek
sygnału. W konsekwencji filtracja obejmuje tylko skończoną liczbę próbek sygnału, czyli
ograniczony przedział czasu. Jeżeli czas trwania sygnału jest dłuższy, konieczne jest podzie-
lenie go na segmenty. Skutkiem podziału sygnału ciągłego na krótsze przedziału czasu są
opisane wyżej zniekształcenia widma dyskretnego. Wyniki filtracji pojawiają się cyklicznie, a
nie w sposób ciągły. Ten szkodliwy na ogół efekt można co prawda wyeliminować, lecz nie
można usunąć opóźnienia związanego z czasem zbierania próbek i wyznaczania transformat
Fouriera i operacjami na widmie. Z tych powodów filtracja w dziedzinie częstotliwości nadaje
się przede wszystkim do przetwarzania danych, a w mniejszym stopnie do przetwarzania sy-
gnałów w czasie rzeczywistym.
Działanie filtru w dziedzinie czasu pokażemy na przykładzie zaszumionego sygnału si-
nusoidalnego o częstotliwości f0 zawierającej się w paśmie B o niewielkiej szerokości.
%DANE
fo=51; % Częstotliwość [Hz]
128

Fs=1000; % Częstotliwość próbkowania [Hz]


fi=2*pi* randn(1,1); % Faza [rad]
N=1000; % Liczba próbek
%GENERACJA SYGNAŁU Z SZUMEM
n=0:N-1; % Wektor próbek
x=sin(2*pi*fo*n/Fs+fi); % Sygnał sinusoidalny
szum=2*randn(1,N); % Szum
s=x+szum; % Sygnał z szumem
%FILTRACJA W DZIEDZINIE CZĘSTOTLIWOŚCI
S=fft(s); % Widmo zaszumionego sygnału
W=zeros(1,N); % Prążki zerowe
W(50:54)=1; % Prążki jednostkowe, lewe
W(948:952)=1; % Prążki jednostkowe, prawe
SW=S.*W; % Filtracja
y=real(ifft(SW)); % Odtwarzanie sygnału w dziedzinie czasu
%WYKRESY
t=n(1:100)/Fs;
subplot(2,2,1);plot(t,s(1:100))
subplot(2,2,2);stem(abs(S))
subplot(2,2,3);stem(abs(SW))
subplot(2,2,4);plot(t,y(1:100))
Do sygnału sinusoidalnego o częstotliwości 51 Hz i amplitudzie jednostkowej dodano
szum biały o odchyleniu standardowym równym 2. Widmo zaszumionego sygnału pomno-
żono przez funkcję przenoszenia filtru W, która ma pasmo B=5 Hz. Funkcja ta składa się z 5
prążków jednostkowych o lewej stronie widma i tyluż po prawej stronie. W wyniku pomno-
żenia widma przez funkcję przenoszenia pozostało po 5 prążków widma z jego lewej i prawej
strony. Tak zmienione widmo poddano odwrotnej transformacji Fouriera, w wyniku czego
praktycznie usunięto szum z sygnału wyjściowego. Pokazano to na rys. 7.17.

Rys. 7.17. Filtracja w dziedzinie częstotliwości: a) sygnał sinusoidalny z szumem, b) widmo tego sy-
gnału, c) widmo po filtracji, d) sygnał po filtracji.
Należy zauważyć, że sygnał po filtracji nie jest idealnym sygnałem sinusoidalnym, gdyż
nieznacznie zmienia się jego amplituda i faza. Wynika to z pozostawienia w widmie czterech
prążków szumu oraz wpływu szumu na amplitudę i fazę prążka widma o częstotliwości 51
129

Hz. Nie mniej, porównując sygnały z rysunków a) i d) widzimy zasadniczą poprawę sygnału
do szumu, uzyskaną dzięki zastosowaniu filtracji w dziedzinie częstotliwości.

7.5.2. Filtracja w dziedzinie czasu


Filtracja w dziedzinie czasu nie wymaga stosowania przekształcenia Fouriera i polega
na mnożeniu próbek przez liczby, ich opóźnianiu i sumowaniu. Każda pobierana próbka sy-
gnału jest poddawana tym samym operacjom arytmetycznym i jeżeli komputer wykonuje je
dostatecznie szybko, otrzymujemy sukcesywnie próbki przefiltrowanego sygnału z pewnym,
zwykle niewielkim, opóźnieniem. Filtracja w dziedzinie czasu jest zatem stosowana w syste-
mach pracujących w czasie rzeczywistym, np. w systemach radiofonicznych, telewizyjnych,
w automatyce itp.
Jeżeli dyskretny sygnał wejściowy oznaczymy jako x(n), a sygnał wyjściowy jako y(n),
to działanie filtru cyfrowego jest opisane w konwencji przyjętej w programie MATLAB
następującym ogólnym wzorem:
M P
y(n)  
m 2
 a(m)y(n  m  1)   b(p)x(n  p  1) .
p 1

Pożądaną charakterystykę filtru uzyskuje się przez dobór stałych M i P (rzędu filtru) i
parametrów a(m) i b(p).
Filtry dzielą się na dwie klasy, a mianowicie filtry ze skończoną odpowiedzią impul-
sową (SOI), (ang. Finite Impulse Response –FIR) i filtry z nieskończoną odpowiedzią impul-
sową (NOI), (ang. Infinite Impulse Response –IIR). W filtrach typu FIR wszystkie współ-
czynniki a(m) są równe zeru, a więc próbki sygnału wyjściowego y(n) są wyznaczane wyłącz-
nie z próbek sygnału wejściowego x(n). W filtrach typu IIR zarówno współczynniki a(m), jak
b(p) są różne od zera. W konsekwencji sygnał wyjściowy zależy od próbek sygnału wejścio-
wego i poprzednich próbek sygnału wyjściowego. W filtrach takich występuje zatem sprzęże-
nie zwrotne, co ma zasadniczy wpływ na ich funkcjonowanie.
Wymienione typy filtrów cyfrowych różnią się właściwościami, z których wymienimy
najważniejsze:
 filtry IIR wymagają wykonania znacznie mniejszej liczby operacji niż filtry FIR dla
uzyskania funkcji przenoszenia o zbliżonych parametrach,
 filtry IIR mają skłonności do wzbudzeń, czyli samoczynnej generacji niepożądanych
sygnałów, której to wady nie mają filtry FIR,
 filtry IIR mają nieliniową charakterystykę fazową, zaś filtry FIR z natury mają
charakterystykę liniową.
Wybór typu filtru zależy od tego, które z wymienionych zalet i wad mają większe zna-
czenie w danym zastosowaniu.
Filtry cyfrowe IIR są na ogół odpowiednikami filtrów analogowych i mają podobne pa-
rametry (często lepsze) i podobne funkcje przenoszenie. W związku z tym noszą te same na-
zwy, jak ich pierwowzory analogowe. Program MALTAB dysponuje bardzo wygodnymi i
prostymi narzędziami do projektowani filtrów obu typów. Narzędzia takie mają formę funk-
cji, których parametrami są pożądane parametry filtrów, a zmiennymi wyjściowymi – współ-
czynniki a(m) i b(p) występujące w podanym wyżej wzorze. Liczba i znaczenie parametrów
zależy od rodzaju filtru. Pokażemy to na przykładach jednego filtru IIR i jednego filtru FIR.
Opis pozostałych filtrów Czytelnik znajdzie w Help programu MATLAB pisząc help <na-
zwa filtru>. Dla ułatwienia poszukiwań podamy niżej listę dysponowanych rodzajów filtrów.
130

Filtry o nieskończonej odpowiedzi impulsowej:


butter - filtr Butterwortha (maksymalnie płaska funkcja przenoszenia)
cheby1 - filtr Czebyszewa (zadane zafalowania w paśmie przenoszeni)
cheby2 - filtr Czebyszewa (zadane zafalowania w paśmie zaporowym).
ellip - filtr eliptyczny
maxflat - uogólniony dolnopasmowy filtr Butterwortha
yulewalk - filtrYule’a-Walkera
Filtry o skończonej odpowiedzi impulsowej:
cremez - filtr o nieliniowej, równofalistej charakterystyce fazowej
fir1 - filtr oparty na metodzie okien (dolno-, górno- i pasmowo przepustowy
lub zaporowy).
fir2 - filtr o dowolnej charakterystyce projektowany metodą próbkowania
częstotliwości
fircls - filtr projektowany metodą najmniejszych kwadratów
(o dowolnej odpowiedzi impulsowej)
fircls1 - filtr dolno- i górnoprzepustowy projektowany metodą najmniejszych
kwadratów
firgauss - filtr Gaussa
firls - filtr optymalny wg. normy najmniejszych kwadratów
firrcos - filtr kosinusowy z piedestałem.
intfilt - filtr interpolacyjny
remez - optymalny filtr wg. normy Czebyszewa
sgolay - wygładzający filtr Savitzky’ego-Golay’a
Sposób projektowania filtrów omówimy na przykładzie jednego typu filtru IIR i jed-
nego typu filtru FIR. Zaprojektujmy najpierw filtr dolnoprzepustowy o maksymalnie płaskiej
charakterystyce amplitudowej i częstotliwości granicznej fg =16 kHz. Filtr ten jest przezna-
czony do filtrowania sygnału próbkowanego z częstotliwością Fs=42 kHz. Funkcja
[B,A]=butter(N,W,’rodzaj’)
wyznacza wektor B współczynników b(p) i wektor A współczynników a(m) podanego wyżej
równia różnicowego. Liczba N jest rzędem filtru, a liczba W określa jego częstotliwość gra-
niczną. Wyznacza się ją z zależności
W=2fg/Fs
Liczba W musi być mniejsza od 1, czyli fg musi być mniejsze od Fs/2. Czy większy jest
rząd filtru, tym zbocza charakterystyki amplitudowej są bardziej strome, ale wykonywanych
jest więcej obliczeń.
Parametr ‘rodzaj’ może występować jako ‘high’, co oznacza, że filtr jest górnoprzepu-
stowy. Brak parametry jest równoznaczny z żądaniem, aby filtr był dolnoprzepustowy.
Dla filtru rzędu N=8 program wyznaczający wektory B i A ma następującą postać:
N=8;fg=16000;Fs=42000;
W=2*fg/Fs;
[B,A]=butter(N,W)
B=
0.1384 1.1073 3.8755 7.7511 9.6888 7.7511 3.8755 1.1073 0.1384
A=
1.0000 4.1743 8.1778 9.6091 7.3332 3.6968 1.1966 0.2266 0.0192
Zauważmy, żel liczba elementów obu wektorów wynosi N+1.
131

Funkcje przenoszenia zaprojektowanego filtru wyznaczają funkcje freqz i freqs, z któ-


rych pierwsza jest wynikiem zastosowania przekształcenia Fouriera do równania różnico-
wego, a druga – przekształcenia Laplce’a. Funkcje te różnią się zmiennymi niezależnymi i
przyjętymi skalami. Ograniczymy się tu do funkcji freqz. Funkcja
freqz(B,A)
wykonuje wykresy charakterystyki amplitudowej i fazowej filtru w 512 punktach znormali-
zowanej częstotliwości 2f/Fs w zakresie od 0 do 1, czyli do połowy częstotliwości próbkowa-
nia. Jeżeli chcemy wykresy przedstawić w funkcji nieznormalizowanej częstotliwości, wów-
czas posługujemy się funkcją freqz z dodatkowymi argumentami, a mianowicie
freqz(B,A,N,Fs),
gdzie N jest liczbą punktów na skali częstotliwości, a Fs – częstotliwością próbkowania.
Korzystając z tej funkcji, na rys. 7.18 pokazano wykresy charakterystyki amplitudowej i
fazowej zaprojektowanego wyżej filtru. Wstawiono N=420 oraz Fs=42000.

Rys. 7.18. Charakterystyka amplitudowa i fazowa filtru Butterwortha.


Instrukcja
[H,F]=freqz(B,A,N,Fs)
zwraca wektor H, który zawiera wartości zespolone funkcji przenoszenia oraz wektor F – za-
wierający wartości częstotliwości, dla których wyznaczono wektor H. Wektory te można wy-
korzystywać w dalszych obliczeniach.
Zaprojektujemy teraz filtr górnoprzepustowy o skończonej odpowiedzi impulsowej.
Wybierzemy filtr projektowany metodą okien fir1. Założymy, że rząd filtru wynosi N=60,
dolna częstotliwość graniczna fd= 4.2 kHz, a częstotliwości próbkowania Fs=42 kHz. Odpo-
wiedni program ma następujący zapis:
N=60;fd=4200;Fs=42000;
W=2*fd/Fs;
B=fir1(N,W);
132

Pomijamy długi wektor B współczynników filtru i wykonujemy wykresy funkcji prze-


noszenia pisząc:
freqz(B,1,420,42000);
W wyniku otrzymujemy charakterystyki amplitudową i fazową zaprojektowanego filtru,
pokazane na rys. 7.19. W miejsce wektora A należy wpisać 1, gdyż wektor współczynników
a(m) zawiera tylko jeden element a(1)=1.

Rys. 7.19. Charakterystyki amplitudowa i fazowa filtru o skończonej odpowiedzi impulsowej.


Jak widać, charakterystyka fazowa filtru jest liniowa w zakresie pasma przenoszenia, co
jest charakterystyczną cecha filtrów o skończonej odpowiedzi impulsowej FIR.
Dysponując wektorami A i B, opisującymi zaprojektowany filtr, można dokonać filtracji
sygnału dyskretnego zapisany wektorem x. Do tego celu służy instrukcja filter o następującej
postaci:
y=filter(B,A,x)
Instrukcja ta wykonuje obliczenia opisane równaniem różnicowym podanym na wstępie
tego punktu. Jeżeli w miejsce wektora x wstawimy macierz X, wówczas otrzymujemy macierz
Y, która jest wynikiem filtracji wszystkich kolumn macierzy X.
Efekt filtracji zademonstrujemy na przykładzie zaszumionego sygnału sinusoidalnego.
Niech sygnał sinusoidalny s ma amplitudę so=1, częstotliwość fo=1 kHz, a szum jest białym
szumem gaussowskim n o zerowej wartości średniej i dyspersji =0.5. Sygnał x jest sumą sy-
gnału s i szumu n. Przyjmiemy, że częstotliwość próbkowania Fs=20fo, a czas obserwacji sy-
gnału wynosi T=10 ms. Zastosujemy filtr pasmowo przepustowy Butterwortha rzędu 8 o pa-
śmie przenoszenia od 600 Hz do 1400 Hz. Realizacje opisanego zadania zapewnia następu-
jący program:
%Dane
so=1; % Amplituda sygnału sinusoidalnego
fo=1000; % Częstotliwość sygnału sinusoidalnego [Hz]
Fs=20*fo; % Częstotliwość próbkowania [Hz]
T=0.01 % Czas obserwacji [s]
sigma=0.5 % Dyspersja szumu
133

% Generacja sygnału
M=T*Fs; % Liczba próbek sygnału
m=1:M; % Ciąg numerów próbek
s=so*sin(2*pi*fo*m/Fs); % Sygnał sinusoidalny
n=sigma*randn(1,M); % Szum
x=s+n; % Sygnał z szumem

%Projekt filtru
Wn=2*[600 1400]/Fs; % Wektor granic pasma przenoszenia filtru
[B,A]=butter(8,Wn); % Wektory współczynników filtru Butterwortha

% Filtracja
y=filter(B,A,x); % Filtracja sygnału z szumem
z=filter(B,A,s); % Filtracja sygnału sinusoidalnego

%Wykresy
skala=m*10^3*T/M;
subplot(2,2,1);plot(skala,s,'k');axis([0 10 -2 2]);xlabel( 't [ms]');ylabel('s')
subplot(2,2,2);plot(skala,x,'k');axis([0 10 -2 2]);xlabel( 't [ms]');ylabel('x=s+n)')
subplot(2,2,3);plot(skala,z,'k');axis([0 10 -2 2]);xlabel( 't [ms]');ylabel('z')
subplot(2,2,4);plot(skala,y,'k');axis([0 10 -2 2]);xlabel( 't [ms]');ylabel('y')
Wynikiem działania powyższego programu jest następujący rysunek.

Rys. 7.20. Filtracja pasmowo przepustowa sygnału dyskretnego: s – sygnał sinusoidalny, x –


sygnał z szumem, z – sygnał sinusoidalny na wyjściu filtru, y – sygnał z szumem na wyjściu filtru.
Zauważmy, że sygnał sinusoidalny na wyjściu filtru jest opóźniony i zniekształcony.
Jest to cecha charakterystyczna wszystkich filtrów, przy czym opóźnienie w filtrach o nie-
skończonej odpowiedzi impulsowej zależy od częstotliwości i na ogół nie może być skom-
pensowane. Zniekształcenia występują na początku sygnału (stan nieustalony) i zmniejszają
się z upływem czasu.
134

Sygnał z szumem na wyjściu filtru znacznie różni się od sygnału wejściowego, co jest
efektem poprawy stosunku sygnału do szumu. Jest także opóźniony i ma stan nieustalony,
lecz dodatkowo zmienia się jego amplituda i faza. Efekt te nie zanika z upływem czasu, gdyż
jest skutkiem szumu, który pozostał po filtracji.
Poprawę stosunku sygnału do szumu uzyskaną dzięki filtracji można oszacować nume-
rycznie wprowadzając pewne zmiany i uzupełnienia w podanym wyżej programie.
%Dane
so=1; % Amplituda sygnału sinusoidalnego
fo=1000; % Częstotliwość sygnału sinusoidalnego [Hz]
Fs=20*fo; % Częstotliwość próbkowania [Hz]
T=10 % Czas obserwacji [s]
sigma=0.5 % Dyspersja szumu
% Generacja sygnału
M=T*Fs; % Liczba próbek sygnału
m=1:M; % Ciąg numerów próbek
s=so*sin(2*pi*fo*m/Fs); % Sygnał sinusoidalny
n=sigma*randn(1,M); % Szum
x=s+n; % Sygnał z szumem
%Projekt filtru
Wn=2*[600 1400]/Fs; % Wektor granic pasma przenoszenia filtru
[B,A]=butter(8,Wn); % Wektory współczynników filtru Butterwortha
% Filtracja
z=filter(B,A,s); % Filtracja sygnału sinusoidalnego
v=filter(B,A,n); % Filtracja sygnału sinusoidalnego
% Obliczenia
SNRx=var(s)/var(n) % Wejściowy stosunek sygnału do szumu
SNRy=var(z)/var(v) % Wyjściowy stosunek sygnału do szumu
b=SNRx/SNRy % Wskaźnik poprawy stosunku sygnału do szumu
p=Fs/(1400-600) % Teoretyczny wskaźnik poprawy stosunku sygnału do szumu

% Wyniki
SNRx =
2.0003
SNRy =
24.5071
p=
12.2516
P=
12.5000

Zgodnie z przewidywaniami teoretycznymi, wynikiem filtracji jest poprawa stosunku


sygnału do szumu. Wejściowy stosunek sygnału do szumu SNRx, który teoretycznie wynosi 2,
w symulacji numerycznej ma wartość 2.0003. Wyjściowy stosunek sygnału do szumu przy
idealnej filtracji powinien mieć wartość 25, a w symulacji ma 24.5071. W rezultacie otrzy-
mano poprawę stosunku sygnału do szumu nieco różną od teoretycznej: 12.2516 zamiast 12.5.
Aby zbliżyć wyniki symulacji do wyników teoretycznych przyjęto długi czas obserwacji T=10
s, co należy czynić zawsze, gdy sygnał jest stochastyczny.
Zmieniając w powyższym programie tylko jedną instrukcję można dokonać filtracji
tego samego sygnału filtrem o skończonej odpowiedzi impulsowej. Jeżeli w miejsce instrukcji
[B,A]=butter(8,Wn) wpiszemy np.
B=fir1(60,Wn); A=1
to otrzymamy wyniki pokazane na rys. 7.21.
135

Rys. 7.21. Filtracja sygnału filtrem o skończonej odpowiedzi impulsowej.


Zastosowany filtr poprawia stosunek sygnału do szumu około 15.5 razy. Wynika to
stąd, że efektywna szerokość pasma przenoszenia filtru jest mniejsza od wynikającej z wek-
tora Wn (kształt modułu funkcji przenoszenia znacznie różni się od prostokątnego, a granice
pasma przenoszenia podane są na poziomie – 6 dB).
Podobnie jak w wypadku filtru IIR, filtr FIR wnosi opóźnienie, a sygnał wyjściowy ma
stan nieustalony. Różnica polega na tym, że opóźnienie w filtrze FIR jest stałe – niezależne od
częstotliwości sygnału wejściowego.

7.6. Splot
Operacja splotu wykorzystywana jest w analizie systemów i układów liniowych w dzie-
dzinie czasu oraz w innych zastosowaniach. Jeżeli system lub układ opisany jest odpowiedzią
impulsową k(t), czyli odpowiedzią na impuls Diraca, to między sygnałem wejściowym x(t) i
sygnałem wyjściowym y(t) zachodzi zależność splotowa:

y( t )   k()x(t  )d .


W obliczeniach numerycznych przyjmuje się z reguły, że odpowiedź impulsowa i sy-


gnał wejściowy mają wartość zero dla t<0. W ujęcie analitycznym całka splotu ma wtedy inne
granice, a mianowicie:
t


y( t )  k( )x( t  )d .
0

W wersji dyskretnej powyższa całka zastąpiona jest następującą sumą:


136

n
y(n)   k(m)x(n  m) ,
m1
m<n

Wzór ten odpowiada zasadzie obowiązującej w programie MATLAB, według której


ciągi są numerowane od 1.
Funkcja splotu ma następujący zapis:
y=conv(k,x)
Jeżeli ciąg k ma długość lk, ciąg x ma długość lx, to długość ciągu y wynosi ll=lk+lx-1.
Ciągi k, n mogą mieć wartości rzeczywiste lub zespolone, a w wyniku otrzymujemy ciąg y
również o wartościach rzeczywistych bądź zespolonych.
Działanie funkcji conv ilustruje następujący prosty przykład. Niech k i x będą ciągami
o długości L=15. Ciąg k zawiera impuls prostokątny o długości lk=5, a ciąg x – impuls prosto-
kątny od długości lx=10. Wyznaczymy splot y obu ciągów liczbowych.
% Dane
l=15; lk=5; lx=10;
% Generacja ciągów
k=zeros(1,Lk);
x=k;
k(1:lk)=1;
x(1:lx)=1;
% Splot
y=conv(k,x);
% Wykresy
subplot(3,1,1);stem(k);xlabel(‘n’);ylabel(‘k’)
subplot(3,1,2);stem(x);xlabel(‘n’);ylabel(‘x’)
subplot(3,1,3);stem(y);xlabel(‘n);ylabel(‘y’)

Rys. 8.22. Splot y(n) ciągów k(n) i x(n).


Wyznaczony ciąg ma kształt impulsu trapezowego, co można łatwo wykazać analitycz-
nie. Długość ciągu wynosi 29, gdyż ciągi k i x mają długość 15.
Operacja splotu jest równoważna podanym niżej operacjom wykonywanym w dziedzi-
nie częstotliwości.
137

K=fft(k); % Widmo ciągu k (funkcja przenoszenia)


X=fft(x); % Widmo ciągu x
Y=K.*X; % Mnożenie widm
y=ifft(Y); % Odwrotna transformacja Fouriera
stem(abs(y)) % Wykres

Rys. 7.23. Ciąg y(n) wyznaczony operacjami w dziedzinie częstotliwości.

8. ANALIZA NUMERYCZNA OBWODÓW I UKŁADÓW ELEKTRYCZNYCH


8.1. Obwody prądu stałego
Pokażemy dwa przykłady numerycznego rozwiązywania obwodów prądu stałego me-
todą prądów oczkowych i napięć węzłowych.
Schemat pokazany na rys. 8.1 przedstawia obwód zawierający pięć oczek, a więc sto-
sunkowo trudny do rozwiązania analitycznego.

E4
R4

R45
J4
R1 R24 R34 E5

J5

E1 R12 R23 R35 R5


J1 J2 J3

Rys.8.1. Schemat obwodu prądu stałego.


138

Obwód ten można opisać następującym równaniem macierzowym


R1  R12  R12 0 0 0   J1   E1 
     
  R12 R12  R 23  R 24  R 23  R 24 0   J2   0 
 0  R 23 R 23  R 34  R 35  R 34  R 35   J3    0 
     
 0  R 24  R 34 R 4  R 24  R 34  R 45  R 45  J 4   E 4 
  R 35  R 45 R 5  R 35  R 45  J5   E5 
 0 0

lub w zwięzłej formie jako


[R]  [J]  [E] lub R∙I=E

Prądy oczkowe są rozwiązaniem tego równania macierzowego, które można zapisać


jako:
-1
J=R ·E lub J=inv(R)·E
Program, który przedstawiono niżej, rozwiązuje powyższy układ równań dla wpisywa-
nych ręcznie wartości oporności i sił elektromotorycznych oraz wyznacza prądy płynące
przez oporności, spadki napięcia na nich oraz wydzielające się w nich moce.
R=zeros(5,5);
E=zeros(5,1);
% Wprowadzanie danych
R1=input('R1=');
R4=input('R4=');
R5=input('R5=');
R(1,2)=-input('R12=');
R(2,3)=-input('R23=');
R(2,4)=-input('R24=');
R(3,4)=-input('R34=');
R(3,5)=-input('R35=');
R(4,5)=-input('R45=');
E(1)=input('E1=');
E(4)=input('E4=');
E(5)=-input('E5=');
%Wyznaczanie elementów macierzy na przekątnej
R(1,1)=R1-R(1,2);
R(2,2)=-R(1,2)-R(2,3)-R(2,4);
R(3,3)=-R(2,3)-R(3,4)-R(3,5);
R(4,4)=R4-R(2,4)-R(3,4)-R(4,5);
R(5,5)=R5-R(3,5)-R(4,5);
%Uzupełnienie elementów macierzy
for n=1:5;
for m=1:5
R(m,n)=R(n,m);
end
end
% Wyznaczanie prądów oczkowych
J=inv(R)*E
% Wyznaczanie prądów płynących przez oporności
I1=J(1)
I12=J(1)-J(2)
I23=J(2)-J(3)
I24=J(2)-J(4)
I34=J(3)-J(4)
I35=J(3)-J(5)
I4=J(4)
I45=J(4)-J(5);I5=J(5)
% Wyznaczanie spadków napięć na opornościach
139

U1=I1*R1
U12=I12*R(1,2)
U23=I23*R(2,3)
U24=I24*R(2,4)
U34=I34*R(3,4)
U35=I35*R(3,5)
U4=I4*R4
U45=I45*R(4,5)
U5=I5*R5
% Moc wydzielająca się na opornościach
P1=abs(U1*I1)
P12=abs(U12*I12)
P23=abs(U23*I23)
P24=abs(U24*I24)
P34=abs(U34*I34)
P35=abs(U35*I35)
P4=abs(U4*I4)
P45=abs(U45*I45)
P5=abs(U5*I5*R5)
%Sprawdzenie
P=P1+P12+P23+P24+P34+P35+P4+P45+P5 % Suma mocy wydzielających się na
opornościach
PD=E(1)*I1+E(4)*I4+E(5)*I5 % Suma mocy dostarczonych ze źródeł
if P==PD
'Wyniki prawidłowe'
else
'Błędy!'
end
W analogiczny sposób rozwiązuje się obwody prądu stałego metodą napięć węzłowych.
Pokażemy to na prostym przykładzie obwodu, którego schemat zamieszczono na rys. 8.2.

U1 G12 U2 G23 U3

J1 G1 G2 G3 J3

Rys. 8.2. Obwód prądu stałego.


Obwód pokazany na powyższym rysunku opisują następujące równania:
G1U1  G12 (U1  U2 )  J1
G2U2  G12 (U2  U1 )  G23 (U2  U3 )  0
G3U3  G23 (U3  U2 )  J3

Powyższemu układowi równań można nadać formę macierzową:


G1  G12  G12 0  U1   J1 
     
  G12 G2  G12  G23  G23   U2    0 
 0  G23 G3  G23  U3   J3 

Napięcia węzłowe otrzymujemy rozwiązując to równanie macierzowe, a mianowicie:


140

U=inv(G)∙J.
Podany niżej program oblicza napięcia węzłowe, prądy płynące przez poszczególne
przewodności oraz moc wydzielającą się w obwodzie i moc do niego dostarczoną z obu źró-
deł.
%DANE
%Przewodności w [S]
G1=1; G2=2; G3=3;G12=1;G23=2;
% Prądy w [A]
J=[2 0 -1]';
%OBLICZENIA
%Wartości macierzy
G=zeros(3,3);
G(1,1)=G1+G12;
G(1,2)=-G12;G(2,1)=G(1,2);
G(2,2)=G2+G12+G23;
G(2,3)=-G23;G(3,2)=G(2,3);
G(3,3)=G3+G23;
'Napięcia węzłowe'
U=inv(G)*J
'Wartości prądów'
I1=G1*U(1)
I12=G12*(U(1)-U(2))
I2=G2*U(2)
I23=G23*(U(2)-U(3))
I3=G3*U(3)
'Moce w przewodnościach'
P1=I1^2/G1
P12=I12^2/G12
P2=I2^2/G2
P23=I23^2/G23
P3=I3^2/G3
'Suma mocy w przewodnościach'
P=P1+P12+P2+P23+P3
'Suma mocy dostarczonych'
PD=abs(J(1)*U(1))+abs(J(3)*U(3))
Dla wartości przewodności i prądów źródeł podanych w powyższym programie, wyniki
obliczeń są następujące:
>> ans =
Napięcia węzłowe
U=
1.0811
0.1622
-0.1351
ans =
Wartości prądów
I1 =
1.0811
I12 =
0.9189
I2 =
0.3243
I23 =
0.5946
I3 =
-0.4054
ans =
Moce w przewodnościach
141

P1 =
1.1687
P12 =
0.8444
P2 =
0.0526
P23 =
0.1768
P3 =
0.0548
ans =
Suma mocy w przewodnościach
P=
2.2973
ans =
Suma mocy dostarczonych
PD =
2.2973

8.2. Analiza obwodów RLC przy pobudzeniu sinusoidalnym


8.2.1. Obwód RL
Weźmy najpierw pod uwagę prosty obwód RL, w którym prąd wyznaczyliśmy rozwią-
zując równanie różniczkowe. Dla wygody Czytelnika schemat tego obwodu pokazano po-
nownie na rys. 8.3.

i(t) L

u(t) R

Rys. 8.3. Schemat obwodu RL.


Równanie różniczkowe tego obwodu ma postać:
di( t )
L  Ri( t )  u( t )
dt
Należy je poddać obustronnie przekształceniu Fouriera, a mianowicie
di( t )
L{ }  R{i( t )}  {u(t )}.
dt
Przy pobudzeniu sinusoidalnym w stanie ustalonym mamy:
jLI( j)  RI( j)  U( j) ,

a stąd otrzymujemy:
U( j) U( j)
I( j)   ,
R  jL Z( j)

gdzie Z(j) jest impedancją obwodu.


142

Przyjmijmy teraz, że obwód jest pobudzany napięciem sinusoidalnym o zapisie wykład-


niczym:
u(t )  U0 e jt

Stąd mamy:
U( j)  U0 oraz i(t )  I( j)e jt .
I(j) jest zespoloną amplitudą prądu, którą można zapisać jako:
I( j) | I( j) | e j( j)

gdzie |I(j)| jest amplitudą prądu, a - przesunięciem fazy między prądem i napięciem.
Napiszemy teraz program, który wykreśli zależność amplitudy i fazy w analizowanym
układzie w funkcji częstotliwości, a wyniki przedstawimy na rys. 8.4. Przyjmiemy jak po-
przednio, że R=1k, L=10 mH. Jedynym problemem jest właściwy dobór zakresu częstotliwo-
ści i odstępu między ich wartościami. Dobra wskazówką jest tzw. 3-decybelowa częstotliwość
graniczna, której wartość wynosi:
L
fg 
2R
Przyjmując przykładowo, że zakres skali częstotliwości wynosi 10fg i dzieląc go na 100
równych części mamy:
%DANE
R=10^4;
L=10^-2;
Uo=1;
%OBLICZENIA
fg=R/(2*pi*L) %Częstotliwość graniczna
f=0:5*fg/100:5*fg; % Skala częstotliwości
I=Uo./(R+i*2*pi*f*L); %Zespolone wartości prądu
Ia=abs(I); %Amplituda prądu
fi=angle(I)*180/pi; %Faza prądu
%WYKRESY
subplot(2,1,1);plot(f/fg,Ia,'k');xlabel('f/fg');ylabel('abs(I) [A]')
subplot(2,1,2);plot(f/fg,fi,'k');xlabel('f/fg');ylabel('faza [deg')
fg =
1.5915e+005
Mnożąc charakterystykę amplitudową prądu przez oporność R i dzieląc przez U0 otrzy-
mujemy napięciową funkcję przenoszenia, która ma identyczny przebieg, jak pokazana na
rys. 8.4 charakterystyka prądowa.
143

Rys. 8.4. Charakterystyka amplitudowa i fazowa prądu w obwodzie RL.

8.2.2. Szeregowy obwód rezonansowy


Wyznaczmy teraz funkcję przenoszenia obwodu pokazanego na rys. 8.5. Funkcję tę de-
finiujemy jako:
I( j)
K( j)  =
U( j)

Ponieważ I(j)=U(j)/Z(j), więc otrzymujemy:


1
K( j)   Y( j)
Z( j)

gdzie impedancja Z(j) jest równa:


1
Z( j)  jL  R 
jC

i(t) L C

u(t)
R

Rys. 8.5. Schemat szeregowego obwodu rezonansowego.


Oznaczając pulsację rezonansową obwodu jako
1
0 
LC
144

oraz dobroć obwodu jako


0L
Q
R
po prostych przekształceniach otrzymujemy:
1/ R
K( j)  .
 0
1  jQ(  )
0 

Zapisany niżej program wyznacza funkcję przenoszenia układu (admitancję) dla kilku
dobroci Q w funkcji znormalizowanej częstotliwości f/f0=/0. Funkcję tę znormalizowano
mnożąc ją przez R, w wyniku czego jest ona bezwymiarowa.
K=zeros(301,3);
for n=1:3
Q(n)=n^2;
f=0:0.01:3;
K(:,n)=1./(1+i*Q(n)*(f-1./f))';
end
plot(f,K,'k');xlabel('f/fo');ylabel('K(f/fo')
Funkcje przenoszenia obwodu (krzywe rezonansowe) pokazano na rys. 8.6.

Rys. 8.6. Krzywe rezonansowe obwodu RLC.

8.2.3. Sprzężone równoległe obwody rezonansowe


Wyznaczymy funkcję przenoszenia układu zbudowanego z dwóch równoległych obwo-
dów rezonansowych sprzężonych pojemnościowo. Układ taki pokazano na rys. 8.7.
145

C
J1

C1 G1 L1 C2 G2 L2 U2
1

Rys. 8.7. Układ dwóch sprzężonych, równoległych obwodów rezonansowych.


Do analizy układu zastosujemy metodę napięć węzłowych. Układ jest opisany następu-
jącą macierzą:
 Y11 Y12  U1  J1 
     ,
Y21 Y22  U2   0 

gdzie
1
Y11  jC1  G1   jC
jL1
Y12  Y21   jC
1
Y22  jC 2  G 2   jC
jL 2

Poszukiwana funkcja przenoszenia jest zdefiniowana jako:


U2 ( j)
K( j) 
J1( j)

Układ jest pobudzany z generatora prądowego przebiegiem sinusoidalnym o zapisie wy-


kładniczym
J1  J1( j)e jt

Jak wiadomo z teorii układów liniowych, napięcie U2 jest również sinusoidalne. Nie ma
zatem potrzeby wyznaczania jego przebiegu w czasie; wystarczy znajomość jego amplitudy
zespolonej U2(j). W miejsce J1(j) można wstawić amplitudę prądu o dowolnej wielkości, np.
J1=1 A, co nie wpływa na wynik obliczeń.
Rozpatrywany układ jest filtrem pasmowo-przepustowym. Elementy układu można do-
brać tak, aby filtr miał założoną częstotliwość środkową fo i pożądane pasmo przenoszenia B.
Jeżeli nie chcemy wyznaczać wartości elementów analitycznie, a zdać się wyłącznie na obli-
czenia numeryczne, konieczne jest wykonanie licznych prób i minimalizacja uzyskanych błę-
dów. W tym celu założymy na wstępie, że oba obwody rezonansowe są identyczne i mają
częstotliwości rezonansową równą częstotliwości środkowej filtru. Założymy także wstępnie,
że szerokość pasma przenoszenia pojedynczego obwodu rezonansowego jest równa połowie
szerokości pasma przenoszenia filtru B. Dodatkowo należy założyć wartość przewodności
obwodów rezonansowych G1=G2=G oraz podać wartość współczynnika k =2C/C1. Przy takich
założeniach obowiązują następujące zależności, wynikające ze znanych własności równole-
głych obwodów rezonansowych:
f0
Q dobroć obwodu rezonansowego
B
146

2f0C1
Q1  Q2=Q1
G1

G
C1  C2=C1
2B
kC 1
C
2
1
L1  L2=L1
( 2f0 )2 C 1

Przy takich założeniach program obliczający funkcję przenoszenia przedstawia się na-
stępująco:
%WPROWADZANIE DANYCH
fo=input('fo=');
B=input('B=');
G=input('G=');
k=input('k=');
%WYZNACZANIE WARTOŚCI ELEMENTÓW
C1=G/(pi*B);
L1=1/(C1*(2*pi*fo)^2);
C=k*C1/2;
%WYZNACZANIE ADMITANCJI
a=i*2*pi;
N=10^3;
K=zeros(1,N);
for n=1:N
s=a*(n-1)*2*fo/N+eps;
Y11=s*(C1+C)+G+1/(s*L1);
Y12=-s*C;
Y=[Y11 Y12;Y12 Y11]; %Macierz admitancji
%WYZNACZANIE FUNKCJI PRZENOSZENIA
U=inv(Y)*[1 0]'; %Rozwiązanie równania macierzowego
K(n)=U(2,1); % Funkcja przenoszenia
end
%WYZNACZANIE PARAMETRÓW FUNKCJI PRZENOSZENIA
P=abs(K)>0.707*max(abs(K));
PD=diff(P);
p=2*fo*find(PD)/N;
'Szerokość pasma przenoszenia [Hz]'
Bo=p(2)-p(1)
'Częstotliwość środkowa [ Hz]'
fc=(p(1,1)+p(1,2))/2
%WYKRES FUNKCJI PRZENOSZENIA
f=2*fo*(1:N)/N;
plot(f,abs(K),’k’)
Wpisując podane niżej wartości parametrów otrzymujemy wyznaczoną szerokość pa-
sma i częstotliwość środkową oraz wykres modułu funkcji przenoszenia, pokazany na rys.
8.8.
fo=1000
B=400
G=10^-3
k=0.8
ans =
Szerokość pasma przenoszenia [Hz]
Bo =
354
147

ans =
Częstotliwość środkowa [Hz]
fc =
893

Rys. 8.8. Moduł funkcji przenoszenia filtru z obwodami sprzężonymi.


Pomimo jednakowych częstotliwości rezonansowych obwodów równoległych funkcja
przenoszenia ma dwa maksima, z których jedno występuje na częstotliwości zbliżonej do
częstotliwości rezonansowej, a drugie – na niższej częstotliwości. Jest to charakterystyczne
dla obwodów sprzężonych pojemnościowo. Odstęp między tymi częstotliwościami jest tym
większy, im większa jest wartość współczynnika sprzężenia k, czyli im większa jest pojem-
ność C.
W celu otrzymania zakładanych parametrów filtru należy zwiększyć częstotliwość fo,
wartość współczynnika sprzężenia i ewentualnie pasmo przenoszenia B. Wstawiając niżej
podane wartości mamy:
fo=1130
B=400
G=10^-3
k=0.84
ans =
Szerokość pasma przenoszenia [Hz]
Bo =
402.2800
ans =
Częstotliwość środkowa [Hz]
fc =
1.0034e+003
Zważywszy, że obliczenia wykonywane są z krokiem 2 Hz, a więc wynik można uznać
za zadowalający.
Podany przykład nie pokazuje bynajmniej zalecanej metody projektowania filtrów z
obwodami sprzężonymi. Może być natomiast wykorzystany do weryfikacji filtrów zaprojek-
towanego inną metodą, zwłaszcza filtrów z większą liczbą obwodów rezonansowych.
148

8.3. Analiza obwodów RLC przy dowolnym pobudzeniu


8.3.1. Analiza numeryczna w dziedzinie częstotliwości
Do analizy obwodów RLC przy pobudzeniu nieharmonicznym można wykorzystać
dyskretną transformację Fouriera. Z własności dyskretnej transformaty Fouriera wynika, że
sygnał pobudzenia powinien mieć ograniczone widmo. Używane w praktyce sygnały mają
zawsze ograniczone widmo, lecz ich uproszczone modele niekiedy nie mają tej własności.
Stosując owe modele należy liczyć się z pewnymi błędami, które jednak można zmniejszać
do akceptowalnego poziomu.
Analiza numeryczna odbywa się w następujących etapach:
 próbkowanie wejściowego sygnału ciągłego z określoną częstotliwością Fs, speł-
niającą kryterium Nyquista
 wyznaczenie dyskretnej transformaty Fouriera sygnału
 wyznaczenie funkcji przenoszenia analizowanego układu
 numeryczny zapis funkcji przenoszenia w formie dyskretnej
 mnożenie dyskretnej funkcji przenoszenia przez dyskretne widmo sygnału
 wyznaczenie sygnału wyjściowego jako odwrotnej, dyskretnej transformaty
Fouriera z iloczynu widma sygnału i funkcji przenoszenia.
Częstotliwość próbkowania Fs należy dobrać tak aby jednocześnie spełniała kryterium
Nyquista dla sygnału wejściowego i była dwukrotnie większa od górnej częstotliwości pasma
przenoszenia układu.
W wyniku obliczenia dyskretnej transformaty Fouriera sygnału x(n), przy użyciu funkcji
w którym częstotliwość f(k) jest równa:
fft, otrzymujemy widmo X(k)
k 1
f (k )  Fs dla k=1,2,...,N/2+1
N
gdzie N jest liczbą próbek sygnału i jednocześnie liczbą prążków widma.
Prążki widma o wyższych numerach odpowiadają ujemnym częstotliwościom widma
ciągłego. Z tego względu należy funkcję przenoszenia układu dostosować do konwencji obo-
wiązującej w dyskretnym przekształceniu Fouriera. W tym celu z funkcji przenoszenia K(j)
pobieramy N próbek z odstępem Fs/N, a więc mamy:
k  1: N
dla N parzystych
K  K[ j2(Fs / N)( N / 2  k ]
k  1: N
dla N nieparzystych
K  K[ j2(Fs / N)( (N  1) / 2  k ]

Następnie należy utworzyć następująco wektor dyskretnej funkcji przenoszenia Kd:


Kd  [K(N / 2 : N) K(1 : N / 2  1)] dla N parzystych
Kd  [K((N  1) / 2 : N) K(1 : (N  1) / 2)] dla N nieparzystych
Kolejnym krokiem, jak już powiedziano, jest mnożenie dyskretnego widma sygnału
przez dyskretną funkcję przenoszenia:
Y=S.*Kd
Sygnał wyjściowy y otrzymujemy obliczając odwrotną transformatę Fouriera:
149

y=real(ifft(Y)
Jako przykład znajdziemy odpowiedź napięciową UR(t) układu RL pokazanego na rys.
8.3 na pobudzenie napięciem U(t) w postaci impulsu prostokątnego o czasie trwania ti. Funkcja
przenoszenia obwodu jest równa:
R 1 1
K( j)   
R  jL 1  j / g 1  jf / fg

gdzie fg=R/2L.
Ponieważ funkcja przenoszenia jest nieograniczona, więc w celu zapewnienia dobrej
dokładności obliczeń przyjmiemy:
Fs  20fg

Widmo impulsu prostokątnego jest również nieograniczone. Czas trwania impulsu na-
leży dobrać tak, aby istotna część widma była mniejsza od połowy częstotliwości próbkowa-
nia. Mamy zatem następujący warunek:
2 1
t i  
Fs 10fg

Można przykładowo przyjąć, że


2 4
t i  20 
Fs fg

Próbki funkcji przenoszenia mają następujące wartości dla N parzystych


1 1
K 
Fs N 20 N
1 i (  k ) 1  i (  k )
Nfg 2 N 2

Należy teraz wyznaczyć liczbę próbek ni impulsu prostokątnego. Jest ona równa:
ni  t iFs  40

Liczbę próbek N dobieramy tak aby była większa od czasu trwania impulsu, np.
N=5*ni=200. Umożliwia to napisanie następującego programu.
'Górna częstotliwość pasma przenoszenia układu RL [Hz]'
fg=input('fg=');
'Częstotliwość próbkowania [Hz]'
Fs=20*fg
'Czas trwania impulsu [s]'
ti=4/fg
ni=round(ti*Fs);
N=5*ni;
%Generacja impulsu
x=zeros(1,N);
x(1:ni)=1;
%Widmo impulsu
X=fft(x);
%Funkcja przenoszenia
k=1:N;
Kp=1./(1+i*(20/N)*(-N/2+k));
K=[Kp(N/2:N) Kp(1:N/2-1)];
%Wyznaczanie odpowiedzi układu
Y=X.*K;
y=real(ifft(Y));
150

%Wykresy
t=1000*(k-1)/Fs;
f=k*Fs/(10^3*N);
subplot(2,2,1); plot(t,x,'k');xlabel('t [ms]');ylabel('x(t)'); axis([0 10 -0.5 1.5])
subplot(2,2,2); plot(f,abs(K),'k');xlabel('f [kHz]');ylabel('|K(f)|');
subplot(2,2,3); plot(f,abs(X),'k');xlabel('f [kHz]');ylabel('|X(f)|');
subplot(2,2,4): plot(t,y,'k');xlabel('t [ms]');ylabel('y(t)');axis([0 10 -0.5 1.5])
Na rys. 8.9 przedstawiono wyznaczone przez powyższy program przebiegi sygnałów
oraz widmo impulsu i funkcję przenoszenia.

Rys. 8.9. Odpowiedź y(t) układu RL o funkcji przenoszenia K(f) na impuls prostokątny x(t).

8.3.2. Analiza numeryczna w dziedzinie czasu


W układach liniowych odpowiedź układu y(t) jest splotem jego odpowiedzi impulsowej
k(t) z pobudzeniem x(t), co zapisujemy symbolicznie jako:
y(t )  k(t )  x(t ) .

W programie MATLAB powyższy splot ma następujący zapis


y=conv(k,x)
Problem sprowadza się do wyznaczenia odpowiedzi impulsowej układu. Można to zro-
bić na kilka sposobów, a mianowicie:
 wyznaczyć analitycznie odpowiedź impulsową układu i zapisać ją w formie
ciągu próbek
 wyznaczyć numerycznie odpowiedź impulsową układu rozwiązując jego
równanie różniczkowe
 wyznaczyć numerycznie odpowiedź impulsową jako odwrotną transformatę
Fouriera funkcji przenoszenia
Ponieważ żaden z tych sposobów nie jest prosty w odniesieniu do bardziej złożonych
układów, więc analiza w dziedzinie czasu nie jest popularna. Dlatego pokażemy tu jedynie
151

prosty przykład odnoszący się do układu RL rozpatrywanego w poprzednim punkcie. Odpo-


wiedź impulsową wyznaczymy analitycznie, jako odwrotną transformatę Fouriera funkcji
przenoszenia układu. Funkcja przenoszenie jest równa:
UR ( j) R
K( j)  
U( j) R  jL

Korzystając ze znanych zależności transformacji Fouriera mamy:


1
k( t )  1 {K( j)}  1( t ) e  t / 

gdzie =L/R, a 1(t) jest funkcją jednostkową.
W zapisie dyskretnym odpowiedź impulsowa ma następującą postać:
1 n / Fs
k(n)  e n=0,1,2,.....,N-1

Znając odpowiedź impulsową układu można wyznaczyć jego odpowiedź przy dowol-
nym pobudzeniu. Przedstawiony niżej program wyznacza takie odpowiedzi dla impulsu pro-
stokątnego i wykładniczego.
%Dane
'Stała czasowa układu [ms]'
tu=input('tu=');
'Czas trwania impulsów [ms]'
ti=input('ti=');
%Obliczenia
dt=ti/100; %Okres próbkowania
N=5*ti/dt; %Liczba próbek sygnałów
sp=zeros(1,N); %Sygnał prostokątny
sp(1:ti/dt)=1;
n=0:N-1;
sw=exp(-n*dt/ti); %Impuls wykładniczy
k=exp(-n*dt/tu)/tu; %Odpowiedź impulsowa
yp=conv(k,sp); %Odpowiedź na impuls prostokątny
yw=conv(k,sw); %Odpowiedź na impuls wykładniczy
%Wykresy
t=(0:N-1)*dt;
subplot(2,2,1); plot(t,sp); xlabel('t [ms]'); ylabel('Uwej(t)')
hold on
subplot(2,2,1); plot(t,sw);
subplot (2,2,2); plot(t,k); xlabel('t [ms]'); ylabel('k(t)')
subplot(2,2,3); plot(t,yp(1:N)); xlabel('t [ms]'); ylabel('Uwyj(t)')
subplot(2,2,4);plot(t,yw(1:N)); xlabel('t [ms]'); ylabel('Uwyj(t)')
Na rys. 8.10 pokazano impulsy wejściowe i wyjściowe oraz odpowiedź impulsową dla
czasy trwania impulsów 100 ms i stałej czasowej układu 50 ms.
152

Rys. 8.10. Pobudzenia, odpowiedź impulsowa układu RL oraz sygnały wyjściowe.

8.4. Projektowanie filtrów analogowych


8.4.1. Podstawy teoretyczne
Większość filtrów analogowych, to filtry aktywne, w których wykorzystuje się pasywne
obwody RLC do kształtowania charakterystyk przenoszenia, a układy aktywne do wzmacnia-
nia sygnału i separacji obwodów pasywnych. Filtry takie projektuje się tak, żeby obwody
aktywne nie miały wpływu na kształt charakterystyk przenoszenia. W ujęciu ogólnym, struk-
turę filtru pokazuje rys. 8.11.

Wzmacniacz- Obwód Wzmacniacz- Obwód


separator RLC separator RLC
W1 K1(s) W2 K2(s)

Rys. 8.11. Ogólny schemat filtru aktywnego


Wzmocnienia i funkcje przenoszenia mogą być rozmaicie definiowane w zależności od
konstrukcji filtru. Mogą to być wzmocnienia prądowe, napięciowe, ale także stosunki napięć
do prądów lub odwrotnie. Podobnie funkcje przenoszenia mogą opisywać stosunki napięć
wyjściowych do wejściowych, prądów wyjściowych do wejściowych, lecz również stosunki
np. napięć wyjściowych do prądów wejściowych. W każdym jednak wypadku funkcja prze-
noszenia (transmitancja) wyrażona jest jako iloraz transformat Laplace’a odpowiednich na-
pięć bądź prądów.
Transmitancja filtru może być w każdym z omawianych przypadków zapisana jako:
K(s)  W1  K1(s)  W2  K 2 (s)  ...  Wn  Kn (s)

Ponieważ wzmocnienie nie ma wpływu na przebieg funkcji przenoszenia, więc analizę


można ograniczyć do następującego zapisu:
153

K(s)  K1(s)  K 2 (s)  ...  Kn (s)

Transmitancja filtru jest iloczynem transmitancji poszczególnych obwodów pasywnych.


Mnożąc transmitancję obwodów otrzymujemy funkcją niewymierną o ogólnej postaci:
L

 a(l)s
l0
l

K( s)  M

 b(m)s
m0
m

W liczniku i mianowniku występują wielomiany zmiennej s odpowiednio rzędu L i M,


przy czym L<M.
Obwody należy zaprojektować tak, aby iloczyn ich transmitancji miał założony prze-
bieg w funkcji częstotliwości. W syntezie filtrów przebieg transmitancji określają jej zera i
bieguny. Zera są to wartości zmiennej zespolonej s, przy których transmitancja ba wartość
zerową. Bieguny są miejscami zerowymi (pierwiastkami) wielomianu występującego w mia-
nowniku.
Rozkład zer i biegunów transmitancji zależy od rodzaju filtru i jego parametrów. Z kolei
od rodzaju filtrów zależy kształt funkcji przenoszenia i jej własności. Do najczęściej stosowa-
nych rodzajów filtrów należą:
 filtry Butterwortha o maksymalnie płaskiej są charakterystyce amplitudowej
 filtry Czebyszewa o równofalistej charakterystyce amplitudowej
 filtry Bessela o liniowej charakterystyce fazowej
Program MATLAB dysponuje następującymi funkcjami wyznaczającymi zera i bie-
guny transmitancji filtrów analogowych:
butter filtr Butterwortha
cheby1 filtr Czebyszewa pierwszego rodzaju
cheby2 filtr Czebyszewa drugiego rodzaju
besself filtr Bessela
besselap znormalizowany filtr Bessela
ellip filtr eliptyczny
Składnia podanych wyżej funkcji nie różni się znacznie od składni odpowiednich funk-
cji do projektowania filtrów cyfrowych. I tak dla filtrów dolnoprzepustowych i pasmowo
przepustowych mamy:
[z,p,k]=butter(N,W,’s’)
gdzie N jest rzędem filtru, W jest pulsacją w [rad/s] określającą 3-decybelowe pasmo przeno-
szenia filtru dolnopasmowego, a ‘s’ jest parametrem wskazującym, że funkcja dotyczy filtru
analogowego. W odróżnieniu od filtrów cyfrowych W nie jest liczbą ograniczoną. Jeżeli filtr
jest pasmowoprzepustowy, to W jest wektorem W=[Wd Wg], gdzie Wd jest dolną, 3-decybe-
lową pulsacją graniczną, a Wg – górną 3-decybelową pulsacją graniczną. Jeżeli filtr jest gór-
noprzepustowy lub zaporowy to piszemy odpowiednio:
[z,p,k]=butter(N,W,’high’,’s’)
[z,p,k]=butter(N,W,’stop’,’s’)
154

Program zwraca wartości zer i biegunów transmitancji i wartość wzmocnienia w ukła-


dzie pokazanym na przykładzie filtru pasmowoprzepustowego 5. rzędu o częstotliwości gra-
nicznej 800Hz.
>>W=2*pi*800;
>> [z,p,k]=butter(5,W,'s')
z=
Empty matrix: 0-by-1
p=
1.0e+003 *
-1.5533 + 4.7805i
-1.5533 - 4.7805i
-4.0666 + 2.9545i
-4.0666 - 2.9545i
-5.0265
k=
3.2088e+018
Interpretacja wyników jest następująca:
z=
Empty matrix: 0-by-1
Pusta macierz zer oznacza, że w liczniku występuje tylko liczba (zerowy stopień wie-
lomianu).
W liczniku mamy pięć pierwiastków, czyli transmitancja ma pięć biegunów. Po dwa z
tych biegunów są zespolone i sprzężone, a jeden jest biegunem rzeczywistym. Daje to wska-
zówkę z jakich obwodów ma być skonstruowany projektowany filtr. Bieguny zespolone,
sprzężone mają obwody rezonansowe, zaś bieguny rzeczywiste – obwody RC i RL. Do za-
gadnienia tego wrócimy w dalszej części tego punktu.
Podamy teraz przykład filtru pasmowo przepustowego 5. rzędu o częstotliwościach gra-
nicznych 800 Hz i 1200 Hz.
W=2*pi*[800 1200];
[z,p,k]=butter(5,W,'s')
z=
0
0
0
0
0
p=
1.0e+003 *
-0.4625 + 7.4547i
-0.4625 - 7.4547i
-1.1394 + 6.8563i
-1.1394 - 6.8563i
-1.2566 + 6.0266i
-1.2566 - 6.0266i
-0.8939 + 5.3791i
-0.8939 - 5.3791i
-0.3142 + 5.0644i
-0.3142 - 5.0644i
k=
1.0028e+017
W mianowniku mamy 5 zer, co oznacza, że występuje w nim wielomian s5 posiadający
pięciokrotny pierwiastek zerowy. W mianowniku mamy wielomian 10. stopnia, który ma 10
parami sprzężonych pierwiastków zespolonych. Takim wielomianem opisany jest filtr zawie-
155

rający 5 obwodów rezonansowych. Współczynniki wielomianów można wyznaczyć wyko-


rzystując funkcję poly lub pisząc:
[B,A]=butter(5,W,'s')
Zapis funkcji cheby1 i cheby2 jest następujący:
[z,p,k]=chebz1(N,D,W,'s')
W miejsce symbolu D należy wpisać w decybelach wielkość zafalowania w paśmie
przenoszenia. W funkcji cheby2, symbol D oznacza tłumienie (w decybelach) w paśmie zapo-
rowym, zaś W pulsację (lub pulsacje) graniczną pasma zaporowego. Parametry ‘high’ i ‘stop’
mogą być także używane.
Zapis funkcji besself jest identyczny jako funkcji butter. W zapisie funkcji besselap po-
dajemy tylko rząd filtru:
[z,p,k]=besselap(N)
Składnia funkcji ellip jest następująca:
[z,p,k] = ellip(N,Dp,Ds,W,’s’)
gdzie Dp [dB] oznacza zafalowanie w paśmie przenoszenia, a Ds [dB] – minimalne tłumienie
w paśmie zaporowym.

8.4.2. Wybór rozwiązania konstrukcyjnego


Praktyczny filtr analogowy zbudowany jest z układów aktywnych (wzmacniaczy,
wzmacniaczy operacyjnych) i obwodów pasywnych. Dysponując określonym układem
wzmacniacza należy określić, od jakiej funkcji opisującej obwód zależy wzmocnienie
wzmacniacza. Może to być impedancja obwodu, admitancja lub funkcja przenoszenia. Na-
stępnie należy wybrać rodzaje obwodów, których owa funkcja (ogólnie mówiąc transmitan-
cja) ma cechy odpowiadające wymaganiom określonym w poprzednim punkcie. Do dyspozy-
cji mamy elementy RLC, które można połączyć w rozmaitych konfiguracjach, z których
każda ma specyficzne własności. Generalnie rzecz ujmując transmitancje wszystkich obwo-
dów RL i RC mają pojedyncze bieguny rzeczywiste, a obwodów RLC, sprzężone bieguny
zespolone. Tak więc, jeżeli w projektowanym filtrze występują bieguny rzeczywiste, to reali-
zować je będziemy za pomocą obwodów RL lub RC. Podobnie bieguny zespolone będą reali-
zowane za pomocą szeregowych lub równoległych obwodów rezonansowych. Pozostaje do
rozwiązania kwestia wyboru tych obwodów i ustalenia ich konfiguracji. Przydatna jest do
tego znajomość impedancji, admitancji i funkcji przenoszenia poszczególnych obwodów.
Poniżej podamy wybrane konfiguracje obwodów przydatnych w konstruowaniu filtrów i opi-
sujące je funkcje oraz wartości biegunów. W przedstawionym zestawieniu bieguny mają na-
stępujący zapis:
1
s1  1  j1 s1*  1  j1 1  12  12 12 
LC
Admitancja szeregowego obwodu rezonansowego:
1 s R
Y(s)  1  (1)
L R 1 2L
s2  s 
L LC
Impedancja równoległego obwodu rezonansowego:
156

1 s G
Z(s)  , 1  (2)
C G 1 2C
s2  s 
C LC
Jeżeli wzmocnienie układu aktywnego jest proporcjonalne do impedancji, należy zasto-
sować równoległy obwód rezonansowy i wtedy K(s)=KZ(s). Gdy wzmocnienie układu jest
proporcjonalne do admitancji, to należy zastosować szeregowy obwód rezonansowy i przyjąć
K(s)=KY(s).
Obwody pokazane na rys. 8.12 mają transmitancję
U2 ( s )
K( s)  .
U1 (s)

I L C R I

(1) U
(2)
C G L U
C
(3)
L C
Uwej Uwyj (7)
R

Uwej R Uwyj
L
(4)
L R
Uwej R Uwyj (8)

C
Uwej Uwyj
R
(5)
C R
C
(9)
Uwej Uwyj

Uwej L Uwyj
R
(6)

L Uwyj
Uwej

Rys .8.12. Schematy układów pasywnych filtrów analogowych.


Bieguny obwodów RC i RL są rzeczywiste o podanych wartościach 
157

s 1
K ( s)   (3)
1 RC
s
RC
R 1 R
K ( s)   (4)
L R L
s
L
1 1 1
K( s)   (5)
RC 1 RC
s
RC
s R
K ( s)   (6)
R L
s
L
Bieguny układów (7) do (9) są zespolone i sprzężone, a wartość bezwzględna części
rzeczywistej jest równa . Część urojona opisana jest podanymi wyżej wzorami dla obwodów
rezonansowych.
R

2L
R s
K ( s)  (7)
L R 1
s2  s 
L LC
L 1
K ( s)  (8)
C R 1
s  s
2
L LC

s2
K( s)  (9)
R 1
s2  s 
L LC
Bieguny wszystkich obwodów są jednakowe, a ich transmitancje różnią się stopniem
wielomianu w mianowniku i „wzmocnieniem”.
Dysponując podanymi zależnościami można wybrać właściwe obwody dla projektowa-
nego filtru. I tak przykładowo, filtr dolnopasmowy, którego zera i bieguny wyznaczono w
poprzednim punkcie, ma w mianowniku wartość stałą, dwie paru biegunów zespolonych i
jeden biegun rzeczywisty. Można go zatem zbudować z dwóch obwodów rezonansowych o
konfiguracji (8) oraz obwodu RL (4) lub RC (6). Obwody (4) i (6) są z tego punktu widzenia
równoważne (na ogół wybieramy w takiej sytuacji obwód RC).
W drugim przykładzie mamy w liczniku s5 oraz w 5 par biegunów zespolonych. Filtr
można zatem zbudować z 5 obwodów szeregowych, równoległych bądź o konfiguracji (7).
Najczęściej wybieramy obwody równoległe, choć nie jest to regułą.
W analogiczny sposób wybiera się konfigurację filtrów o innych funkcjach przenosze-
nia.

8.4.3. Wyznaczanie wartości elementów obwodów


Po określeniu struktury obwodów realizujących transmitancję filtru można przystąpić
do wyznaczania wartości elementów. W tym celu należy rozwiązać równanie lub układ rów-
158

nań, w których niewiadomymi są wartości elementów. I tak, w przypadku obwodów rezonan-


sowych, których bieguny są zespolone i sprzężone mamy:
G
 obwód równoległy
2C
R
 obwód szeregowy
2L
1
2  2  obwód równoległy i szeregowy
LC
W przypadku obwodów RC i RL obowiązują zależności podane w powyższych wzo-
rach
1
 obwód RL
RC
R
 obwód RC
L
Jak widać, rozwiązania powyższych równań nie dają jednoznacznych wyników, gdyż
liczba niewiadomych jest większa od liczby równań. Konieczne jest zatem przyjęcie wartości
jednego z elementów. Można się przy tym kierować różnymi względami, np. wzmocnieniem,
pożądaną wartością obciążenia wzmacniacza, techniczną realizowalnością poszczególnych
elementów itp.
Poniżej pokażemy proste programy wspomagające projektowanie filtrów dolnopasmo-
wych i pasmowoprzepustowych. Pierwszy program wyznacza wielkości elementów dolno-
przepustowego filtru Czebyszewa o częstotliwości granicznej Fg i zafalowaniu D w paśmie
przenoszenia. Należy zauważyć, że licznik w transmitancji filtru nie ma zer, a więc filtr może
być zbudowany z układów (4), (5) i (8) pokazanych na rys. 8.12. Jeżeli rząd filtru jest
parzysty, to filtr złożony jest wyłącznie z układów (8). W przeciwnym wypadku jednym z
ogniw powinien być układ RC (5) lub RL (4). Na ogół preferowane jest używanie układów
RC. Program sprawdza parzystość rzędu filtru i wyznacza wartości elementów stosowanie do
wyniku sprawdzenia.
%ZAŁOŻENIA PROJEKTOWE
'Rząd filtru N'
N=input('N=');
'Górna częstotliwość graniczna Fg [Hz]'
Fg=input('Fg=');
'Zafalowanie w paśmie przenoszenia [dB]'
D=input('D=');
'Oporność w obwodach rezonansowych [om]'
R=input('R=');
%OBLICZENIA
W=2*pi*Fg; %Górna częstotliwość pasma przenoszenia
[z,p,k]=cheby1(N,D,W,'s') %Zera i bieguny transmitancji
s=abs(real(p));
o=abs(imag(p));
%Test parzystości
m=mod(N,2);
if m==0
M=N/2;
else
M=(N-1)/2;
end
%Wyznaczanie wartości elementów obwodów rezonansowych
159

C=zeros(1,M);
L=zeros(1,M);
for n=1:M
L(n)=R./(2*s(2*n-1)); %Wyznaczanie pojemności
C(n)=1/(L(n)*(o(2*n-1).^2+s(2*n-1).^2)); %Wyznaczanie indukcyjności
end
'Częstotliwości rezonansowe [Hz]'
f=1./(2*pi*sqrt(C.*L))
'Indukcyjności [H] obwodów rezonansowych'
L
'Pojemności [F] obwodów rezonansowych'
C
if m==1
'Oporność obwodu RC'
Rrc=input('Rrc=');
'Pojemność [F] obwodu RC'
Crc=1./(R*s(N))
end

%SPRAWDZENIE
F=1:2*Fg;
w=i*2*pi*F;
wm=size(w);
Z=zeros(M,wm(1,2));
K=ones(1,wm(1,2));
for n=1:M
Z(n,:)=1./(C(n)*w.*(R+w*L(n)+1./(w*C(n)))); %Wartości impedancji obwodów
rezonansowych
K=Z(n,:).*K; %Wyznaczanie iloczynu transmitancji
end
if m==1
K=K.*(1./(1+w*Crc*R));
end
Ka=abs(K); %Wartości bezwzględne transmitancji
'"Wzmocnienie |Uwyj|/|Iwej|'
Kamax=max(Ka)
%WYKRESY
subplot(2,1,1);plot(F,20*log10(abs(Ka/Kamax)),'k')
axis([min(F) max(F) -80 10])
xlabel('f [Hz]');ylabel('20log(|K|/Kmax)')
hold on
subplot(2,1,2);plot(F,unwrap(angle(K)),'k')
xlabel('f [Hz]');ylabel('faza [rad]')
hold on

Poniżej zamieszczono wydruk z okna Command Window zawierający wprowadzone dane


i wyniki obliczeń. Na rys. 8.13 pokazano charakterystykę amplitudową i fazową zaprojek-
towanego filtru. Funkcje te wyznaczono z transmitancji poszczególnych obwodów.
Rząd filtru N
N=7
Górna częstotliwość graniczna Fg [Hz]
Fg=20000
Zafalowanie w paśmie przenoszenia [dB]
D=3
Oporność w obwodach rezonansowych [om]
R=20
z=
Empty matrix: 0-by-1
p=
160

1.0e+005 *
-0.0354 + 1.2349i
-0.0354 - 1.2349i
-0.0991 + 0.9903i
-0.0991 - 0.9903i
-0.1432 + 0.5496i
-0.1432 - 0.5496i
-0.1589
k=
7.7503e+033
Częstotliwości rezonansowe [Hz]
f=
1.0e+004 *
1.9662 1.5840 0.9039
Indukcyjności [H] obwodów rezonansowych
L=
0.0028 0.0010 0.0007
Pojemności [F] obwodów rezonansowych
C=
1.0e-006 *
0.0232 0.1000 0.4440
Oporność obwodu RC
Rrc=100
Pojemność [F] obwodu RC
Crc =
3.1457e-006
"Wzmocnienie |Uwyj|/|Iwej|
Kamax =
1.0000

Rys. 8.13. Charakterystyka amplitudowa i fazowa filtru Czebyszewa.


Przedstawiony dalej program wyznacza wartości elementów filtru pasmowoprzepusto-
wego. Podane wyniki dotyczą filtru 5. rzędu zbudowanego z równoległych obwodów rezo-
nansowych o oporności R=1 k. Częstotliwości graniczne pasma przenoszenia wynoszą
Fd=800 Hz i Fg=1200 Hz. Dla porównania na rys. 8.14 pokazano charakterystyki filtrów rzędu
3. i 7. o tych samych parametrach.
161

%ZAŁOŻENIA PROJEKTOWE
'Rząd filtru N'
N=input('N=');
'Dolna częstotliwość graniczna Fd [Hz]'
Fd=input('Fd=');
'Górna częstotliwość graniczna Fg [Hz]'
Fg=input('Fg=');
'Oporność w obwodach rezonansowych [om]'
R=input('R=');
%OBLICZENIA
W=2*pi*[Fd Fg]; %Pasmo przenoszenia
[z,p,k]=butter(N,W,'s'); %Zera i bieguny transmitancji
s=abs(real(p));
o=abs(imag(p));
C=zeros(1,N);
L=zeros(1,N);
for n=1:N
C(n)=1/(2*R*s(2*n-1)); %Wyznaczanie pojemności
L(n)=1/(C(n)*(o(2*n-1).^2+s(2*n-1).^2)); %Wyznaczanie indukcyjności
end
'Częstotliwości rezonansowe [Hz]'
f=1./(2*pi*sqrt(C.*L))
'Indukcyjności [H]'
L
'Pojemności [F]'
C
%SPRAWDZENIE
Fc=(Fd+Fg)/2; b=Fg-Fd;
F=Fc-2*b:Fc+2*b;
w=i*2*pi*F;
wm=size(w);
Z=zeros(N,wm(1,2));
K=ones(1,wm(1,2));
for n=1:N
Z(n,:)=1./(1/R+w*C(n)+1./(w*L(n))); %Wartości impedancji równoległych obwodów
rezonansowych
K=Z(n,:).*K; %Wyznaczanie iloczynu impedancji równego
transmitancji
end
Ka=abs(K); %Wartości bezwzględne transmitancji
'"Wzmocnienie |Uwyj|/|Iwej|'
Kamax=max(Ka)
%WYKRESY
subplot(2,1,1);plot(F,20*log10(abs(Ka/Kamax)),'k')
axis([min(F) max(F) -60 10])
xlabel('f [Hz]');ylabel('20log(|K|/Kmax)')
hold on
subplot(2,1,2);plot(F,unwrap(angle(K)),'k')
xlabel('f [Hz]');ylabel('faza [rad]')

Częstotliwości rezonansowe [Hz]


f=
1.0e+003 *
1.1887 1.1062 0.9798 0.8678 0.8076
Indukcyjności [H]
L=
0.0166 0.0472 0.0663 0.0601 0.0244
Pojemności [F]
C=
1.0e-005 *
162

0.1081 0.0439 0.0398 0.0559 0.1591


"Wzmocnienie” |Uwyj|/|Iwej|
Kamax =
5.9344e+013

Rys. 8.14. Charakterystyka amplitudowa i fazowa filtru Butterwortha.


163

INDEKS INSTRUKCJI I FUNKCJI

fir1 131
A
fir2 131
abs 13 fircls 131
angle 13 fircls1 131
axis 47 firgauss 131
firls 131
B firrcos 131
fix 15
bar 44 flattopwin 126
barthannwin 126 floor 15
blackman 126 fmin 94
blackmanharris 126 fminbnd 94
bohmanwin 126 fmins 94
break 40 for 38
butter 131 format 12
freqs 132
C freqz 132
Callback 73 function 35
camlight 61 fzero 93
caxis 58
ceil 15 G
chebwin 126 gausswin 126
cheby1 131 gca 62
cheby2 131 gcf 62
clear 11 get 62
clear all 11 grid 48
close 11 guidata 75
close all 11 guide 66
colormap 57
conj 29 H
conv 137
CreateFcn 74 hamming 126
cremez 131 handles 72
cumsum 29 hann 126
hist 116
D histc 116
hold on 49
delete 11
det 24 I
diff 29
dir 10 if 33
ifft 119
E imag 13
inline 36
eleseif 33 input 17
ellip 131 intfilt 131
else 33 inv 23
end 33
eye 18 K
F kaiser 126
fft 119 L
fftshift 122
figure 48 legend 48
filter 133 lightangle 61
find 32 lighting 62
findobj 62 load 83
164

loglog 48 semilogx 48
semilogy 48
M set 50
sgolay 131
material 62
size 31
max 30
sound 85
maxflat 131 square 109
mean 30 stairs 44
mesh 56
std 30
meshgrid 64
stem 44
min 30
str2double 75
modulate 113 subplot 50
sum 29
N sur 56
nargin 36
nargout 36 T
num2str 73
text 48
nuttallwin 126
title 47
triang 126
O tripuls 109
ode 97 tukeywin 126
ones 18
open 9 U
openvar 20
uigetfile 85
P
V
parzenwin 126 var 30
plot 44 varargin 36
plot3 54
varargout 36
polar 44
view 60
poly 88
polyval 89
W
pulstran 110
wav 85
Q wavread 85
wavwrite 85
quad 96
what 11
quad8 96
which 10
while 40
R who 11
rand 19 whos 11
randn 19
real 13 X
rectpuls 109
xlabel 47
rectwin 126
remez 131
Y
reshape 43
residue 89 ylabel 47
roots 88 yulewalk 131
round 14
Z
S
zeros 18
save 10 zlabel 57
saveas 10

You might also like