Zoeken…


Invoering

Seriële poorten zijn een gemeenschappelijke interface voor communicatie met externe sensoren of ingebedde systemen zoals Arduinos. Moderne seriële communicatie wordt vaak geïmplementeerd via USB-verbindingen met USB-seriële adapters. MATLAB biedt ingebouwde functies voor seriële communicatie, inclusief RS-232- en RS-485-protocollen. Deze functies kunnen worden gebruikt voor hardware-seriële poorten of "virtuele" USB-seriële verbindingen. De voorbeelden hier illustreren seriële communicatie in MATLAB.

parameters

Seriële poort parameter wat het doet
BaudRate Stelt de baudrate in. De meest voorkomende vandaag is 57600, maar 4800, 9600 en 115200 worden ook vaak gezien
InputBufferSize Het aantal bytes dat in het geheugen wordt bewaard. Matlab heeft een FIFO, wat betekent dat nieuwe bytes worden verwijderd. De standaardwaarde is 512 bytes, maar deze kan eenvoudig zonder probleem worden ingesteld op 20 MB. Er zijn slechts enkele randgevallen waarbij de gebruiker wil dat dit klein is
BytesAvailable Het aantal bytes dat wacht om te worden gelezen
ValuesSent Het aantal verzonden bytes sinds de poort is geopend
ValuesReceived Het aantal gelezen bytes sinds de poort is geopend
BytesAvailableFcn Geef de callback-functie op die moet worden uitgevoerd wanneer een gespecificeerd aantal bytes beschikbaar is in de invoerbuffer of wanneer een terminator wordt gelezen
BytesAvailableFcnCount Geef het aantal bytes op dat beschikbaar moet zijn in de invoerbuffer om een bytes-available gebeurtenis te genereren
BytesAvailableFcnMode Geef op of de bytes-available gebeurtenis wordt gegenereerd nadat een gespecificeerd aantal bytes beschikbaar is in de invoerbuffer of nadat een terminator is gelezen

Een seriële poort maken op 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);

Lezen van de seriële poort

Ervan uitgaande dat u het seriële poortobject s zoals in dit voorbeeld hebt gemaakt

% 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);

Een seriële poort sluiten, zelfs als deze verloren, verwijderd of overschreven is

Ervan uitgaande dat u het seriële poortobject s zoals in dit voorbeeld, om het vervolgens te sluiten

fclose(s)

Soms kunt u echter per ongeluk de poort verliezen (bijv. Wissen, overschrijven, bereik wijzigen, enz ...) en fclose(s) werken niet meer. De oplossing is eenvoudig

fclose(instrfindall)

Meer info op instrfindall() .

Schrijven naar de seriële poort

Ervan uitgaande dat u het seriële poortobject s zoals in dit voorbeeld hebt gemaakt

% 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);

Uw communicatiemodus kiezen

Matlab ondersteunt synchrone en asynchrone communicatie met een seriële poort. Het is belangrijk om de juiste communicatiemodus te kiezen. De keuze hangt af van:

  • hoe het instrument waarmee u communiceert zich gedraagt.
  • welke andere functies uw hoofdprogramma (of GUI) moet doen, afgezien van het beheer van de seriële poort.

Ik zal 3 verschillende gevallen definiëren om te illustreren, van de eenvoudigste tot de meest veeleisende. Voor de 3 voorbeelden is het instrument waarmee ik verbinding maak een printplaat met een inclinometer, die kan werken in de 3 modi die ik hieronder zal beschrijven.


Modus 1: Synchroon (Master / Slave)

Deze modus is de eenvoudigste. Het komt overeen met het geval waarin de pc de master is en het instrument de slave is . Het instrument verzendt zelf niets naar de seriële poort, het antwoordt alleen een antwoord na een vraag / opdracht van de master (de pc, uw programma). Bijvoorbeeld:

  • De pc verzendt een opdracht: "Geef me nu een meting"
  • Het instrument ontvangt de opdracht, voert de meting uit en stuurt vervolgens de meetwaarde terug naar de seriële lijn: "De hellingsmeterwaarde is XXX".

OF

  • De pc verzendt een opdracht: "Wijzigen van modus X naar modus Y"
  • Het instrument ontvangt de opdracht, voert deze uit en stuurt vervolgens een bevestigingsbericht terug naar de seriële regel: " Commando uitgevoerd " (of " Commando NIET uitgevoerd "). Dit wordt gewoonlijk een ACK / NACK-antwoord genoemd (voor "Bevestigen (d)" / "NIET Erkend").

Samenvatting: in deze modus verzendt het instrument (de slave ) alleen gegevens naar de seriële lijn onmiddellijk nadat hierom door de pc (de master ) is gevraagd

Synchrone illustratie


Modus 2: asynchroon

Stel nu dat ik mijn instrument ben gestart, maar het is meer dan alleen een domme sensor. Het bewaakt constant zijn eigen neiging en zolang het verticaal is (binnen een tolerantie, laten we zeggen +/- 15 graden), blijft het stil. Als het apparaat meer dan 15 graden wordt gekanteld en bijna horizontaal komt, stuurt het een alarmbericht naar de seriële lijn, onmiddellijk gevolgd door een meting van de helling. Zolang de helling boven de drempel ligt, blijft deze elke 5 seconden een hellingmeting verzenden.

