Seriell länk#
Introduktion#
Klassen serial_link möjliggör sändning av en ström av råa byte mellan robotar. Den är utformad för kommunikation mellan robotar där både den sändande och den mottagande roboten förstår innehållet i dataströmmen.
Varje användning av send lägger till data i den länkade EXP Brain-kön, och kön läses först in, först ut (FIFO). Om flera meddelanden skickas innan de andra EXP Brain-användarna tar emot, kommer de att lagras och returneras ett i taget i den ordning de skickades. Eftersom meddelanden kan köas kan det skapa en eftersläpning om man upprepar sändningar av samma status i varje loop; för tidskritisk logik, skicka endast när värdena ändras.
Viktigt: Båda robotarna måste köra projekt som använder serial_link samtidigt, annars kommer ingen data att skickas/tas emot.
Klasskonstruktörer#
serial_link(
int32_t index,
const char *name,
linkType type,
bool isWired = false );
Klassförstörare#
Förstör serial_link objektet och frigör tillhörande resurser.
~serial_link();
Parametrar#
Parameter |
Typ |
Beskrivning |
|---|---|---|
|
|
Den smarta port som meddelandelänken är ansluten till, skriven som |
|
|
Namnet på den här länken. Det rekommenderas att den här unika strängen är tillräckligt lång för att den ska skapa ett unikt ID när den hashas av vexos. Ett felaktigt länknamn skulle vara något generiskt som “vexlink” eftersom det kan användas av ett annat team. |
|
|
Länktypen, antingen
|
|
|
Om serial_link-objektet är trådbundet (standardvärdet är
|
Anteckningar#
VEXlink stöder både trådlös och trådbunden kommunikation, där trådbundna anslutningar rekommenderar en modifierad smart kabel för att förhindra problem med strömförsörjningen.
För trådlös kommunikation behöver varje robot en V5-robotradio ansluten till en Smart Port.
VEXlink-radion kan användas tillsammans med en EXP-styrenhets VEXnet-radio, som bör anslutas till den högst numrerade Smart Port för att undvika konflikter.
För att skapa en VEXlink måste båda EXP-hjärnorna vara anslutna till en V5-robotradio.
Exempel#
Kod för robot 1
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWiredKod för robot 2
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
Medlemsfunktioner#
Klassen serial_link innehåller följande medlemsfunktioner:
isLinked— Kontrollerar om EXP-hjärnorna är parade ihop och kommunicerar på denna länk.send— Skickar ett meddelande till den parade hjärnan.receive— Väntar på och returnerar nästa inkommande meddelande.received— Registrerar en funktion som ska anropas när ett nytt meddelande tas emot.
Innan några serial_link medlemsfunktioner anropas måste en serial_link instans skapas, som visas nedan:
Kod för robot 1
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWiredKod för robot 2
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
isLinked#
Returnerar om EXP-hjärnorna på en seriell länk är parade med varandra.
Available Functionsbool isLinked();
Den här funktionen har inga parametrar.
Return ValuesReturnerar ett booleskt värde som anger om EXP-hjärnorna är länkade:
true— The two EXP Brains are paired and communicating on this link.false— The two EXP Brains are not paired on this link.
Det är god praxis att alltid kontrollera att EXP-hjärnorna är länkade i början av ett projekt innan du kör ytterligare kod.
Kod för 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));
Kod för 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#
Skickar ett meddelande till den parade hjärnan.
Available Functions1 — Skickar ett meddelande med hjälp av en bytebuffert.
int32_t send( uint8_t *buffer, int32_t length );
Parameters2 — Skickar ett meddelande med hjälp av en teckenbuffert.
int32_t send( const char *buffer, int32_t length );
Parameter |
Typ |
Beskrivning |
|---|---|---|
|
|
Bufferten som ska skickas till den andra länkade EXP-hjärnan. |
|
|
Längden på bufferten som ska skickas. |
Returnerar int32_t som representerar antalet skickade byte.
Kod för 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); }
Kod för 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#
Väntar på och returnerar nästa inkommande meddelande.
Available FunctionsParameters1 — Tar emot ett meddelande i en teckenbuffert med valfri timeout.
int32_t receive( char *buffer, int32_t length, int32_t timeoutMs = 500);
Parameter |
Typ |
Beskrivning |
|---|---|---|
|
|
Bufferten för att lagra det mottagna meddelandet. |
|
|
Buffertens längd. |
|
|
Hur länge i millisekunder |
Returnerar int32_t som representerar antalet mottagna byte.
receivereturnerar nästa meddelande i kö från den andra länkade EXP-hjärnan.Meddelanden läses i FIFO-ordning (äldsta olästa först).
Om kön är tom när
receiveanropas, väntar den upp till den angivnatimeoutMspå ett nytt meddelande.Om inget meddelande anländer i det fönstret returnerar
receive0, och alla meddelanden som skickas efteråt ligger kvar i kön för att läsas nästa gångreceiveanvänds.
Kod för 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); }
Kod för 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#
Registrerar en funktion som ska anropas när EXP-hjärnan tar emot ett skickat meddelande.
Available Functions1 — Registrerar en återuppringningsfunktion för varje mottaget meddelande.
void received( void (* callback)(const char *, const char *, double) );
2 — Registrerar ett återanrop som anropas för varje mottaget meddelande som innehåller ett ytterligare int32_t-fält.
void received( void (* callback)(const char *, const char *, int32_t, double) );
3 — Registrerar ett återuppringningssystem som endast anropas för mottagna meddelanden vars namn matchar meddelandet.
void received( const char *message, void (* callback)(const char *, const char *, double) );
Parameters4 — Registrerar ett återanrop som endast anropas för mottagna meddelanden vars namn matchar meddelande, där meddelandets nyttolast innehåller ett ytterligare int32_t-fält.
void received( const char *message, void (* callback)(const char *, const char *, int32_t, double) );
Parameter |
Typ |
Beskrivning |
|---|---|---|
|
|
The message name (string) to match. When a received message’s name matches this value, the |
|
|
En tidigare definierad funktion som körs när EXP-hjärnan tar emot ett meddelande som matchar |
Den här funktionen returnerar inget värde.
Notesreceivedåteranrop anropas med fyra argument:
callback(message, linkname, index, value)
Argument |
Beskrivning |
|---|---|
|
Meddelandenamnet som mottogs (till exempel |
|
Länknamnet som meddelandet mottogs från. |
|
Heltalsvärdet som skickas med meddelandet (om det anges). |
|
Flyttalsvärdet som skickas med meddelandet (om det anges). |
Kod för 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); }
Kod för 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..."); }