Στέλνω μια λίστα με τις θέσεις των σερβομηχανισμών μέσω της σειριακής σύνδεσης στο arduino με την ακόλουθη μορφή
1:90&2:80&3:180
Η οποία θα μπορούσε να αναλυθεί ως εξής: "Ορίστε;", "Ορίστε;", "Ορίστε;":
servoId : Position & servoId : Position & servoId : Position
Πώς θα μπορούσα να χωρίσω αυτές τις τιμές και να τις μετατρέψω σε ακέραιο αριθμό;
Σε αντίθεση με άλλες απαντήσεις, εγώ θα προτιμούσα να μείνω μακριά από την String
για τους ακόλουθους λόγους:
Σε ένα ενσωματωμένο περιβάλλον όπως το Arduino (ακόμα και για ένα Mega που έχει περισσότερη SRAM), θα προτιμούσα να χρησιμοποιήσω πρότυπες συναρτήσεις της C:
strchr()
: αναζήτηση ενός χαρακτήρα σε μια συμβολοσειρά C (π.χ. char *
)strtok()
: χωρίζει ένα αλφαριθμητικό C σε υποαλφαριθμητικά, με βάση ένα διαχωριστικό χαρακτήραatoi()
: μετατρέπει μια συμβολοσειρά C σε int
.Αυτό θα οδηγούσε στο ακόλουθο δείγμα κώδικα:
// Calculate based on max input size expected for one command
#define INPUT_SIZE 30
...
// Get next command from Serial (add 1 for final 0)
char input[INPUT_SIZE + 1];
byte size = Serial.readBytes(input, INPUT_SIZE);
// Add the final 0 to end the C string
input[size] = 0;
// Read each command pair
char* command = strtok(input, "&");
while (command != 0)
{
// Split the command in two values
char* separator = strchr(command, ':');
if (separator != 0)
{
// Actually split the string in 2: replace ':' with 0
*separator = 0;
int servoId = atoi(command);
++separator;
int position = atoi(separator);
// Do something with servoId and position
}
// Find the next command in input string
command = strtok(0, "&");
}
Το πλεονέκτημα εδώ είναι ότι δεν πραγματοποιείται δυναμική κατανομή μνήμης- μπορείτε ακόμη και να δηλώσετε την input
ως τοπική μεταβλητή μέσα σε μια συνάρτηση που θα διαβάζει τις εντολές και θα τις εκτελεί- μόλις η συνάρτηση επιστρέψει, ανακτάται το μέγεθος που καταλαμβάνει η input
(στη στοίβα).
Θα μπορούσατε να κάνετε κάτι σαν το ακόλουθο, αλλά λάβετε υπόψη σας διάφορα πράγματα:
Αν χρησιμοποιήσετε την readStringUntil()
, θα περιμένει μέχρι να λάβει τον χαρακτήρα ή μέχρι να λήξει ο χρόνος. Έτσι, με το τρέχον αλφαριθμητικό σας, η τελευταία θέση θα διαρκέσει λίγο περισσότερο, καθώς πρέπει να περιμένει. Μπορείτε να προσθέσετε ένα τελειωτικό &
για να αποφύγετε αυτό το timout. Μπορείτε εύκολα να ελέγξετε αυτή τη συμπεριφορά στην οθόνη σας, δοκιμάστε να στείλετε τη συμβολοσειρά με και χωρίς το επιπλέον &
και θα δείτε αυτή την καθυστέρηση χρονοκαθυστέρησης.
Στην πραγματικότητα δεν χρειάζεστε τον δείκτη του σερβομηχανισμού, μπορείτε απλά να στείλετε το αλφαριθμητικό των θέσεων και να λάβετε τον δείκτη του σερβομηχανισμού από τη θέση της τιμής στο αλφαριθμητικό, κάπως έτσι: 90&80&180&
. Εάν χρησιμοποιείτε τον δείκτη σερβομηχανισμού, ίσως θέλετε να τον ελέγξετε (μετατρέψτε τον σε `int
, και στη συνέχεια αντιστοιχίστε τον δείκτη βρόχου i) για να βεβαιωθείτε ότι τίποτα δεν πήγε στραβά με το μήνυμά σας.
Πρέπει να ελέγξετε ότι το αλφαριθμητικό που επιστρέφει από το readStringUntil`` δεν είναι κενό. Αν η συνάρτηση έχει χρονοκαθυστέρηση, δεν λάβατε αρκετά δεδομένα, και έτσι οποιαδήποτε προσπάθεια εξαγωγής των τιμών του
int`` σας θα παράγει περίεργα αποτελέσματα.
void setup() {
Serial.begin(9600);
}
void loop() {
for(int i=1; i<=3; i++) {
String servo = Serial.readStringUntil(':');
if(servo != ""){
//here you could check the servo number
String pos = Serial.readStringUntil('&');
int int_pos=pos.toInt();
Serial.println("Pos");
Serial.println(int_pos);
}
}
}
Μπορείτε να χρησιμοποιήσετε Stream.readStringUntil(terminator)
περνώντας διαφορετικό τερματικό για κάθε μέρος.
Σε κάθε μέρος, στη συνέχεια, καλείτε `String.toInt