Σειριακός σύνδεσμος#
Εισαγωγή#
Η κλάση serial_link επιτρέπει την αποστολή μιας ροής ακατέργαστων bytes μεταξύ ρομπότ. Έχει σχεδιαστεί για επικοινωνία ρομπότ με ρομπότ, όπου το ρομπότ μετάδοσης και το ρομπότ λήψης κατανοούν και τα δύο τα περιεχόμενα της ροής δεδομένων.
Κάθε χρήση του send προσθέτει δεδομένα στην ουρά του συνδεδεμένου V5 Brain και η ουρά διαβάζεται με τη μέθοδο FIFO (first-in, first-out). Εάν αποσταλούν πολλά μηνύματα πριν τα λάβουν οι άλλες χρήσεις του 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 Robot Radio συνδεδεμένο σε μια Έξυπνη Θύρα.
Το VEXlink Radio μπορεί να χρησιμοποιηθεί παράλληλα με το VEXnet radio ενός V5 Controller, το οποίο θα πρέπει να είναι συνδεδεμένο στην Smart Port με τον μεγαλύτερο αριθμό για την αποφυγή διενέξεων.
Για να δημιουργήσετε ένα 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— Στέλνει ένα μήνυμα στον ζευγαρωμένο εγκέφαλο.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 σε μια σειριακή σύνδεση είναι ζευγαρωμένοι μεταξύ τους.
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 είναι συνδεδεμένοι στην αρχή ενός έργου πριν από την εκτέλεση οποιουδήποτε περαιτέρω κώδικα.
Κωδικός για το Ρομπότ 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 — Στέλνει ένα μήνυμα χρησιμοποιώντας ένα buffer byte.
int32_t send( uint8_t *buffer, int32_t length );
Parameters2 — Στέλνει ένα μήνυμα χρησιμοποιώντας μια προσωρινή μνήμη χαρακτήρων.
int32_t send( const char *buffer, int32_t length );
Παράμετρος |
Τύπος |
Περιγραφή |
|---|---|---|
|
|
Το buffer που θα σταλεί στον άλλο συνδεδεμένο εγκέφαλο V5. |
|
|
Το μήκος του buffer που θα αποσταλεί. |
Επιστρέφει την τιμή int32_t που αντιπροσωπεύει τον αριθμό των byte που στάλθηκαν.
Κωδικός για το Ρομπότ 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);
Παράμετρος |
Τύπος |
Περιγραφή |
|---|---|---|
|
|
Η προσωρινή μνήμη για την αποθήκευση του ληφθέντος μηνύματος. |
|
|
Το μήκος του buffer. |
|
|
Πόσο χρόνο σε χιλιοστά του δευτερολέπτου θα λάβει το |
Επιστρέφει την τιμή int32_t που αντιπροσωπεύει τον αριθμό των byte που λαμβάνονται.
Η εντολή
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 — Καταχωρεί μια συνάρτηση επανάκλησης για κάθε buffer byte που λαμβάνεται.
void received( void (* callback)(uint8_t *, int32_t) );
Παράμετρος |
Τύπος |
Περιγραφή |
|---|---|---|
|
|
Μια προηγουμένως καθορισμένη συνάρτηση που εκτελείται όταν ο εγκέφαλος V5 λαμβάνει δεδομένα. |
Αυτή η συνάρτηση δεν επιστρέφει τιμή.
NotesΟι επανακλήσεις
receivedκαλούνται με δύο ορίσματα: ένα buffer byte και τον αριθμό των byte που ελήφθησαν.Τα ληφθέντα δεδομένα ενδέχεται να μην έχουν τερματισμό null. Εάν η επανάκληση αντιμετωπίζει τα δεδομένα ως συμβολοσειρά, αντιγράψτε τα ληφθέντα byte σε έναν πίνακα χαρακτήρων και προσθέστε έναν τερματιστή null.
callback(buffer, length)
Επιχείρημα |
Περιγραφή |
|---|---|
|
Ένας δείκτης προς το buffer byte που λήφθηκε. |
|
Ο αριθμός των byte που ελήφθησαν. |
Κωδικός για το Ρομπότ 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); } }