Σειριακός σύνδεσμος#
Εισαγωγή#
Η κλάση serial_link επιτρέπει την αποστολή μιας ροής ακατέργαστων bytes μεταξύ ρομπότ. Έχει σχεδιαστεί για επικοινωνία ρομπότ με ρομπότ, όπου το ρομπότ μετάδοσης και το ρομπότ λήψης κατανοούν και τα δύο τα περιεχόμενα της ροής δεδομένων.
Κάθε χρήση του send προσθέτει δεδομένα στην ουρά του συνδεδεμένου EXP Brain και η ουρά διαβάζεται με προτεραιότητα την είσοδο, την έξοδο (FIFO). Εάν αποσταλούν πολλά μηνύματα πριν τα λάβει ο άλλος χρήστης του EXP 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 ενός ελεγκτή EXP, το οποίο θα πρέπει να είναι συνδεδεμένο στην Smart Port με τον μεγαλύτερο αριθμό για την αποφυγή διενέξεων.
Για να δημιουργήσετε ένα VEXlink, και οι δύο εγκέφαλοι EXP πρέπει να είναι συνδεδεμένοι σε ένα ρομποτικό ραδιόφωνο 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— Ελέγχει εάν οι εγκέφαλοι EXP είναι ζευγαρωμένοι και επικοινωνούν σε αυτόν τον σύνδεσμο.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#
Επιστρέφει εάν οι εγκέφαλοι EXP σε μια σειριακή σύνδεση είναι ζευγαρωμένοι μεταξύ τους.
Available Functionsbool isLinked();
Αυτή η συνάρτηση δεν έχει παραμέτρους.
Return ValuesΕπιστρέφει μια λογική τιμή που υποδεικνύει εάν οι εγκέφαλοι EXP είναι συνδεδεμένοι:
true— The two EXP Brains are paired and communicating on this link.false— The two EXP Brains are not paired on this link.
Είναι καλή πρακτική να ελέγχετε πάντα για να βεβαιωθείτε ότι οι εγκέφαλοι EXP είναι συνδεδεμένοι στην αρχή ενός έργου πριν από την εκτέλεση οποιουδήποτε περαιτέρω κώδικα.
Κωδικός για το Ρομπότ 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 που θα σταλεί στον άλλο συνδεδεμένο εγκέφαλο EXP. |
|
|
Το μήκος του 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επιστρέφει το επόμενο μήνυμα στην ουρά από τον άλλο συνδεδεμένο εγκέφαλο EXP.Τα μηνύματα διαβάζονται με σειρά 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#
Καταγράφει μια συνάρτηση που θα καλείται κάθε φορά που ο εγκέφαλος EXP λαμβάνει ένα απεσταλμένο μήνυμα.
Available Functions1 — Καταχωρεί μια συνάρτηση επανάκλησης για κάθε ληφθέν μήνυμα.
void received( void (* callback)(const char *, const char *, double) );
2 — Καταγράφει μια επανάκληση που καλείται για κάθε ληφθέν μήνυμα που περιλαμβάνει ένα επιπλέον πεδίο int32_t.
void received( void (* callback)(const char *, const char *, int32_t, double) );
3 — Καταχωρεί μια επανάκληση που καλείται μόνο για ληφθέντα μηνύματα των οποίων το όνομα ταιριάζει με το μήνυμα.
void received( const char *message, void (* callback)(const char *, const char *, double) );
Parameters4 — Καταχωρεί μια επανάκληση που καλείται μόνο για ληφθέντα μηνύματα των οποίων το όνομα ταιριάζει με το μήνυμα, όπου το ωφέλιμο φορτίο μηνύματος περιλαμβάνει ένα επιπλέον πεδίο int32_t.
void received( const char *message, void (* callback)(const char *, const char *, int32_t, double) );
Παράμετρος |
Τύπος |
Περιγραφή |
|---|---|---|
|
|
Το όνομα του μηνύματος (συμβολοσειρά) που θα ταιριάζει. Όταν το όνομα ενός ληφθέντος μηνύματος ταιριάζει με αυτήν την τιμή, καλείται η συνάρτηση |
|
|
Μια προηγουμένως καθορισμένη συνάρτηση που εκτελείται όταν ο εγκέφαλος EXP λαμβάνει ένα μήνυμα που ταιριάζει με το μήνυμα |
Αυτή η συνάρτηση δεν επιστρέφει τιμή.
NotesΟι επανακλήσεις
receivedκαλούνται με τέσσερα ορίσματα:
callback(message, linkname, index, value)
Επιχείρημα |
Περιγραφή |
|---|---|
|
Το όνομα του μηνύματος που ελήφθη (για παράδειγμα, |
|
Το όνομα του συνδέσμου από τον οποίο ελήφθη το μήνυμα. |
|
Η ακέραια τιμή που αποστέλλεται με το μήνυμα (εάν παρέχεται). |
|
Η τιμή float που αποστέλλεται με το μήνυμα (εάν παρέχεται). |
Κωδικός για το Ρομπότ 1
// 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(); // 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.pressed(screen_pressed); }
Κωδικός για το Ρομπότ 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..."); }