Enlace serie#
Introducción#
The serial_link class allows for a stream of raw bytes to be sent between robots. It’s designed for robot-to-robot communication where the transmitting and receiving robot both understand the contents of the data stream.
Every usage of send adds data to the linked V5 Brain’s queue, and the queue is read first-in, first-out (FIFO). If multiple messages are sent before the other V5 Brain uses receive, they will be stored and returned one at a time in the order they were sent. Because messages can queue, repeatedly sending the same status every loop may create backlog; for time-critical logic, send only when values change.
Important: Both robots must be running projects that use serial_link at the same time, or no data will be sent/received.
Constructores de clases#
serial_link(
int32_t index,
const char *name,
linkType type,
bool isWired = false );
Instructor de clase#
Destroys the serial_link object and releases associated resources.
~serial_link();
Parámetros#
Parámetro |
Tipo |
Descripción |
|---|---|---|
|
|
The Smart Port that the message link is connected to, written as |
|
|
El nombre de este enlace. Se recomienda que esta cadena única sea lo suficientemente larga como para que, al ser procesada por vexos, genere un ID único. Un nombre de enlace inadecuado sería algo genérico como “vexlink”, ya que podría ser utilizado por otro equipo. |
|
|
The type of link, either
|
|
|
Whether the serial_link object is wired (defaults to
|
Notas#
VEXlink admite comunicación inalámbrica y por cable, recomendándose para las conexiones por cable un cable inteligente modificado para evitar problemas de enrutamiento de energía.
Para la comunicación inalámbrica, cada robot necesita una radio V5 conectada a un puerto inteligente.
La radio VEXlink se puede usar junto con la radio VEXnet de un controlador V5, que debe conectarse al puerto inteligente con el número más alto para evitar conflictos.
Para crear un VEXlink, ambos cerebros V5 deben estar conectados a una radio robótica V5.
Ejemplo#
Código para el Robot 1
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWiredCódigo para el Robot 2
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
Funciones de los miembros#
The serial_link class includes the following member functions:
isLinked— Checks if the V5 Brains are paired and communicating on this link.send— Sends a message to the paired Brain.receive— Waits for and returns the next incoming message.received— Registers a function to be called whenever a new message is received.
Before calling any serial_link member functions, a serial_link instance must be created, as shown below:
Código para el Robot 1
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWiredCódigo para el Robot 2
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
isLinked#
Indica si los módulos V5 Brains conectados mediante un enlace serie están emparejados entre sí.
Available Functionsbool isLinked();
Esta función no tiene ningún parámetro.
Return ValuesDevuelve un valor booleano que indica si los cerebros V5 están conectados:
true— The two V5 Brains are paired and communicating on this link.false— The two V5 Brains are not paired on this link.
Es recomendable comprobar siempre que los V5 Brains estén conectados al inicio de un proyecto, antes de ejecutar cualquier otro código.
Código para el 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));
Código para el 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#
Envía un mensaje al cerebro emparejado.
Available Functions1 — Envía un mensaje usando un búfer de bytes.
int32_t send( uint8_t *buffer, int32_t length );
Parameters2 — Envía un mensaje usando un búfer de caracteres.
int32_t send( const char *buffer, int32_t length );
Parámetro |
Tipo |
Descripción |
|---|---|---|
|
|
El búfer que se enviará al otro cerebro V5 vinculado. |
|
|
La longitud del búfer a enviar. |
Returns an int32_t representing the number of bytes sent.
Código para el 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); }
Código para el 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#
Espera el siguiente mensaje entrante y lo devuelve.
Available FunctionsParameters1 — Recibe un mensaje en un búfer de caracteres con tiempo de espera opcional.
int32_t receive( char *buffer, int32_t length, int32_t timeoutMs = 500);
Parámetro |
Tipo |
Descripción |
|---|---|---|
|
|
El búfer para almacenar el mensaje recibido. |
|
|
La longitud del búfer. |
|
|
How long in milliseconds |
Returns an int32_t representing the number of bytes received.
receivereturns the next queued message from the other linked V5 Brain.Los mensajes se leen en orden FIFO (primero los que no se han leído, primero).
If the queue is empty when
receiveis called, it waits up to the specifiedtimeoutMsfor a new message.If no message arrives in that window,
receivereturns0, and any message sent afterward remains in the queue to be read the next timereceiveis used.
Código para el 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); }
Código para el 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#
Registra una función que se llamará cada vez que el V5 Brain reciba un mensaje.
Available Functions1 — Registra una función de devolución de llamada para cada mensaje recibido.
void received( void (* callback)(const char *, const char *, double) );
2 — Registra una función de devolución de llamada que se invoca para cada mensaje recibido que incluye un campo int32_t adicional.
void received( void (* callback)(const char *, const char *, int32_t, double) );
3 — Registra una función de devolución de llamada que se invoca solo para los mensajes recibidos cuyo nombre coincide con el mensaje.
void received( const char *message, void (* callback)(const char *, const char *, double) );
Parameters4 — Registra una función de devolución de llamada que se invoca solo para los mensajes recibidos cuyo nombre coincide con el mensaje, donde la carga útil del mensaje incluye un campo int32_t adicional.
void received( const char *message, void (* callback)(const char *, const char *, int32_t, double) );
Parámetro |
Tipo |
Descripción |
|---|---|---|
|
|
The message name (string) to match. When a received message’s name matches this value, the |
|
|
A previously defined function that runs when the V5 Brain receives a message matching |
Esta función no devuelve ningún valor.
Notesreceivedcallbacks are called with four arguments:
callback(message, linkname, index, value)
Argumento |
Descripción |
|---|---|
|
The message name that was received (for example, |
|
El nombre del enlace desde el que se recibió el mensaje. |
|
El valor entero enviado con el mensaje (si se proporciona). |
|
El valor flotante enviado con el mensaje (si se proporciona). |
Código para el 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); }
Código para el 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..."); }