Als uw hoofdprogramma (of GUI) constant "wacht" op berichten die op de seriële lijn binnenkomen, kan het dat goed ... maar in de tussentijd kan het niets anders doen. Als het hoofdprogramma een GUI is, is het erg frustrerend om een GUI te hebben die 'bevroren' lijkt te zijn, omdat deze geen invoer van de gebruiker accepteert. In wezen werd het de slaaf en het instrument is de meester . Tenzij u een chique manier heeft om uw GUI vanaf het instrument te besturen, is dit iets om te vermijden. Gelukkig kunt u met de asynchrone communicatiemodus:

  • definieer een aparte functie die uw programma vertelt wat te doen wanneer een bericht wordt ontvangen
  • bewaar deze functie in een hoek, deze wordt alleen aangeroepen en uitgevoerd wanneer een bericht op de seriële lijn binnenkomt . De rest van de tijd kan de GUI elke andere code uitvoeren die het moet uitvoeren.

Samenvatting: in deze modus kan het instrument op elk moment een bericht naar de seriële lijn sturen (maar niet noodzakelijkerwijs altijd ). De pc wacht niet permanent tot een bericht is verwerkt. Het is toegestaan om elke andere code uit te voeren. Alleen wanneer een bericht binnenkomt, wordt een functie geactiveerd die dit bericht vervolgens leest en verwerkt.

voer hier de afbeeldingsbeschrijving in


Modus 3: Streaming ( realtime )

Laten we nu de volle kracht van mijn instrument ontketenen. Ik heb het in een modus gezet waar het constant metingen naar de seriële lijn stuurt. Mijn programma wil deze pakketten ontvangen en weergeven op een curve of een digitaal display. Als het alleen om de 5 seconden een waarde verzendt zoals hierboven, geen probleem, houd de bovenstaande modus aan. Maar mijn instrument op volle kracht zendt een datapunt naar de seriële lijn op 1000Hz, dat wil zeggen het stuurt elke milliseconde een nieuwe waarde. Als ik in de hierboven beschreven asynchrone modus blijf, is er een groot risico (eigenlijk een gegarandeerde zekerheid) dat de speciale functie die we hebben gedefinieerd om elk nieuw pakket te verwerken meer dan 1 ms nodig heeft om uit te voeren (als u de waarde wilt plotten of weergeven, grafische functies zijn vrij traag, zelfs niet gezien het filteren of FFT'en van het signaal). Dit betekent dat de functie wordt uitgevoerd, maar voordat deze wordt voltooid, arriveert een nieuw pakket dat de functie opnieuw activeert. De tweede functie wordt voor uitvoering in een wachtrij geplaatst en begint pas wanneer de eerste is voltooid ... maar tegen die tijd zijn er een paar nieuwe pakketten aangekomen en elk heeft een functie geplaatst om in de wachtrij te worden uitgevoerd. Je kunt het resultaat snel voorspellen: tegen de tijd dat ik de 5e punten beraam, heb ik er al honderden die wachten om uitgezet te worden ... de gui vertraagt, uiteindelijk bevriest, de stapel groeit, de buffers worden vol totdat er iets geeft. Uiteindelijk blijft er een volledig bevroren programma over of gewoon een gecrasht programma.

Om dit te verhelpen, zullen we de synchronisatielink tussen de pc en het instrument nog verder verbreken. We laten het instrument gegevens in zijn eigen tempo verzenden, zonder bij elke aankomst van een pakket onmiddellijk een functie te activeren. De seriële poortbuffer verzamelt alleen de ontvangen pakketten. De pc verzamelt alleen gegevens in de buffer op een tempo dat het kan beheren (een regelmatig interval, ingesteld op de pc-zijde), doet er iets mee (terwijl de buffer door het instrument wordt bijgevuld) en verzamelt vervolgens een nieuwe partij gegevens uit de buffer ... enzovoort.

Samenvatting: in deze modus verzendt het instrument continu gegevens, die worden verzameld door de seriële poortbuffer. Met regelmatige tussenpozen verzamelt de pc gegevens uit de buffer en doet er iets mee. Er is geen harde synchronisatielink tussen de pc en het instrument. Beide voeren hun taken uit volgens hun eigen timing.

voer hier de afbeeldingsbeschrijving in


Automatisch verwerken van gegevens ontvangen van een seriële poort

Sommige apparaten die via een seriële poort zijn aangesloten, verzenden gegevens naar uw programma met een constante snelheid (streaming gegevens) of verzenden gegevens met onvoorspelbare intervallen. U kunt de seriële poort configureren om een functie automatisch uit te voeren om gegevens te verwerken wanneer deze binnenkomen. Dit wordt de "callback-functie" genoemd voor het seriële poortobject.

Er zijn twee eigenschappen van de seriële poort die moeten worden ingesteld om deze functie te gebruiken: de naam van de gewenste functie voor de callback ( BytesAvailableFcn ) en de voorwaarde die het uitvoeren van de callback-functie ( BytesAvailableFcnMode ) moet activeren.

Er zijn twee manieren om een callback-functie te activeren:

  1. Wanneer een bepaald aantal bytes is ontvangen op de seriële poort (meestal gebruikt voor binaire gegevens)
  2. Wanneer een bepaald teken wordt ontvangen op de seriële poort (meestal gebruikt voor tekst- of ASCII-gegevens)

Callback-functies hebben twee vereiste invoerargumenten, genaamd obj en event . obj is de seriële poort. Bijvoorbeeld, als u de ontvangen van de seriële poort gegevens af te drukken, definieert u een functie voor het afdrukken van de gegevens genoemd 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

Als u bijvoorbeeld de functie newdata wilt uitvoeren wanneer 64 bytes aan gegevens worden ontvangen, configureert u de seriële poort als volgt:

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

Bij tekst- of ASCII-gegevens worden de gegevens meestal verdeeld in regels met een "terminator-teken", net als tekst op een pagina. Om de functie newdata te voeren telkens wanneer het teken voor de return van de wagen wordt ontvangen, configureert u de seriële poort als volgt:

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow