シリアルリンク#
導入#
serial_link クラスを使用すると、ロボット間で生のバイト列を送信できます。これは、送信側と受信側の両方のロボットがデータストリームの内容を理解する、ロボット間通信向けに設計されています。
send を使用するたびに、リンクされた V5 Brain のキューにデータが追加され、キューは先入れ先出し (FIFO) で読み取られます。他の V5 Brain が受信を使用する前に複数のメッセージが送信された場合、それらは保存され、送信された順序で 1 つずつ返されます。メッセージはキューに入れることができるため、ループごとに同じステータスを繰り返し送信するとバックログが発生する可能性があります。時間制約のあるロジックでは、値が変更されたときのみ送信してください。
重要: 両方のロボットは、 serial_link を使用するプロジェクトを同時に実行する必要があります。そうでない場合、データの送受信は行われません。
クラスコンストラクタ#
serial_link(
int32_t index,
const char *name,
linkType type,
bool isWired = false );
クラスデストラクタ#
serial_link オブジェクトを破棄し、関連するリソースを解放します。
~serial_link();
パラメータ#
パラメータ |
タイプ |
説明 |
|---|---|---|
|
|
メッセージリンクが接続されているスマートポートは、 |
|
|
このリンクの名前。この固有の文字列は、Vexosによってハッシュ化された際に一意のIDが生成されるよう、十分な長さにすることをお勧めします。「vexlink」のような一般的な名前は、他のチームによって使用される可能性があるため、好ましくありません。 |
|
|
リンクの種類は、
|
|
|
serial_link オブジェクトが有線かどうか (デフォルトは
|
注記#
VEXlinkは無線および有線通信の両方をサポートしており、有線接続の場合は電力経路の問題を回避するために改良されたスマートケーブルの使用を推奨します。
無線通信を行うには、各ロボットにスマートポートに接続されたV5ロボット無線機が必要です。
VEXlink無線機は、V5コントローラーのVEXnet無線機と併用できます。競合を避けるため、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
メンバーの機能#
serial_link クラスには、以下のメンバ関数が含まれています。
isLinked— V5 Brain がペアになってこのリンクで通信しているかどうかを確認します。send— ペアになっているブレインにメッセージを送信します。receive— 次の受信メッセージを待機し、返します。received— 新しいメッセージが受信されるたびに呼び出される関数を登録します。
serial_link メンバー関数を呼び出す前に、以下に示すように serial_link インスタンスを作成する必要があります。
ロボット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 Brainが互いにペアになっているかどうかを返します。
Available Functionsbool isLinked();
この関数には引数がありません。
Return ValuesV5 Brainがリンクされているかどうかを示すブール値を返します。
true— The two V5 Brains are paired and communicating on this link.false— The two V5 Brains are not paired on this link.
プロジェクトを開始する前に、V5 Brainが正しくリンクされていることを必ず確認してから、さらにコードを実行することをお勧めします。
ロボット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 Brainに送信するバッファ。 |
|
|
送信するバッファの長さ。 |
送信されたバイト数を表す int32_t を返します。
ロボット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);
パラメータ |
タイプ |
説明 |
|---|---|---|
|
|
受信したメッセージを格納するためのバッファ。 |
|
|
バッファの長さ。 |
|
|
|
受信したバイト数を表す int32_t を返します。
receiveは、リンクされたもう一方の V5 Brain から次のキューイングされたメッセージを返します。メッセージはFIFO順(最も古い未読メッセージから順に)で読み込まれます。
receiveが呼び出されたときにキューが空の場合、指定されたtimeoutMsまで新しいメッセージを待ちます。そのウィンドウ内にメッセージが到着しない場合、
receiveは0を返し、その後送信されたメッセージはキューに残り、receiveが次に使用されるときに読み取られます。
ロボット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 Brainがデータを受信するたびに呼び出される関数を登録します。
Available FunctionsParameters1 — 受信したバイトバッファごとにコールバック関数を登録します。
void received( void (* callback)(uint8_t *, int32_t) );
パラメータ |
タイプ |
説明 |
|---|---|---|
|
|
V5 Brainがデータを受信した際に実行される、事前に定義された関数。 |
この関数は値を返しません。
Notesreceivedコールバックが、バイトバッファと受信したバイト数の 2 つの引数で呼び出されます。受信データはヌル終端されていない可能性があります。コールバックがデータを文字列として扱う場合は、受信したバイト列を文字配列にコピーし、ヌル終端文字を追加してください。
callback(buffer, length)
口論 |
説明 |
|---|---|
|
受信したバイトバッファへのポインタ。 |
|
受信したバイト数。 |
ロボット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); } }
ロボット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); } }