رابط تسلسلي#
مقدمة#
تتيح فئة 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. أما اسم الرابط غير المناسب فهو اسم عام مثل “vexlink” لأنه قد يكون مستخدمًا من قِبل فريق آخر. |
|
|
نوع الرابط، إما
|
|
|
ما إذا كان كائن serial_link سلكيًا (الافتراضي
|
ملحوظات#
يدعم VEXlink كلاً من الاتصالات اللاسلكية والسلكية، مع التوصية باستخدام كابل ذكي معدل للاتصالات السلكية لمنع مشاكل توجيه الطاقة.
للاتصال اللاسلكي، يحتاج كل روبوت إلى جهاز راديو روبوت V5 متصل بمنفذ ذكي.
يمكن استخدام راديو VEXlink جنبًا إلى جنب مع راديو VEXnet الخاص بوحدة التحكم V5، والذي يجب توصيله بالمنفذ الذكي ذي الرقم الأعلى لتجنب التعارضات.
لإنشاء 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 Brains مقترنة وتتواصل عبر هذا الرابط.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 مرتبطة ببعضها البعض أم لا:
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 الأخرى المرتبطة. |
|
|
طول المخزن المؤقت المراد إرساله. |
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);
المعلمة |
يكتب |
وصف |
|---|---|---|
|
|
المخزن المؤقت لتخزين الرسالة المستلمة. |
|
|
طول المخزن المؤقت. |
|
|
كم من الوقت بالمللي ثانية |
Returns an int32_t representing the number of bytes received.
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 بيانات.
Available FunctionsParameters1 — يسجل دالة رد نداء لكل مخزن بايت مستلم.
void received( void (* callback)(uint8_t *, int32_t) );
المعلمة |
يكتب |
وصف |
|---|---|---|
|
|
وظيفة محددة مسبقًا يتم تشغيلها عندما يتلقى معالج V5 Brain البيانات. |
هذه الدالة لا تُرجع قيمة.
Notesreceivedcallbacks are called with two arguments: a byte buffer and the number of bytes received.قد لا تكون البيانات المستلمة منتهية بحرف فارغ. إذا تعاملت دالة الاستدعاء مع البيانات كسلسلة نصية، فانسخ البايتات المستلمة إلى مصفوفة أحرف وأضف حرفًا فارغًا لإنهاء السلسلة.
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); } }