Szukaj…


Wprowadzenie

Porty szeregowe są powszechnym interfejsem do komunikacji z zewnętrznymi czujnikami lub systemami wbudowanymi, takimi jak Arduinos. Współczesna komunikacja szeregowa jest często implementowana poprzez połączenia USB za pomocą adapterów szeregowych USB. MATLAB zapewnia wbudowane funkcje komunikacji szeregowej, w tym protokoły RS-232 i RS-485. Tych funkcji można używać do sprzętowych portów szeregowych lub „wirtualnych” połączeń szeregowych USB. Przykłady tutaj ilustrują komunikację szeregową w MATLAB.

Parametry

Parametr portu szeregowego co to robi
BaudRate Ustawia szybkość transmisji. Najpopularniejszym obecnie jest 57600, ale często widywane są również 4800, 9600 i 115200
InputBufferSize Liczba bajtów przechowywanych w pamięci. Matlab ma FIFO, co oznacza, że nowe bajty zostaną odrzucone. Domyślnie jest to 512 bajtów, ale bez problemu można go łatwo ustawić na 20 MB. Istnieje tylko kilka skrajnych przypadków, w których użytkownik chciałby, aby był mały
BytesAvailable Liczba bajtów oczekujących na odczyt
ValuesSent Liczba bajtów wysłanych od momentu otwarcia portu
ValuesReceived Liczba bajtów odczytanych od momentu otwarcia portu
BytesAvailableFcn Określ funkcję wywołania zwrotnego, która ma być wykonywana, gdy w buforze wejściowym dostępna jest określona liczba bajtów lub czytany jest terminator
BytesAvailableFcnCount Podaj liczbę bajtów, które muszą być dostępne w buforze wejściowym, aby wygenerować zdarzenie bytes-available w bytes-available
BytesAvailableFcnMode Określ, czy zdarzenie bytes-available w bytes-available ma być generowane po udostępnieniu określonej liczby bajtów w buforze wejściowym, czy po odczytaniu terminatora

Tworzenie portu szeregowego w systemie Mac / Linux / Windows

% Define serial port with a baud rate of 115200
rate = 115200;
if ispc
    s = serial('COM1', 'BaudRate',rate);
elseif ismac
    % Note that on OSX the serial device is uniquely enumerated. You will
    % have to look at /dev/tty.* to discover the exact signature of your
    % serial device
    s = serial('/dev/tty.usbserial-A104VFT7', 'BaudRate',rate);
elseif isunix
    s = serial('/dev/ttyusb0', 'BaudRate',rate);
end

% Set the input buffer size to 1,000,000 bytes (default: 512 bytes).
s.InputBufferSize = 1000000;    

% Open serial port    
fopen(s);

Odczyt z portu szeregowego

Zakładając, że stworzył seryjny obiekt portowy s jak w tym przykładzie, a następnie

% Read one byte
data = fread(s, 1);

% Read all the bytes, version 1
data = fread(s);

% Read all the bytes, version 2
data = fread(s, s.BytesAvailable);

% Close the serial port
fclose(s);

Zamykanie portu szeregowego, nawet jeśli zostanie utracone, usunięte lub zastąpione

Zakładając, że tworzony obiekt portu szeregowego s jak w tym przykładzie, a następnie, aby go zamknąć

fclose(s)

Czasami jednak możesz przypadkowo utracić port (np. Wyczyść, zastąpić, zmienić zakres itp.), A fclose(s) przestaną działać. Rozwiązanie jest łatwe

fclose(instrfindall)

Więcej informacji na instrfindall() .

Zapis do portu szeregowego

Zakładając, że stworzył seryjny obiekt portowy s jak w tym przykładzie, a następnie

% Write one byte
fwrite(s, 255);

% Write one 16-bit signed integer
fwrite(s, 32767, 'int16');

% Write an array of unsigned 8-bit integers
fwrite(s,[48 49 50],'uchar');

% Close the serial port
fclose(s);

Wybór trybu komunikacji

Matlab obsługuje synchroniczną i asynchroniczną komunikację z portem szeregowym. Ważne jest, aby wybrać odpowiedni tryb komunikacji. Wybór zależy od:

  • jak zachowuje się instrument, z którym się komunikujesz.
  • jakie inne funkcje Twój główny program (lub GUI) będzie musiał wykonać oprócz zarządzania portem szeregowym.

Zdefiniuję 3 różne przypadki do zilustrowania, od najprostszych do najbardziej wymagających. Dla 3 przykładów instrumentem, z którym się łączę, jest płytka drukowana z inklinometrem, która może pracować w 3 trybach, które opiszę poniżej.


Tryb 1: Synchroniczny (Master / Slave)

Ten tryb jest najprostszy. Odpowiada to przypadkowi, gdy komputer PC jest urządzeniem nadrzędnym, a instrument jest urządzeniem podrzędnym . Instrument sam nie wysyła niczego do portu szeregowego, odpowiada tylko po zadaniu pytania / polecenia przez Master (komputer, twój program). Na przykład:

  • Komputer wysyła polecenie: „Daj mi teraz pomiar”
  • Urządzenie odbiera polecenie, wykonuje pomiar, a następnie przesyła wartość pomiaru do linii szeregowej: „Wartość inklinometru wynosi XXX”.

LUB

  • Komputer wysyła polecenie: „Zmień tryb X na tryb Y”
  • Urządzenie odbiera polecenie, wykonuje je, a następnie przesyła komunikat potwierdzający z powrotem do linii szeregowej: „ Polecenie wykonane ” (lub „ Polecenie NIE wykonane ”). Jest to powszechnie nazywane odpowiedzią ACK / NACK (dla „Acknowledge (d)” / „NOT Acknowledged”).

Podsumowanie: w tym trybie urządzenie ( Slave ) wysyła dane do linii szeregowej natychmiast po otrzymaniu zapytania od komputera PC ( Master )

Ilustracja synchroniczna


Tryb 2: asynchroniczny

Załóżmy teraz, że uruchomiłem swój instrument, ale to coś więcej niż głupi czujnik. Stale monitoruje swoje nachylenie i dopóki jest pionowe (w granicach tolerancji, powiedzmy +/- 15 stopni), milczy. Jeśli urządzenie zostanie przechylone o więcej niż 15 stopni i zbliży się do poziomu, wysyła komunikat alarmowy do linii szeregowej, po czym natychmiast następuje odczyt nachylenia. Dopóki nachylenie jest powyżej progu, wysyła odczyt nachylenia co 5 sekund.

Jeśli twój program główny (lub GUI) ciągle „czeka” na wiadomość przychodzącą na linię szeregową, może to zrobić dobrze ... ale w międzyczasie nie może nic zrobić. Jeśli głównym programem jest GUI, bardzo frustrujące jest posiadanie GUI pozornie „zamrożonego”, ponieważ nie przyjmuje on żadnych danych wejściowych od użytkownika. Zasadniczo stał się Niewolnikiem, a instrumentem jest Mistrz . O ile nie masz wymyślnego sposobu kontrolowania GUI z poziomu instrumentu, należy tego unikać. Na szczęście tryb komunikacji asynchronicznej umożliwia:

  • zdefiniuj oddzielną funkcję, która mówi Twojemu programowi, co ma robić po otrzymaniu wiadomości
  • trzymaj tę funkcję w rogu, będzie ona wywoływana i wykonywana tylko, gdy wiadomość dotrze do linii szeregowej. Przez resztę czasu GUI może wykonać dowolny kod, który musi uruchomić.

Podsumowanie: W tym trybie przyrząd może wysyłać wiadomości do linii szeregowej w dowolnym momencie (ale niekoniecznie przez cały czas). Komputer nie czeka na stałe na przetworzenie komunikatu. Dozwolone jest uruchamianie dowolnego innego kodu. Dopiero gdy wiadomość dotrze, aktywuje funkcję, która następnie ją przeczyta i przetworzy.

wprowadź opis zdjęcia tutaj


Tryb 3: Streaming (w czasie rzeczywistym )

