직렬 링크#
소개#
serial_link 클래스는 로봇 간에 원시 바이트 스트림을 전송할 수 있도록 합니다. 이 클래스는 송신 로봇과 수신 로봇 모두 데이터 스트림의 내용을 이해하는 로봇 간 통신을 위해 설계되었습니다.
send를 사용할 때마다 연결된 V5 Brain의 큐에 데이터가 추가되며, 큐는 선입선출(FIFO) 방식으로 읽힙니다. 다른 V5 Brain이 수신하기 전에 여러 메시지가 전송되면 해당 메시지는 저장되었다가 전송된 순서대로 하나씩 반환됩니다. 메시지는 큐에 저장될 수 있으므로, 매 루프마다 동일한 상태를 반복적으로 전송하면 백로그가 발생할 수 있습니다. 시간 제약이 있는 로직의 경우 값이 변경될 때만 전송하십시오.
중요: 두 로봇 모두 동시에 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 라디오와 함께 사용할 수 있으며, 충돌을 방지하기 위해 가장 높은 번호의 스마트 포트에 연결해야 합니다.
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 브레인이 이 링크에서 페어링되고 통신하는지 확인합니다.send— 쌍을 이룬 Brain에 메시지를 보냅니다.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 Brains가 서로 페어링되었는지 여부를 반환합니다.
Available Functionsbool isLinked();
이 함수는 매개변수가 없습니다.
Return ValuesV5 브레인이 연결되어 있는지 여부를 나타내는 부울 값을 반환합니다.
true— The two V5 Brains are paired and communicating on this link.false— The two V5 Brains are not paired on this link.
프로젝트를 시작할 때 추가 코드를 실행하기 전에 V5 브레인이 제대로 연결되었는지 항상 확인하는 것이 좋습니다.
로봇 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 브레인으로 보낼 버퍼입니다. |
|
|
전송할 버퍼의 길이입니다. |
전송된 바이트 수를 나타내는 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 브레인에서 대기 중인 다음 메시지를 반환합니다.메시지는 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 브레인이 데이터를 수신할 때마다 호출될 함수를 등록합니다.
Available FunctionsParameters1 — 수신된 각 바이트 버퍼에 대한 콜백 함수를 등록합니다.
void received( void (* callback)(uint8_t *, int32_t) );
매개변수 |
유형 |
설명 |
|---|---|---|
|
|
V5 브레인이 데이터를 수신할 때 실행되는 미리 정의된 함수입니다. |
이 함수는 값을 반환하지 않습니다.
Notesreceived콜백이 호출되며, 이 콜백은 바이트 버퍼와 수신된 바이트 수라는 두 개의 인수를 받습니다.수신된 데이터는 널 종료 문자가 아닐 수 있습니다. 콜백 함수가 데이터를 문자열로 처리하는 경우, 수신된 바이트를 문자 배열에 복사하고 널 종료 문자를 추가하십시오.
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); } }