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 V5 Brain. De wachtrij wordt gelezen volgens het first-in, first-out (FIFO) principe. Als er meerdere berichten worden verzonden voordat de andere V5 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 V5-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 V5 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 V5-hersenen 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 V5 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 V5-hersenen met elkaar verbonden zijn:
true— The two V5 Brains are paired and communicating on this link.false— The two V5 Brains are not paired on this link.
Het is goede gewoonte om aan het begin van een project altijd te controleren of de V5 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 V5 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 V5 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 telkens wanneer de V5 Brain gegevens ontvangt.
Available FunctionsParameters1 — Registreert een callbackfunctie voor elke ontvangen bytebuffer.
void received( void (* callback)(uint8_t *, int32_t) );
Parameter |
Type |
Beschrijving |
|---|---|---|
|
|
Een vooraf gedefinieerde functie die wordt uitgevoerd wanneer de V5-hersenen gegevens ontvangen. |
Deze functie retourneert geen waarde.
Notesreceivedcallbacks are called with two arguments: a byte buffer and the number of bytes received.De ontvangen gegevens hoeven niet te eindigen met een null-teken. Als de callback de gegevens als een tekenreeks behandelt, kopieert u de ontvangen bytes naar een tekenreeksarray en voegt u een null-teken toe.
callback(buffer, length)
Argument |
Beschrijving |
|---|---|
|
Een aanwijzer naar de ontvangen bytebuffer. |
|
Het aantal ontvangen bytes. |
Code voor Robot 1
// Create the link. serial_link link(PORT1, "VEXRoboticsLink123456789", linkType::manager, true); // 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(); // 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); while (true) { wait(10, msec); } }
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..."); while (true) { wait(10, msec); } }