串行链路#
介绍#
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.
类构造函数#
serial_link(
int32_t index,
const char *name,
linkType type,
bool isWired = false );
类析构函数#
Destroys the serial_link object and releases associated resources.
~serial_link();
参数#
范围 |
类型 |
描述 |
|---|---|---|
|
|
The Smart Port that the message link is connected to, written as |
|
|
此链接的名称。建议此唯一字符串足够长,以便 Vexos 对其进行哈希处理后能够生成唯一的 ID。不建议使用“vexlink”之类的通用名称,因为它可能被其他团队使用。 |
|
|
The type of link, either
|
|
|
Whether the serial_link object is wired (defaults to
|
笔记#
VEXlink 支持无线和有线通信,有线连接建议使用改良的智能电缆,以防止电源路由问题。
对于无线通信,每个机器人都需要一个连接到智能端口的 V5 机器人无线电模块。
VEXlink 无线电可以与 V5 控制器的 VEXnet 无线电一起使用,应将其连接到编号最高的智能端口以避免冲突。
要创建 VEXlink,两个 V5 主控模块都必须连接到 V5 机器人无线电模块。
例子#
机器人 1 的代码
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWired机器人2的代码
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
成员功能#
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:
机器人 1 的代码
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::manager, // type true); // isWired机器人2的代码
// Create a wireless link in Port 1 serial_link link = serial_link( PORT1, // index "VEXRoboticsLink123456789", // name linkType::worker, // type true); // isWired
isLinked#
返回通过串行链路连接的 V5 大脑是否彼此配对。
Available Functionsbool isLinked();
此函数没有任何参数。
Return Values返回一个布尔值,指示 V5 大脑是否已连接:
true— The two V5 Brains are paired and communicating on this link.false— The two V5 Brains are not paired on this link.
在项目开始时,运行任何其他代码之前,最好始终检查以确保 V5 Brains 已连接。
机器人 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));
机器人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#
向配对的大脑发送消息。
Available Functions1 — 使用字节缓冲区发送消息。
int32_t send( uint8_t *buffer, int32_t length );
Parameters2 — 使用字符缓冲区发送消息。
int32_t send( const char *buffer, int32_t length );
范围 |
类型 |
描述 |
|---|---|---|
|
|
要发送到另一个已连接的 V5 脑区的缓冲区。 |
|
|
要发送的缓冲区长度。 |
Returns an int32_t representing the number of bytes sent.
机器人 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); }
机器人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#
等待并返回下一条传入的消息。
Available FunctionsParameters1 — 将消息接收到字符缓冲区中,并可选择设置超时时间。
int32_t receive( char *buffer, int32_t length, int32_t timeoutMs = 500);
范围 |
类型 |
描述 |
|---|---|---|
|
|
用于存储接收到的消息的缓冲区。 |
|
|
缓冲区长度。 |
|
|
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.消息按先进先出(FIFO)顺序读取(最旧的未读消息优先)。
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.
机器人 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); }
机器人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#
注册一个函数,当 V5 大脑收到发送的消息时,该函数将被调用。
Available Functions1 — 为收到的每条消息注册一个回调函数。
void received( void (* callback)(const char *, const char *, double) );
2 — 注册一个回调函数,该函数会针对每个接收到的消息调用,其中包含一个额外的 int32_t 字段。
void received( void (* callback)(const char *, const char *, int32_t, double) );
3 — 注册一个回调函数,该回调函数仅在接收到名称与 message 匹配的消息时才会调用。
void received( const char *message, void (* callback)(const char *, const char *, double) );
Parameters4 — 注册一个回调函数,该回调函数仅在接收到名称与 message 匹配的消息时调用,其中消息有效负载包含一个额外的 int32_t 字段。
void received( const char *message, void (* callback)(const char *, const char *, int32_t, double) );
范围 |
类型 |
描述 |
|---|---|---|
|
|
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 |
此函数不返回值。
Notesreceivedcallbacks are called with four arguments:
callback(message, linkname, index, value)
争论 |
描述 |
|---|---|
|
The message name that was received (for example, |
|
收到该消息的链接名称。 |
|
消息中发送的整数值(如果提供)。 |
|
消息中发送的浮点值(如果提供)。 |
机器人 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); }
机器人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..."); }