Послідовне посилання#
Вступ#
Клас serial_link дозволяє надсилати потік необроблених байтів між роботами. Він розроблений для зв’язку між роботами, де робот-передавач і робот-отримувач розуміють вміст потоку даних.
Кожне використання send додає дані до черги пов’язаного V5 Brain, і черга зчитується в порядку «першим прийшов, першим вийшов» (FIFO). Якщо кілька повідомлень надіслано до того, як інший V5 Brain використає receive, вони будуть збережені та повернуті по одному в порядку надсилання. Оскільки повідомлення можуть стояти в черзі, багаторазове надсилання одного й того ж статусу в кожному циклі може створювати затримки; для логіки, критичної за часом, надсилайте лише тоді, коли значення змінюються.
Важливо: Обидва роботи повинні одночасно запускати проекти, що використовують serial_link , інакше дані не будуть надсилатися/отримуватися.
Конструктори класів#
serial_link(
int32_t index,
const char *name,
linkType type,
bool isWired = false );
Деструктор класів#
Знищує об’єкт serial_link та звільняє пов’язані з ним ресурси.
~serial_link();
Параметри#
Параметр |
Тип |
Опис |
|---|---|---|
|
|
Розумний порт, до якого підключено посилання повідомлення, записується як |
|
|
Назва цього посилання. Рекомендується, щоб цей унікальний рядок був достатньо довгим, щоб після хешування vexos він створив унікальний ідентифікатор. Неправильною назвою посилання буде щось загальне, наприклад, «vexlink», оскільки її може використовувати інша команда. |
|
|
Тип з’єднання:
|
|
|
Чи є об’єкт serial_link дротовим (за замовчуванням
|
Нотатки#
VEXlink підтримує як бездротовий, так і дротовий зв’язок, при цьому для дротового підключення рекомендується використовувати модифікований смарт-кабель, щоб уникнути проблем із прокладанням живлення.
Для бездротового зв’язку кожному роботу потрібен радіомодуль V5 Robot Radio, підключений до смарт-порту.
Радіоприймач VEXlink можна використовувати разом із радіоприймачем VEXnet контролера V5, який слід підключити до смарт-порту з найвищим номером, щоб уникнути конфліктів.
Щоб створити VEXlink, обидва модулі V5 Brain повинні бути підключені до радіомодуля V5 Robot Radio.
Приклад#
Код для робота 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— Надсилає повідомлення парному мозку.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 ValuesПовертає логічне значення, яке вказує, чи пов’язані V5 Brains:
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 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викликаються зворотні виклики з двома аргументами: байтовим буфером та кількістю отриманих байтів.Отримані дані можуть не мати нульового символу в кінці. Якщо зворотний виклик обробляє дані як рядок, скопіюйте отримані байти в масив символів і додайте нульовий символ у кінці.
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); } }