Sériové propojení#
Zavedení#
Třída serial_link umožňuje odesílání proudu nezpracovaných bajtů mezi roboty. Je navržena pro komunikaci mezi roboty, kde vysílající i přijímající robot rozumí obsahu datového proudu.
Každé použití funkce send přidává data do fronty propojeného EXP Brain a fronta se čte v systému FIFO (first in, first out). Pokud je odesláno více zpráv předtím, než druhý EXP Brain použije funkci receive, budou uloženy a vráceny jedna po druhé v pořadí, v jakém byly odeslány. Protože se zprávy mohou řadit do fronty, opakované odesílání stejného stavu v každé smyčce může způsobit nahromadění nevyřízených dat; z časově kritické logiky odesílejte pouze při změně hodnot.
Důležité: Oba roboti musí současně spouštět projekty, které používají serial_link , jinak nebudou odesílána/přijímána žádná data.
Konstruktory tříd#
serial_link(
int32_t index,
const char *name,
linkType type,
bool isWired = false );
Destruktor tříd#
Zničí objekt serial_link a uvolní přidružené prostředky.
~serial_link();
Parametry#
Parametr |
Typ |
Popis |
|---|---|---|
|
|
Inteligentní port, ke kterému je připojen odkaz na zprávu, zapsaný jako |
|
|
Název tohoto odkazu. Doporučuje se, aby tento jedinečný řetězec byl dostatečně dlouhý, aby po hašování službou vexos vytvořil jedinečné ID. Špatný název odkazu by byl něco obecného, například „vexlink“, protože by ho mohl používat jiný tým. |
|
|
Typ odkazu, buď
|
|
|
Zda je objekt serial_link připojen kabelem (výchozí hodnota je
|
Poznámky#
VEXlink podporuje bezdrátovou i kabelovou komunikaci, přičemž pro kabelové připojení se doporučuje použít upravený inteligentní kabel, aby se předešlo problémům s vedením napájení.
Pro bezdrátovou komunikaci potřebuje každý robot rádio V5 připojené k inteligentnímu portu.
Rádiový modul VEXlink lze použít společně s rádiovým modulem VEXnet ovladače EXP, který by měl být připojen k nejvyššímu číslu inteligentního portu, aby se předešlo konfliktům.
Pro vytvoření VEXlinku musí být oba EXP mozky připojeny k robotickému rádiu V5.
Příklad#
Kód pro robota 1
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWiredKód pro Robota 2
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
Členské funkce#
Třída serial_link obsahuje následující členské funkce:
isLinked— Zkontroluje, zda jsou EXP mozky spárované a komunikují na tomto odkazu.send— Odešle zprávu spárovanému mozku.receive— Čeká na další příchozí zprávu a vrací ji.received— Registruje funkci, která má být volána při každém přijetí nové zprávy.
Před voláním jakékoli členské funkce typu serial_link musí být vytvořena instance serial_link , jak je znázorněno níže:
Kód pro robota 1
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWiredKód pro Robota 2
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
isLinked#
Vrací, zda jsou EXP mozky na sériovém propojení vzájemně spárovány.
Available Functionsbool isLinked();
Tato funkce nemá žádné parametry.
Return ValuesVrací booleovskou hodnotu označující, zda jsou EXP mozky propojeny:
true— The two EXP Brains are paired and communicating on this link.false— The two EXP Brains are not paired on this link.
Je dobrým zvykem vždy zkontrolovat, zda jsou EXP Brains propojeny na začátku projektu, než spustíte jakýkoli další kód.
Kód pro robota 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));
Kód pro Robota 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#
Odešle zprávu spárovanému mozku.
Available Functions1 — Odešle zprávu s využitím bajtové vyrovnávací paměti.
int32_t send( uint8_t *buffer, int32_t length );
Parameters2 — Odešle zprávu s použitím vyrovnávací paměti znaků.
int32_t send( const char *buffer, int32_t length );
Parametr |
Typ |
Popis |
|---|---|---|
|
|
Vyrovnávací paměť, která se má odeslat do druhého propojeného EXP mozku. |
|
|
Délka vyrovnávací paměti, která se má odeslat. |
Vrací hodnotu int32_t představující počet odeslaných bajtů.
Kód pro robota 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); }
Kód pro Robota 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#
Čeká na další příchozí zprávu a vrací ji.
Available FunctionsParameters1 — Přijme zprávu do vyrovnávací paměti znaků s volitelným časovým limitem.
int32_t receive( char *buffer, int32_t length, int32_t timeoutMs = 500);
Parametr |
Typ |
Popis |
|---|---|---|
|
|
Vyrovnávací paměť pro uložení přijaté zprávy. |
|
|
Délka vyrovnávací paměti. |
|
|
Jak dlouho v milisekundách |
Vrací hodnotu int32_t představující počet přijatých bajtů.
receivevrací další zprávu ve frontě z druhého propojeného EXP Brainu.Zprávy se čtou v pořadí FIFO (nejstarší nepřečtené jako první).
Pokud je fronta při volání funkce
receiveprázdná, čeká na novou zprávu až do zadaného časového limitutimeoutMs.Pokud v tomto okně nedorazí žádná zpráva,
receivevrátí0a jakákoli zpráva odeslaná poté zůstane ve frontě ke čtení při příštím použitíreceive.
Kód pro robota 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); }
Kód pro Robota 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#
Registruje funkci, která má být volána vždy, když EXP Brain přijme odeslanou zprávu.
Available Functions1 — Zaregistruje funkci zpětného volání pro každou přijatou zprávu.
void received( void (* callback)(const char *, const char *, double) );
2 — Registruje zpětné volání vyvolané pro každou přijatou zprávu, která obsahuje další pole int32_t.
void received( void (* callback)(const char *, const char *, int32_t, double) );
3 — Registruje zpětné volání vyvolané pouze pro přijaté zprávy, jejichž název odpovídá textu message.
void received( const char *message, void (* callback)(const char *, const char *, double) );
Parameters4 — Registruje zpětné volání vyvolané pouze pro přijaté zprávy, jejichž název odpovídá textu message, kde datová část zprávy obsahuje další pole int32_t.
void received( const char *message, void (* callback)(const char *, const char *, int32_t, double) );
Parametr |
Typ |
Popis |
|---|---|---|
|
|
The message name (string) to match. When a received message’s name matches this value, the |
|
|
Dříve definovaná funkce, která se spustí, když EXP Brain obdrží zprávu odpovídající |
Tato funkce nevrací hodnotu.
Notesreceivedzpětných volání se čtyřmi argumenty:
callback(message, linkname, index, value)
Argument |
Popis |
|---|---|
|
Název přijaté zprávy (například |
|
Název odkazu, ze kterého byla zpráva přijata. |
|
Celočíselná hodnota odeslaná se zprávou (pokud je zadána). |
|
Hodnota s desetinnou čárkou odeslaná se zprávou (pokud je zadána). |
Kód pro robota 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); }
Kód pro Robota 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..."); }