Seriële link#
Invoering#
De klasse serial_link maakt het mogelijk om een stroom onbewerkte bytes tussen robots te verzenden. Deze klasse is ontworpen voor robot-naar-robotcommunicatie, waarbij zowel de verzendende als de ontvangende robot de inhoud van de datastroom begrijpen.
Elke keer dat send wordt gebruikt, worden gegevens toegevoegd aan de wachtrij van de gekoppelde EXP Brain. De wachtrij wordt gelezen volgens het first-in, first-out (FIFO) principe. Als er meerdere berichten worden verzonden voordat de andere EXP Brain ze ontvangt, worden ze één voor één opgeslagen en geretourneerd in de volgorde waarin ze zijn verzonden. Omdat berichten in de wachtrij kunnen worden geplaatst, kan het herhaaldelijk verzenden van dezelfde status in elke lus een opstopping veroorzaken; voor tijdskritieke logica is het raadzaam alleen te verzenden wanneer waarden veranderen.
Belangrijk: Beide robots moeten tegelijkertijd projecten uitvoeren die gebruikmaken van serial_link , anders worden er geen gegevens verzonden/ontvangen.
Klasseconstructors#
serial_link(
int32_t index,
const char *name,
linkType type,
bool isWired = false );
Klasse-destructor#
Vernietigt het serial_link object en geeft de bijbehorende resources vrij.
~serial_link();
Parameters#
Parameter |
Type |
Beschrijving |
|---|---|---|
|
|
De slimme poort waarmee de berichtverbinding is verbonden, wordt weergegeven als |
|
|
De naam van deze link. Het is aan te raden dat deze unieke tekenreeks lang genoeg is, zodat Vexos er een unieke ID mee kan genereren. Een slechte linknaam zou iets generieks zijn, zoals “vexlink”, omdat deze mogelijk al door een ander team wordt gebruikt. |
|
|
Het type verbinding, ofwel
|
|
|
Of het serial_link-object bedraad is (standaard
|
Notities#
VEXlink ondersteunt zowel draadloze als bekabelde communicatie. Voor bekabelde verbindingen wordt een aangepaste slimme kabel aanbevolen om problemen met de stroomtoevoer te voorkomen.
Voor draadloze communicatie heeft elke robot een V5 Robot Radio nodig die is aangesloten op een Smart Port.
De VEXlink-radio kan samen met de VEXnet-radio van een EXP-controller worden gebruikt. Deze moet worden aangesloten op de Smart Port met het hoogste nummer om conflicten te voorkomen.
Om een VEXlink te creëren, moeten beide EXP Brains verbonden zijn met een V5 Robot Radio.
Voorbeeld#
Code voor Robot 1
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWiredCode voor Robot 2
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
Lidfuncties#
De klasse serial_link bevat de volgende lidfuncties:
isLinked— Controleert of de EXP Brains gekoppeld zijn en communiceren via deze link.send— Verstuurt een bericht naar het gekoppelde brein.receive— Wacht op het volgende binnenkomende bericht en retourneert dit.received— Registreert een functie die wordt aangeroepen wanneer een nieuw bericht wordt ontvangen.
Voordat er lidfuncties van serial_link worden aangeroepen, moet er een instantie van serial_link worden aangemaakt, zoals hieronder weergegeven:
Code voor Robot 1
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWiredCode voor Robot 2
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
isLinked#
Geeft aan of de EXP Brains op een seriële link met elkaar gekoppeld zijn.
Available Functionsbool isLinked();
Deze functie heeft geen parameters.
Return ValuesGeeft een Booleaanse waarde terug die aangeeft of de EXP Brains met elkaar verbonden zijn:
true— The two EXP Brains are paired and communicating on this link.false— The two EXP Brains are not paired on this link.
Het is goede gewoonte om aan het begin van een project altijd te controleren of de EXP Brains correct zijn gekoppeld voordat er verdere code wordt uitgevoerd.
Code voor Robot 1
// Create the link serial_link link(PORT1, "VEXRoboticsLink123456789", linkType::manager, true); // Do not run code UNTIL the Brains are linked while (!link.isLinked()) { wait(0.1, seconds); } Brain.Screen.print("Robot 1 - Manager"); Brain.Screen.newLine(); Brain.Screen.print("Sending message..."); // Message to send const char* message = "Hello Robot 2"; // Send the message link.send((uint8_t*)message, strlen(message));
Code voor Robot 2
// Create the link serial_link link(PORT1, "VEXRoboticsLink123456789", linkType::worker, true); // Do not run code UNTIL the Brains are linked while (!link.isLinked()) { wait(0.1, seconds); } Brain.Screen.print("Robot 2 - Worker"); Brain.Screen.newLine(); Brain.Screen.print("Waiting..."); // Buffer to store incoming bytes uint8_t buffer[32] = {0}; int32_t n = link.receive(buffer, sizeof(buffer) - 1); // Null-terminate if (n > 0) { buffer[n] = 0; // Display the message that was sent Brain.Screen.clearScreen(); Brain.Screen.setCursor(1, 1); Brain.Screen.print("Robot 2 - Worker"); Brain.Screen.newLine(); Brain.Screen.print((char*)buffer); } else { Brain.Screen.newLine(); Brain.Screen.print("No message received"); }
send#
Verstuurt een bericht naar het gekoppelde brein.
Available Functions1 — Verstuurt een bericht met behulp van een bytebuffer.
int32_t send( uint8_t *buffer, int32_t length );
Parameters2 — Verstuurt een bericht met behulp van een tekenbuffer.
int32_t send( const char *buffer, int32_t length );
Parameter |
Type |
Beschrijving |
|---|---|---|
|
|
De buffer die naar de andere gekoppelde EXP Brain moet worden verzonden. |
|
|
De lengte van de te verzenden buffer. |
Retourneert een int32_t die het aantal verzonden bytes vertegenwoordigt.
Code voor Robot 1
// Create the link serial_link link(PORT1, "VEXRoboticsLink123456789", linkType::manager, true); // Do not run code UNTIL the Brains are linked while (!link.isLinked()) { wait(0.1, seconds); } Brain.Screen.clearScreen(); Brain.Screen.setCursor(1, 1); Brain.Screen.print("Robot 1 - Manager"); // Track last sent state uint8_t lastState = 255; // impossible initial value // Tell Robot 2 when the screen is being pressed while (true) { uint8_t state = Brain.Screen.pressing() ? 1 : 0; // Only send if state changed if (state != lastState) { link.send(&state, 1); lastState = state; } wait(0.02, seconds); }
Code voor Robot 2
// Create the link serial_link link(PORT1, "VEXRoboticsLink123456789", linkType::worker, true); // Do not run code UNTIL the Brains are linked while (!link.isLinked()) { wait(0.1, seconds); } Brain.Screen.clearScreen(); Brain.Screen.setCursor(1, 1); Brain.Screen.print("Robot 2 - Worker"); Brain.Screen.newLine(); Brain.Screen.print("Waiting..."); // Track the last state uint8_t lastShown = 255; while (true) { // Variable stores 1 - pressed, 0 - not pressed uint8_t state = 0; int32_t n = link.receive(&state, 1, 200); // Only update screen if state changes if (n == 1 && state != lastShown) { Brain.Screen.clearScreen(); Brain.Screen.setCursor(1, 1); Brain.Screen.print("Robot 2 - Worker"); Brain.Screen.newLine(); // Display text if Robot 1's screen is being pressed if (state == 1) { Brain.Screen.print("Manager IS being pressed!"); } else { Brain.Screen.print("Manager is NOT being pressed"); } lastShown = state; } wait(0.02, seconds); }
receive#
Wacht op het volgende binnenkomende bericht en stuurt het terug.
Available FunctionsParameters1 — Ontvangt een bericht in een tekenbuffer met optionele time-out.
int32_t receive( char *buffer, int32_t length, int32_t timeoutMs = 500);
Parameter |
Type |
Beschrijving |
|---|---|---|
|
|
De buffer om het ontvangen bericht op te slaan. |
|
|
De lengte van de buffer. |
|
|
Hoe lang in milliseconden ontvangt |
Retourneert een int32_t die het aantal ontvangen bytes weergeeft.
receiveen retourneert het volgende bericht uit de wachtrij van de andere gekoppelde EXP Brain.Berichten worden in FIFO-volgorde gelezen (oudste ongelezen eerst).
Als de wachtrij leeg is wanneer
receivewordt aangeroepen, wacht deze maximaal de opgegeventimeoutMsop een nieuw bericht.Als er binnen dat tijdsvenster geen bericht binnenkomt, retourneert
receive0, en blijft elk bericht dat daarna wordt verzonden in de wachtrij staan om te worden gelezen wanneerreceivede volgende keer wordt gebruikt.
Code voor Robot 1
// Create the link serial_link link(PORT1, "VEXRoboticsLink123456789", linkType::manager, true); // Do not run code UNTIL the Brains are linked while (!link.isLinked()) { wait(0.1, seconds); } Brain.Screen.clearScreen(); Brain.Screen.setCursor(1, 1); Brain.Screen.print("Robot 1 - Manager"); // Track last sent state uint8_t lastState = 255; // impossible initial value // Tell Robot 2 when the screen is being pressed while (true) { uint8_t state = Brain.Screen.pressing() ? 1 : 0; // Only send if state changed if (state != lastState) { link.send(&state, 1); lastState = state; } wait(0.02, seconds); }
Code voor Robot 2
// Create the link serial_link link(PORT1, "VEXRoboticsLink123456789", linkType::worker, true); // Do not run code UNTIL the Brains are linked while (!link.isLinked()) { wait(0.1, seconds); } Brain.Screen.clearScreen(); Brain.Screen.setCursor(1, 1); Brain.Screen.print("Robot 2 - Worker"); Brain.Screen.newLine(); Brain.Screen.print("Waiting..."); // Track the last state uint8_t lastShown = 255; while (true) { // Variable stores 1 - pressed, 0 - not pressed uint8_t state = 0; int32_t n = link.receive(&state, 1, 200); // Only update screen if state changes if (n == 1 && state != lastShown) { Brain.Screen.clearScreen(); Brain.Screen.setCursor(1, 1); Brain.Screen.print("Robot 2 - Worker"); Brain.Screen.newLine(); // Display text if Robot 1's screen is being pressed if (state == 1) { Brain.Screen.print("Manager IS being pressed!"); } else { Brain.Screen.print("Manager is NOT being pressed"); } lastShown = state; } wait(0.02, seconds); }
received#
Registreert een functie die wordt aangeroepen wanneer de EXP Brain een verzonden bericht ontvangt.
Available Functions1 — Registreert een callbackfunctie voor elk ontvangen bericht.
void received( void (* callback)(const char *, const char *, double) );
2 — Registreert een callback die wordt aangeroepen voor elk ontvangen bericht dat een extra int32_t-veld bevat.
void received( void (* callback)(const char *, const char *, int32_t, double) );
3 — Registreert een callback die alleen wordt aangeroepen voor ontvangen berichten waarvan de naam overeenkomt met het bericht.
void received( const char *message, void (* callback)(const char *, const char *, double) );
Parameters4 — Registreert een callback die alleen wordt aangeroepen voor ontvangen berichten waarvan de naam overeenkomt met het bericht, waarbij de berichtpayload een extra int32_t-veld bevat.
void received( const char *message, void (* callback)(const char *, const char *, int32_t, double) );
Parameter |
Type |
Beschrijving |
|---|---|---|
|
|
The message name (string) to match. When a received message’s name matches this value, the |
|
|
Een eerder gedefinieerde functie die wordt uitgevoerd wanneer de EXP Brain een bericht ontvangt dat overeenkomt met bericht |
Deze functie retourneert geen waarde.
NotesEr zijn
receivedargumenten:
callback(message, linkname, index, value)
Argument |
Beschrijving |
|---|---|
|
De naam van het ontvangen bericht (bijvoorbeeld |
|
De naam van de link waarvan het bericht afkomstig is. |
|
De integerwaarde die met het bericht is meegestuurd (indien opgegeven). |
|
De zwevendekommagetalwaarde die met het bericht is meegestuurd (indien aanwezig). |
Code voor Robot 1
// Send left or right when pressed void screen_pressed() { if (Brain.Screen.xPosition() < 240) { link.send((uint8_t*)"left", 4); } else { link.send((uint8_t*)"right", 5); } } int main() { /* vexcodeInit() is only required when using VEXcode. Remove vexcodeInit() if compiling in VS Code. */ vexcodeInit(); // Create the link serial_link link(PORT1, "VEXRoboticsLink123456789", linkType::manager, true); // Do not run code UNTIL the Brains are linked while (!link.isLinked()) { wait(0.1, seconds); } Brain.Screen.print("Robot 1 - Manager"); Brain.Screen.pressed(screen_pressed); }
Code voor Robot 2
// Called when message received void received_callback(uint8_t *buffer, int32_t length) { char msg[32]; // Copy safely and null terminate int n = (length < 31) ? length : 31; memcpy(msg, buffer, n); msg[n] = '\0'; Brain.Screen.clearScreen(); Brain.Screen.setCursor(1,1); Brain.Screen.print("Robot 2 - Worker"); Brain.Screen.newLine(); // Display if Robot 1's screen is pressed on left or right if (strcmp(msg, "left") == 0) { Brain.Screen.print("Manager pressed LEFT"); } else if (strcmp(msg, "right") == 0) { Brain.Screen.print("Manager pressed RIGHT"); } } int main() { /* vexcodeInit() is only required when using VEXcode. Remove vexcodeInit() if compiling in VS Code. */ vexcodeInit(); // Create the link serial_link link(PORT1, "VEXRoboticsLink123456789", linkType::worker, true); // Do not run code UNTIL the Brains are linked while (!link.isLinked()) { wait(0.1, seconds); } link.received(received_callback); Brain.Screen.clearScreen(); Brain.Screen.setCursor(1,1); Brain.Screen.print("Robot 2 - Worker"); Brain.Screen.newLine(); Brain.Screen.print("Waiting..."); }