MATLAB Language
Verwenden Sie serielle Anschlüsse
Suche…
Einführung
Serielle Ports sind eine gemeinsame Schnittstelle für die Kommunikation mit externen Sensoren oder eingebetteten Systemen wie Arduinos. Moderne serielle Kommunikation wird häufig über USB-Verbindungen mit seriellen USB-Adaptern implementiert. MATLAB bietet integrierte Funktionen für die serielle Kommunikation, einschließlich der Protokolle RS-232 und RS-485. Diese Funktionen können für serielle Hardwareanschlüsse oder "virtuelle" USB-serielle Verbindungen verwendet werden. Die Beispiele hier veranschaulichen die serielle Kommunikation in MATLAB.
Parameter
Parameter für den seriellen Anschluss | Was es macht |
---|---|
BaudRate | Stellt die Baudrate ein. Die häufigste heute ist 57600, aber häufig werden auch 4800, 9600 und 115200 gesehen |
InputBufferSize | Die Anzahl der im Speicher befindlichen Bytes. Matlab hat einen FIFO, was bedeutet, dass neue Bytes verworfen werden. Der Standardwert ist 512 Byte, kann jedoch problemlos ohne Probleme auf 20 MB gesetzt werden. Es gibt nur wenige Randfälle, in denen der Benutzer möchte, dass dies klein ist |
BytesAvailable | Die Anzahl der zu lesenden Bytes |
ValuesSent | Die Anzahl der seit dem Öffnen des Ports gesendeten Bytes |
ValuesReceived | Die Anzahl der seit dem Öffnen des Ports gelesenen Bytes |
BytesAvailableFcn | Geben Sie die Callback-Funktion an, die ausgeführt werden soll, wenn eine bestimmte Anzahl von Bytes im Eingabepuffer verfügbar ist oder ein Abschlusszeichen gelesen wird |
BytesAvailableFcnCount | Geben Sie die Anzahl der Bytes an, die im Eingangspuffer verfügbar sein müssen, um ein Ereignis in bytes-available zu erzeugen |
BytesAvailableFcnMode | Geben Sie an, ob das Ereignis bytes-available generiert wird, nachdem eine bestimmte Anzahl von Bytes im Eingabepuffer verfügbar ist oder nachdem ein Abschlusszeichen gelesen wurde |
Erstellen einer seriellen Schnittstelle unter 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);
Lesen von der seriellen Schnittstelle
Vorausgesetzt , dass Sie den seriellen Port - Objekt erstellt s
wie in diesem Beispiel, dann
% 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);
Schließen einer seriellen Schnittstelle, auch wenn sie verloren geht, gelöscht oder überschrieben wird
Vorausgesetzt , dass Sie den seriellen Port - Objekt erstellt s
wie in diesem Beispiel, dann um es zu schließen
fclose(s)
Manchmal können Sie jedoch versehentlich den Port verlieren (z. B. löschen, überschreiben, Bereich ändern usw.), und fclose(s)
funktionieren nicht mehr. Die Lösung ist einfach
fclose(instrfindall)
Mehr Infos unter instrfindall()
.
Schreiben an die serielle Schnittstelle
Vorausgesetzt , dass Sie den seriellen Port - Objekt erstellt s
wie in diesem Beispiel, dann
% 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);
Wählen Sie Ihren Kommunikationsmodus
Matlab unterstützt die synchrone und asynchrone Kommunikation mit einer seriellen Schnittstelle. Es ist wichtig, den richtigen Kommunikationsmodus zu wählen. Die Wahl hängt ab von:
- wie sich das Instrument, mit dem Sie kommunizieren, verhält.
- Welche anderen Funktionen muss Ihr Hauptprogramm (oder Ihre GUI) neben der Verwaltung der seriellen Schnittstelle haben?
Ich werde drei verschiedene Fälle definieren, von der einfachsten bis zur anspruchsvollsten. Bei den drei Beispielen ist das Instrument, an das ich mich anschließe, eine Platine mit einem Neigungsmesser, die in den drei Modi arbeiten kann, die ich unten beschreibe.
Modus 1: Synchron (Master / Slave)
Dieser Modus ist der einfachste. Dies entspricht dem Fall, in dem der PC der Master und das Instrument der Slave ist . Das Gerät hat nichts an dem seriell Port auf seine eigenen senden, antwortet er nur eine Antwort nach einer Frage / Befehl vom Master gefragt zu werden (der PC, Ihr Programm). Zum Beispiel:
- Der PC sendet einen Befehl: "Gib mir jetzt eine Messung"
- Das Gerät empfängt den Befehl, nimmt die Messung vor und sendet den Messwert an die serielle Leitung zurück: "Der Neigungsmesserwert ist XXX".
ODER
- Der PC sendet einen Befehl: "Vom Modus X zum Modus Y wechseln"
- Das Instrument empfängt den Befehl, führt ihn aus und sendet dann eine Bestätigungsnachricht an die serielle Leitung zurück: " Befehl ausgeführt " (oder " Befehl NICHT ausgeführt "). Dies wird allgemein als ACK / NACK-Antwort bezeichnet (für "Bestätigen (d)" / "NICHT bestätigt").
Zusammenfassung: In diesem Modus ist das Gerät (die Slave) nur Daten an die seriellen Schnittstelle sendet sofort nach dem vom PC (der Meister) gefragt wurde,
Modus 2: Asynchron
Nehmen wir an, ich habe mein Instrument gestartet, aber es ist mehr als nur ein dummer Sensor. Es überwacht ständig seine eigene Neigung und solange es vertikal ist (innerhalb einer Toleranz, etwa +/- 15 Grad), bleibt es stumm. Wenn das Gerät um mehr als 15 Grad geneigt ist und sich der Horizontalen annähert, sendet es eine Alarmmeldung an die serielle Leitung, unmittelbar gefolgt von einem Ablesen der Neigung. Solange die Neigung über der Schwelle liegt, sendet sie weiterhin alle 5 Sekunden eine Neigungsanzeige.
Wenn Ihr Hauptprogramm (oder Ihre grafische Benutzeroberfläche) ständig auf Nachrichten wartet, die auf der seriellen Leitung ankommen, kann es das gut ... aber es kann in der Zwischenzeit nichts anderes tun. Wenn das Hauptprogramm eine grafische Benutzeroberfläche ist, ist es äußerst frustrierend, wenn eine grafische Benutzeroberfläche scheinbar "eingefroren" ist, da sie keine Eingaben des Benutzers akzeptiert. Im Wesentlichen wurde es der Slave und das Instrument ist der Master . Wenn Sie nicht die Möglichkeit haben, Ihre GUI vom Instrument aus zu steuern, sollten Sie dies vermeiden. Glücklicherweise ermöglicht Ihnen der asynchrone Kommunikationsmodus:
- Definieren Sie eine separate Funktion, die Ihrem Programm mitteilt, was zu tun ist, wenn eine Nachricht empfangen wird
- Bewahren Sie diese Funktion in einer Ecke auf, wird sie nur aufgerufen und ausgeführt, wenn eine Nachricht auf der seriellen Leitung eingeht . Die restliche Zeit kann die GUI jeden anderen Code ausführen, den sie ausführen muss.
Zusammenfassung: In diesem Modus kann das Gerät Nachricht an die serielle Schnittstelle jederzeit senden (aber nicht unbedingt die ganze Zeit). Der PC wartet nicht permanent für eine Nachricht zu verarbeiten. Es ist erlaubt, anderen Code auszuführen. Erst beim Eintreffen einer Nachricht wird eine Funktion aktiviert, die diese Nachricht liest und verarbeitet.
Modus 3: Streaming ( Echtzeit )
Lassen Sie uns jetzt die volle Kraft meines Instruments entfesseln. Ich habe es in einen Modus versetzt, in dem ständig Messungen an die serielle Leitung gesendet werden. Mein Programm möchte diese Pakete empfangen und auf einer Kurve oder einer digitalen Anzeige anzeigen. Wenn nur wie oben alle 5 Sekunden ein Wert gesendet wird, ist das kein Problem. Behalten Sie den obigen Modus bei. Mein Instrument sendet bei Full Whack jedoch einen Datenpunkt bei 1000 Hz an die serielle Leitung, dh es sendet jede neue Millisekunde einen neuen Wert. Wenn ich im oben beschriebenen asynchronen Modus bleibe, besteht ein hohes Risiko (tatsächlich eine garantierte Sicherheit), dass die spezielle Funktion, die wir für die Verarbeitung jedes neuen Pakets definiert haben, mehr als 1 ms für die Ausführung benötigt (wenn Sie den Wert plotten oder anzeigen möchten, Grafikfunktionen sind ziemlich langsam, nicht einmal in Anbetracht der Filterung oder der FFT des Signals). Dies bedeutet, dass die Funktion ausgeführt wird, aber bevor sie beendet ist, wird ein neues Paket eintreffen und die Funktion erneut auslösen. Die zweite Funktion wird zur Ausführung in eine Warteschlange gestellt. Sie wird erst gestartet, wenn die erste Funktion fertiggestellt ist. Zu diesem Zeitpunkt sind jedoch einige neue Pakete angekommen, die jeweils eine Funktion in der Warteschlange enthalten. Sie können das Ergebnis schnell vorhersehen: Wenn ich die fünften Punkte geplottet habe, warten bereits Hunderte darauf, geplottet zu werden. Das Gui wird langsamer, friert schließlich ein, der Stapel wächst, die Puffer füllen sich, bis sich etwas ergibt. Möglicherweise bleibt Ihnen ein vollständig eingefrorenes oder einfach ein abgestürztes Programm.
Um dies zu überwinden, werden wir die Synchronisationsverbindung zwischen dem PC und dem Gerät noch weiter trennen. Das Gerät sendet Daten in seinem eigenen Tempo, ohne dass bei jeder Paketankunft sofort eine Funktion ausgelöst wird. Der Puffer des seriellen Ports sammelt nur die empfangenen Pakete. Der PC sammelt Daten im Puffer nur in einem Tempo, das er verwalten kann (ein regelmäßiges Intervall, das auf der PC-Seite eingerichtet wird), etwas damit zu tun (während der Puffer vom Instrument wieder aufgefüllt wird), und dann eine neue Charge von Daten aus dem Puffer ... und so weiter.
Zusammenfassung: In diesem Modus sendet das Gerät kontinuierlich Daten, die vom Puffer der seriellen Schnittstelle erfasst werden. In regelmäßigen Abständen sammelt der PC Daten aus dem Puffer und tut etwas damit. Es besteht keine feste Synchronisationsverbindung zwischen dem PC und dem Instrument. Beide führen ihre Aufgaben zu ihrem eigenen Zeitpunkt aus.
Daten, die von einem seriellen Port empfangen werden, werden automatisch verarbeitet
Einige Geräte, die über einen seriellen Anschluss angeschlossen sind, senden Daten mit konstanter Geschwindigkeit (Streaming-Daten) an Ihr Programm oder senden Daten in unvorhersehbaren Intervallen. Sie können den seriellen Anschluss so konfigurieren, dass eine Funktion zur Verarbeitung von Daten automatisch ausgeführt wird, sobald sie ankommt. Dies wird als "Rückruffunktion" für das Objekt der seriellen Schnittstelle bezeichnet.
Für die Verwendung dieser Funktion müssen zwei Eigenschaften des seriellen Anschlusses festgelegt werden: der Name der gewünschten Funktion für den Rückruf ( BytesAvailableFcn
) und die Bedingung, die die Ausführung der Rückruffunktion ( BytesAvailableFcnMode
) auslösen soll.
Es gibt zwei Möglichkeiten, eine Callback-Funktion auszulösen:
- Wenn eine bestimmte Anzahl von Bytes an der seriellen Schnittstelle empfangen wurde (normalerweise für binäre Daten verwendet)
- Wenn ein bestimmtes Zeichen an der seriellen Schnittstelle empfangen wird (normalerweise für Text- oder ASCII-Daten verwendet)
Callback-Funktionen haben zwei erforderliche Eingabeargumente, genannt obj
und event
. obj
ist die serielle Schnittstelle. Wenn Sie beispielsweise die von der seriellen Schnittstelle empfangenen Daten drucken möchten, definieren Sie eine Funktion zum Drucken der Daten mit dem Namen 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
Um beispielsweise die newdata
auszuführen, wenn 64 Datenbytes empfangen werden, konfigurieren Sie den seriellen Anschluss folgendermaßen:
s = serial(port_name);
s.BytesAvailableFcnMode = 'byte';
s.BytesAvailableFcnCount = 64;
s.BytesAvailableFcn = @newdata;
Bei Text- oder ASCII-Daten werden die Daten in der Regel in Zeilen mit einem "Abschlusszeichen" unterteilt, genau wie Text auf einer Seite. Um die newdata
auszuführen, wenn das Wagenrücklaufzeichen empfangen wird, konfigurieren Sie den seriellen Anschluss folgendermaßen:
s = serial(port_name);
s.BytesAvailableFcnMode = 'terminator';
s.Terminator = 'CR'; % the carriage return, ASCII code 13
s.BytesAvailableFcn = @newdata;