Teraz uwolnijmy pełną moc mojego instrumentu. Ustawiam go w tryb, w którym będzie stale wysyłać pomiary do linii szeregowej. Mój program chce odbierać te pakiety i wyświetlać je na krzywej lub wyświetlaczu cyfrowym. Jeśli wysyła wartość co 5s jak wyżej, nie ma problemu, zachowaj powyższy tryb. Ale mój instrument z pełną mocą wysyła punkt danych do linii szeregowej przy 1000 Hz, tj. Wysyła nową wartość co milisekundę. Jeśli pozostanę w trybie asynchronicznym opisanym powyżej, istnieje wysokie ryzyko (faktycznie gwarantowana pewność), że specjalna funkcja, którą zdefiniowaliśmy do przetwarzania każdego nowego pakietu, zajmie więcej niż 1 ms (jeśli chcesz wykreślić lub wyświetlić wartość, funkcje graficzne są dość wolne, nawet nie biorąc pod uwagę filtrowania lub FFT'owania sygnału). Oznacza to, że funkcja zacznie się uruchamiać, ale zanim się skończy, nadejdzie nowy pakiet i ponownie uruchomi funkcję. Druga funkcja jest umieszczana w kolejce do wykonania i uruchomi się dopiero po zakończeniu pierwszej ... ale do tego czasu przybyło kilka nowych pakietów i każda umieściła funkcję do wykonania w kolejce. Możesz szybko przewidzieć wynik: do czasu, gdy planuję piąty punkt, mam już setki czekających na wykreślenie również ... gui zwalnia, ostatecznie zawiesza się, stos rośnie, bufory się zapełniają, aż coś się podda. W końcu masz całkowicie zamrożony program lub po prostu zawieszony.

Aby temu zaradzić, jeszcze bardziej rozłączymy łącze synchronizacji między komputerem a instrumentem. Umożliwimy instrumentowi wysyłanie danych we własnym tempie, bez natychmiastowego uruchamiania funkcji przy każdym nadejściu pakietu. Bufor portu szeregowego po prostu gromadzi odebrane pakiety. Komputer będzie zbierał dane w buforze tylko w tempie, w którym może zarządzać (regularny interwał, ustawiany po stronie komputera), coś z tym zrobić (podczas gdy bufor jest napełniany przez urządzenie), a następnie zbiera nową partię dane z bufora ... i tak dalej.

Podsumowanie: W tym trybie przyrząd wysyła dane w sposób ciągły, które są gromadzone przez bufor portu szeregowego. W regularnych odstępach czasu komputer PC zbiera dane z bufora i coś z nim robi. Nie ma twardego połączenia synchronizacji między komputerem a instrumentem. Obaj wykonują swoje zadania według własnego harmonogramu.

wprowadź opis zdjęcia tutaj


Automatyczne przetwarzanie danych otrzymanych z portu szeregowego

Niektóre urządzenia podłączone przez port szeregowy przesyłają dane do programu ze stałą szybkością (przesyłanie strumieniowe danych) lub przesyłają dane w nieprzewidzianych odstępach czasu. Port szeregowy można skonfigurować w taki sposób, aby automatycznie uruchamiał funkcję do obsługi danych za każdym razem, gdy się pojawi. Nazywa się to „funkcją wywołania zwrotnego” dla obiektu portu szeregowego.

Istnieją dwie właściwości portu szeregowego, które należy ustawić, aby można było korzystać z tej funkcji: nazwa funkcji, która ma być BytesAvailableFcn zwrotna ( BytesAvailableFcn ), oraz warunek, który powinien wyzwalać wykonanie funkcji zwrotnej ( BytesAvailableFcnMode ).

Istnieją dwa sposoby uruchomienia funkcji oddzwaniania:

  1. Gdy pewna liczba bajtów została odebrana przez port szeregowy (zwykle używany do danych binarnych)
  2. Po odebraniu określonego znaku przez port szeregowy (zwykle używany do danych tekstowych lub ASCII)

Funkcje zwrotne mają dwa wymagane argumenty wejściowe, zwane obj i event . obj to port szeregowy. Na przykład, jeśli chcesz wydrukować dane otrzymane z portu szeregowego, zdefiniuj funkcję drukowania danych o nazwie newdata :

function newdata(obj,event)
    [d,c] = fread(obj);  % get the data from the serial port
    % Note: for ASCII data, use fscanf(obj) to return characters instead of binary values
    fprintf(1,'Received %d bytes\n',c);
    disp(d)
end

Na przykład, aby wykonać funkcję newdata za każdym razem, gdy odbierane są 64 bajty danych, skonfiguruj port szeregowy w następujący sposób:

s = serial(port_name);
s.BytesAvailableFcnMode = 'byte';
s.BytesAvailableFcnCount = 64;
s.BytesAvailableFcn = @newdata;

W przypadku danych tekstowych lub ASCII dane są zwykle dzielone na linie ze „znakiem terminatora”, podobnie jak tekst na stronie. Aby wykonać funkcję newdata każdym newdata znaku powrotu karetki, skonfiguruj port szeregowy w następujący sposób:

s = serial(port_name);
s.BytesAvailableFcnMode = 'terminator';
s.Terminator = 'CR';  % the carriage return, ASCII code 13
s.BytesAvailableFcn = @newdata;


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow