Σειριακές Επικοινωνίες με Επεξεργασία
Η τάξη σειρών
Οι λειτουργίες για τη χρήση σειριακών επικοινωνιών σε Επεξεργασία ορίζονται στην τάξη Serial
.Η πρώτη λειτουργία που πρέπει να κάνετε για να τα χρησιμοποιήσετε σε ένα πρόγραμμα (σκίτσο) θα είναι να το ενσωματώσετε στον κώδικα με import processing.serial.*;
.
Τάξη Serial
Έχει πέντε διαφορετικούς κατασκευαστές ανάλογα με τις παραμέτρους που υποδεικνύονται. Η μόνη απαιτούμενη παράμετρος είναι το γονικό αντικείμενο (μητρική εταιρεία) που συνήθως αντιστοιχεί στο κύριο πρόγραμμα (ας πούμε, το παράθυρο του προγράμματος) της τάξης PApplet
. Όπως συνήθως ο γονέας θα είναι το πρόγραμμα που γράφεται (το σκίτσο τρέχον), η τιμή αυτής της πρώτης υποχρεωτικής παραμέτρου θα είναι this
.
Οι άλλες πέντε παράμετροι που μπορούν να περάσουν στον κατασκευαστή είναι ① η ταχύτητα, ② το όνομα της σειριακής θύρας ③ η ισοτιμία που χρησιμοποιούνται στο πρωτόκολλο, ④ τα bit δεδομένων και ⑤ τα bit διακοπής. Οι παράμετροι που μεταβιβάζονται πιο συχνά, εκτός από το απαιτούμενο γονικό αντικείμενο, είναι το όνομα της θύρας και η ταχύτητα.
La ταχύτητα σειριακής επικοινωνίας είναι ακέραιος αριθμός (int
), που προεπιλογή στην τιμή 9600 εάν αυτή η παράμετρος δεν μεταβιβαστεί στον κατασκευαστή.
Διαθέσιμες σειριακές θύρες. Η μέθοδος της λίστας
El όνομα λιμένα έχει τη μορφή που καθορίζεται από το σύστημα, με αυτόν τον τρόπο, για παράδειγμα στο Διανομές Linux θα είναι κάτι σαν /dev/ttyS4 / dev / ttyACM3 o /dev/ttyUSB1 (ανάλογα με τον τύπο θύρας), ενώ στα Windows θα είναι κάτι σαν COM12. Εκτός εάν μια θύρα συσχετίζεται φυσικά με μια συσκευή, το πρόγραμμα κανονικά δεν θα γνωρίζει ποια θύρα να χρησιμοποιήσει. Ένας συνηθισμένος τρόπος για να επιλέξετε τη θύρα είναι να αποκτήσετε μια λίστα με τις διαθέσιμες, να την εμφανίσετε στον χρήστη και να του επιτρέψετε να επιλέξει αυτή που θέλει να χρησιμοποιήσει. Η μέθοδος Serial.list()
επιστρέφει ένα διάνυσμα από συμβολοσειρές κειμένου (String
) με τα ονόματα των θυρών που είναι διαθέσιμες στο σύστημα.
1
2
3
4
5
6
7
8
9
|
// Mostrar los puertos serie disponibles en el sistema
import processing.serial.*;
void setup()
{
noLoop(); // No iterar (no llama a draw periódicamente)
println(Serial.list());
}
|
Η θύρα που χρησιμοποιείται από προεπιλογή από τη βιβλιοθήκη Serial
είναι το πρώτο από αυτά που επιστράφηκαν με τη μέθοδο list
(ασφαλώς COM1 σε Windows ή /dev/ttyS0 en GNU / Linux). Εκτός από πολύ περιορισμένα περιβάλλοντα στα οποία το υλικό με το οποίο εργάζεστε είναι αυστηρά γνωστό (όπως ένα σύστημα σε λειτουργία kiosk), συνήθως δεν παραλείπεται και η θύρα προορισμού υποδεικνύεται ρητά.
Το παραπάνω στιγμιότυπο οθόνης δείχνει την έξοδο ενός συστήματος GNU / Linux που διαθέτει τέσσερις σειριακές θύρες RS-232 (ttyS0 a ttyS3) και πέντε προσαρμογείς δύο τύπων (ttyACM0 a ttyACM1 y ttyUSB0 a ttyUSB2).
Για να έχει πρόσβαση στις σειριακές θύρες, ο χρήστης πρέπει να ανήκει στην ομάδα στην οποία τις εκχωρεί το σύστημα, κανονικά TTY o διάλεξη. Στο στιγμιότυπο οθόνης της παραπάνω εικόνας μπορείτε να δείτε ότι οι σειριακές θύρες που αναφέρονται με ls /dev/tty[ASU]* -la
ανήκουν στην ομάδα διάλεξη που έχει δικαιώματα πρόσβασης ανάγνωσης και εγγραφής σε αυτά.
Παράμετροι σειριακού πρωτοκόλλου
La ισοτιμία των σειριακών επικοινωνιών εκφράζεται σε Επεξεργασία ως χαρακτήρας (char
) που μπορεί να πάρει τις τιμές: ① N
(κανένας) για να μην ανιχνεύσετε το ισοτιμία, ② E
(ακόμη και) για να υποδείξετε ότι το bit ισοτιμίας είναι άρτιος, ③ O
(περιττός) για να υποδείξετε ότι το bit ισοτιμίας είναι περίεργο, ④ M
(σημάδι) να κάνει πάντα το bit ισοτιμίας και ⑤ S
(χώρος) να κάνει πάντα ένα το bit ισοτιμίας. Η προεπιλεγμένη τιμή, εάν δεν μεταβιβαστεί στον κατασκευαστή ως παράμετρος, είναι N
(αμαρτία ισοτιμία).
Ο αριθμός των bits δεδομένων, που είναι οκτώ από προεπιλογή, υποδεικνύει τον αριθμό των bit που συνθέτουν το καθαρό ωφέλιμο φορτίο δεδομένων (που ονομάζεται χαρακτήρας ή μερικές φορές λέξη) που μεταδίδεται σε κάθε βασική μονάδα του πλαισίου. Η παράμετρος που υποδεικνύει τον αριθμό των bit δεδομένων εκφράζεται ως ακέραιος αριθμός (int
).
Τέλος, η πέμπτη δυνατή παράμετρος υποδεικνύει τη διάρκεια του τελικού σημείου, εκφραζόμενη ως στοπ μπιτ (μπιτ στοπ), το οποίο υποδεικνύεται ως αριθμός που αναπαρίσταται στο κινητής υποδιαστολής (float
) που μπορεί να πάρει τις τιμές 1.0
(η προεπιλεγμένη τιμή εάν η παράμετρος δεν μεταβιβαστεί στον κατασκευαστή), 1.5
ή 2.0
.
Κατασκευαστές της τάξης Serial
Η ακόλουθη λίστα δείχνει τους διαφορετικούς συνδυασμούς παραμέτρων που μπορούν να περάσουν στον κατασκευαστή κλάσης Serial
:
Serial(padre)
Serial(padre,puerto)
Serial(padre,velocidad)
Serial(padre,puerto,velocidad)
Serial(padre,puerto,velocidad,paridad,bits_datos,bits_parada)
Τερματισμός σειριακών επικοινωνιών. Η μέθοδος διακοπής.
Για να αποδεσμεύσετε τη σειριακή θύρα, που έχει εκχωρηθεί κατά την προετοιμασία Serial
, και ότι άλλες εφαρμογές συστήματος μπορούν να το χρησιμοποιήσουν, οι επικοινωνίες τερματίζονται με τη μέθοδο stop
, το οποίο δεν λαμβάνει παραμέτρους.
1
2
3
4
5
6
7
8
9
10
|
import processing.serial.*;
Serial serie;
void setup()
{
noLoop(); // No iterar
serie=new Serial(this,“/dev/ttyUSB0”,9600); // Usar un puerto USB con un adaptador UART
serie.stop(); // Detiene las comunicaciones serie y libera el puerto ttyUSB0 para otros usos
}
|
Αποστολή δεδομένων μέσω της σειριακής θύρας. Η μέθοδος εγγραφής
Για αποστολή δεδομένων, η τάξη Serial
de Επεξεργασία ενσωματώνει τη μέθοδο write
με τις οποίες μπορείτε να μεταδώσετε ① συμβολοσειρές κειμένου (String
), ② byte ή ③ διανύσματα byte (byte[]
). Είναι ενδιαφέρον να το θυμόμαστε αυτό byte
en Επεξεργασία (Στο Java) αντιπροσωπεύει έναν ακέραιο μεταξύ -128 και 127 και, από προεπιλογή, οι συμβολοσειρές χρησιμοποιούν την κωδικοποίηση UTF-16.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import processing.serial.*;
Serial serie;
String texto=“Ohm”;
void setup()
{
noLoop();
serie=new Serial(this,“/dev/ttyUSB0”,9600); // Usar un puerto USB con un adaptador UART
serie.write(texto); // Envía el texto “Ohm”
serie.write(10); // Envía un fin de línea \n que corresponde con el ASCII 10
serie.write(200); // Envía el valor -56 ¡Es un byte, va de -128 a 127! (200-256=-56)
serie.stop(); // Detiene las comunicaciones serie y libera el puerto ttyUSB0 para otros usos
}
|
Ανάγνωση δεδομένων από σειριακή θύρα
Για να μπορεί το πρόγραμμα να εκτελεί άλλες εργασίες κατά τη λήψη δεδομένων μέσω της σειριακής θύρας, είναι συνηθισμένο να αποθηκεύεται σε α ρυθμιστικό τα δεδομένα που φτάνουν και διαβάστε τα όταν χρειάζεται. Αν και συνήθως δεν είναι πολύ αποτελεσματικό, μπορείτε να σταματήσετε την εφαρμογή για να φορτώσει όλα τα διαθέσιμα δεδομένα. Ωστόσο, το πιο συνηθισμένο πράγμα θα είναι να διαβάζετε τις πληροφορίες καθώς φτάνουν, είτε σε κάθε επανάληψη του draw
, όταν μια συγκεκριμένη ποσότητα είναι διαθέσιμη ή έχει ληφθεί ειδικός κωδικός.
Ποσότητα δεδομένων που είναι διαθέσιμα στο buffer. Η διαθέσιμη μέθοδος
Για να μάθετε αν έχουν φτάσει τα δεδομένα ρυθμιστικό σειρά, η μέθοδος available
επιστρέφει τον αριθμό των byte που έχουν ήδη αποθηκευτεί σε αυτό ρυθμιστικό. Και στις δύο περιπτώσεις, οι λειτουργίες ανάγνωσης μπορούν να επιστρέψουν μια ειδική τιμή (π.χ -1
o null
) όταν προσπαθείτε να φορτώσετε δεδομένα από ρυθμιστικό σειρά όταν είναι άδεια.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import processing.serial.*;
Serial serie;
void setup()
{
frameRate(1); // Llama a draw una vez por segundo
serie=new Serial(this,“/dev/ttyUSB0”,9600);
}
void draw()
{
print(“Hay “);
print(serie.available());
println(” bytes en el buffer serie”);
}
|
Φορτώστε ένα byte τη φορά. Η μέθοδος ανάγνωσης
Οι κύριες μέθοδοι της τάξης Serial
που χρησιμεύουν για την ανάγνωση των πληροφοριών που λαμβάνονται από μια σειριακή θύρα είναι αυτές του τύπου read
» που διαφέρουν μεταξύ τους, κυρίως, από το είδος των δεδομένων στα οποία παραδίδουν τις πληροφορίες που ελήφθησαν.
read
χρησιμοποιείται για την παράδοση των byte που λαμβάνονται από τη σειριακή θύρα ως τιμή μεταξύ 0 και 255. Ως τύπος δεδομένων byte
de Επεξεργασία αντιπροσωπεύει το εύρος μεταξύ -128 και 127 και όχι μεταξύ 0 και 255, είναι απαραίτητο να χρησιμοποιήσετε ένα int
προκειμένου να αντιπροσωπεύει το εύρος που επιστρέφεται από read
. Αν προσπαθήσετε να διαβάσετε με read
και ρυθμιστικό Η συμβολοσειρά είναι κενή, επιστρέφει τιμή -1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import processing.serial.*;
Serial serie;
void setup()
{
frameRate(10); // Llama a draw 10 veces por segundo
serie=new Serial(this,“/dev/ttyUSB0”,9600);
}
void draw()
{
if(serie.available()>0)
{
println(serie.read());
}
}
|
Διαβάστε χαρακτήρες από τη σειριακή θύρα. Η μέθοδος readChar
Η μέθοδος readChar
είναι παρόμοια με read
αλλά επιστρέφει μια τιμή σε μορφή char
αντί για int
. Όπως εσωτερικά, το char
en Επεξεργασία (Στο Java) αποθηκεύονται με δύο byte, την τιμή που επιλέγεται να επιστρέφεται κατά την ανάγνωση readChar
ένα ρυθμιστικό κενή σειρά είναι 0xFFFF
o -1
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import processing.serial.*;
Serial serie;
void setup()
{
frameRate(10);
serie=new Serial(this,“/dev/ttyUSB0”,9600);
}
void draw()
{
if(serie.available()>0)
{
print(serie.readChar());
}
}
|
Φορτώστε μια συμβολοσειρά κειμένου. Οι μέθοδοι readString και readStringUntil.
Η μέθοδος readString
επιστρέφει ένα αντικείμενο String
που σχηματίζεται από όλα τα δεδομένα που είναι διαθέσιμα στο ρυθμιστικό σειρά κατά τη στιγμή της διαβούλευσης.
Η μέθοδος readString
δημιουργεί τη συμβολοσειρά κειμένου υποθέτοντας ότι τα byte που λαμβάνονται από τη σειριακή θύρα είναι στη μορφή ASCII Επομένως, αυτή η μέθοδος ανάγνωσης δεν μπορεί να χρησιμοποιηθεί για άλλες κωδικοποιήσεις.
Αν πρόκειται για την ανάγνωση του ρυθμιστικό σειρά με readString
όταν είναι κενό, η τιμή επιστροφής είναι null
.
Η μέθοδος readStringUntil
προσθήκη σε readString
τη δυνατότητα επιστροφής πληροφοριών που έχουν φορτωθεί στο ρυθμιστικό σειρά που τη χωρίζει με έναν ειδικό χαρακτήρα (κωδικό) που μεταβιβάζεται ως παράμετρος. Αυτός ο τρόπος ανάγνωσης των πληροφοριών που λαμβάνουμε μας επιτρέπει να διακρίνουμε τόσο διαχωριστές όσο και τερματιστές που βοηθούν στην ερμηνεία των πληροφοριών που λαμβάνονται.
Η μέθοδος readStringUntil
φέρε πίσω null
όταν στο ρυθμιστικό Η σειρά δεν βρίσκει τον κώδικα που καθορίζεται στο όρισμα που της διαβιβάστηκε (ένα byte).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import processing.serial.*;
Serial serie;
String mensaje;
void setup()
{
frameRate(5);
serie=new Serial(this,“/dev/ttyUSB0”,9600);
}
void draw()
{
if(serie.available()>1)
{
mensaje=serie.readStringUntil(9); // Lee los datos del buffer hasta encontrar un tabulador
if(mensaje!=null) // Si la respuesta no es null ya ha llegado el tabulador y el mensaje está completo
{
println(“Mensaje recibido: “+mensaje); // Mostrar el mensaje si ha llegado completo
}
}
}
|
Στον παρακάτω κώδικα για Arduino στέλνει τρία μηνύματα μέσω της σειριακής θύρας. Τα δύο πρώτα τελειώνουν σε μια καρτέλα, επομένως θα εμφανιστούν στην κονσόλα. Επεξεργασία, ενώ το τρίτο, αν και θα σταλεί μέσω της σειριακής θύρας, δεν θα διαβάζεται με readStringUntil(9)
αφού δεν τελειώνει σε καρτέλα (με κωδικό ASCII 9).
1
2
3
4
5
6
7
8
9
10
11
12
|
void setup()
{
Serial.begin(9600);
while(!Serial);
Serial.print(“Primer mensaje\t”);
Serial.print(“Segundo mensaje\t”);
Serial.print(“Tercer mensaje”); // Este mensaje no llega porque no termina en tabulador
}
void loop()
{
}
|
Ανάγνωση μπλοκ δεδομένων. Οι μέθοδοι readBytes και readBytesUntil.
Οι μέθοδοι που φαίνονται παραπάνω χρησιμοποιούνται για την ανάγνωση δεδομένων με συγκεκριμένες μορφές, για την ανάγνωση μπλοκ ακατέργαστων δεδομένων ή με μορφή που δεν προβλέπεται στο Επεξεργασία χρησιμοποιούνται μέθοδοι readBytes
y readBytesUntil
Η μέθοδος readBytes
προσπαθήστε να διαβάσετε τα δεδομένα που είναι διαθέσιμα στο ρυθμιστικό σειρά. Εάν δεν μεταβιβαστεί καμία παράμετρος στη μέθοδο readBytes
όλα τα διαθέσιμα δεδομένα διαβάζονται και επιστρέφονται σε ένα διάνυσμα (byte[]
). Εάν ένας ακέραιος μεταβιβαστεί ως παράμετρος, διαβάζεται το μέγιστο από τον αριθμό των byte που υποδεικνύεται από αυτόν τον αριθμό και επιστρέφονται επίσης ως διάνυσμα.
Υπάρχει ένας τρίτος τρόπος χρήσης readBytes
, πιο αποτελεσματικό, το οποίο παίρνει ως όρισμα ένα διάνυσμα byte στο οποίο τα περιεχόμενα του ρυθμιστικό σειρά. Αυτός ο τρόπος χρήσης readBytes
επιστρέφει έναν ακέραιο αριθμό (int
) που αντιπροσωπεύει τον αριθμό των byte που έχουν διαβαστεί.
Η μέθοδος readBytesUntil
λειτουργεί με παρόμοιο τρόπο αλλά περιλαμβάνει μια πρώτη παράμετρο που αντιπροσωπεύει την τιμή του byte που, αν βρεθεί στο ρυθμιστικό, θα υποδηλώνει το τέλος της ανάγνωσης. Σε αυτή τη μέθοδο, η παράμετρος που καθορίζει τον μέγιστο αριθμό bytes που θα διαβαστούν δεν έχει νόημα αφού η ποσότητα θα καθοριστεί από τον ειδικό κωδικό.
Για να ελέγξετε τη λειτουργία της μεθόδου readBytes
Ας υποθέσουμε τον παρακάτω κώδικα για Arduino που στέλνει ένα κείμενο μέσω της σειριακής θύρας.
1
2
3
4
5
6
7
8
9
10
|
void setup()
{
Serial.begin(9600);
while(!Serial);
Serial.println(“En Viena hay diez muchachas, un hombro donde solloza la muerte y un bosque de palomas disecadas. Hay un fragmento de la mañana en el museo de la escarcha. Hay un salón con mil ventanas.”);
}
void loop()
{
}
|
Το παρακάτω παράδειγμα προγράμματος για Επεξεργασία διαβάζει κείμενο από τη σειριακή θύρα σε μπλοκ 32 byte (TOTAL_BYTES). Για να επαληθεύσει ότι λειτουργεί, το εμφανίζει μέσω της κονσόλας ως χαρακτήρες, αναγκάζοντας τον τύπο των byte που λαμβάνονται σε char
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import processing.serial.*;
Serial serie;
byte bloque_datos[];
static byte TOTAL_BYTES=32;
void setup()
{
frameRate(10);
serie=new Serial(this,“/dev/ttyUSB0”,9600);
bloque_datos=new byte[TOTAL_BYTES];
}
void draw()
{
if(serie.available()>0)
{
bloque_datos=serie.readBytes(TOTAL_BYTES);
if(bloque_datos!=null)
{
for(byte numero_byte=0;numero_byte<bloque_datos.length;numero_byte++)
{
print((char)bloque_datos[numero_byte]);
}
}
}
}
|
Στο παρακάτω στιγμιότυπο οθόνης μπορείτε να δείτε πώς εμφανίζονται στην κονσόλα Επεξεργασία τα δεδομένα που έχουν φορτωθεί σε μπλοκ των (μέγιστο) 32 byte (TOTAL_BYTES) κάθε φορά. Υπάρχει όμως ένα πρόβλημα για το οποίο έχει ήδη συζητηθεί: Arduino έχει στείλει τους στίχους του Φεντερίκο Γκαρθία Λόρκα του παραδείγματος κωδικοποιημένο ως κείμενο σε μορφή UTF-8, το οποίο δεν είναι αυτό που χρησιμοποιείται Επεξεργασία (Java), τι προτιμάτε UTF-16 άρα όσοι δεν αντιστοιχούν στον βαθμό του ASCII εκτυπώσιμες ερμηνεύονται εσφαλμένα.
Για να λυθεί αυτό το πρόβλημα, τα σύνολα χαρακτήρων μπορούν να φορτωθούν (charset) και ορίστε ένα νέο αντικείμενο String
αναγκάζοντάς το να αναπαρασταθεί με κωδικοποίηση UTF-8 όπως φαίνεται στο παρακάτω παράδειγμα κώδικα.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
import processing.serial.*;
import static java.nio.charset.StandardCharsets.*;
Serial serie;
byte bloque_datos[];
static byte TOTAL_BYTES=32;
void setup()
{
frameRate(10);
serie=new Serial(this,“/dev/ttyUSB0”,9600);
bloque_datos=new byte[TOTAL_BYTES];
}
void draw()
{
if(serie.available()>0)
{
bloque_datos=serie.readBytes(TOTAL_BYTES);
if(bloque_datos!=null)
{
print(new String(bloque_datos,UTF_8));
}
}
}
|
Διαβάστε τα πιο πρόσφατα δεδομένα που ελήφθησαν. Η τελευταία και η τελευταία μέθοδος Char.
Ενώ οι υπόλοιπες μέθοδοι ανάγνωσης (ο «τύπος read
») φορτώνουν τις πληροφορίες του ρυθμιστικό σειρά με την ίδια σειρά που έφτασε (FIFO), με αυτές τις δύο μεθόδους το τελευταίο byte που έφτασε στο ρυθμιστικό σειρά. Η μέθοδος last
επιστρέφει την τιμή του τελευταίου byte ως a int
y lastChar
επιστρέφει την τιμή ως α char
.
Σειριακή διαχείριση buffer
Αν και οι μέθοδοι που έχουν δει μέχρι τώρα είναι απόλυτα λειτουργικές, δεν αντιπροσωπεύουν πάντα τον καλύτερο τρόπο εκμετάλλευσης της πρόσβασης στη σειριακή θύρα. Για να φορτώσουν τα δεδομένα, πρέπει να ελέγχουν περιοδικά την κατάσταση του ρυθμιστικό σειρά και διαβάστε τα διαθέσιμα δεδομένα σε ένα επαναλαμβανόμενο μέρος του κώδικα. Ένας γενικά πιο αποτελεσματικός τρόπος είναι να διαβάζετε τα δεδομένα μόνο όταν γνωρίζετε ότι είναι διαθέσιμα.
Διαβάστε τη σειριακή θύρα κατά τη λήψη δεδομένων. Το σειριακό γεγονός.
Για πρόσβαση στο ρυθμιστικό κατά τη λήψη των δεδομένων, το σειριακό συμβάν μπορεί να αξιοποιηθεί διαχειρίζοντάς το μέσω του ορισμού της μεθόδου serialEvent
. Αυτή η μέθοδος χρησιμοποιεί τη σειριακή θύρα που την εκκινεί ως όρισμα.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import processing.serial.*;
Serial serie;
void setup()
{
serie=new Serial(this,“/dev/ttyUSB0”,9600);
}
void draw()
{
}
void serialEvent(Serial comunicaciones)
{
print(comunicaciones.readChar());
}
|
Μέγεθος του σειριακού buffer. Η μέθοδος buffer.
Εάν γνωρίζετε τον αριθμό των byte που συνθέτουν ένα μπλοκ χρήσιμων δεδομένων, μπορείτε να βελτιστοποιήσετε περαιτέρω αυτό το στυλ ανάγνωσης των δεδομένων. ρυθμιστικό σειρά μέσω serialEvent
. Η μέθοδος buffer
σας επιτρέπει να ορίσετε τον αριθμό των byte που θα αποθηκευτούν στο ρυθμιστικό πριν από την έναρξη μιας Σειριακής εκδήλωσης. Η μέθοδος αναμένει ως παράμετρο έναν ακέραιο που αντιπροσωπεύει τον αριθμό των byte.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import processing.serial.*;
Serial serie;
void setup()
{
//noLoop();
serie=new Serial(this,“/dev/ttyUSB0”,9600);
serie.buffer(32); // Esperar a recibir 32 bytes antes de lanzar el evento Serial
}
void draw()
{
}
void serialEvent(Serial comunicaciones)
{
while(comunicaciones.available()>0)
{
print(comunicaciones.readChar());
}
}
|
Γεμίστε το buffer μέχρι να ληφθεί μια τιμή. Η μέθοδος bufferUntil.
Αντί να ορίσετε την κλήση μεθόδου serialEvent
για μια ποσότητα δεδομένων στο ρυθμιστικό, με τη μέθοδο bufferUntil
μπορείτε να ρυθμίσετε τις παραμέτρους για αποθήκευση δεδομένων μέχρι να φτάσει μια ειδική τιμή και στη συνέχεια να αυξήσετε το Σειριακό συμβάν. Η παράμετρος που μεταβιβάστηκε σε αυτή τη μέθοδο είναι α int
που αντιπροσωπεύει την τιμή που παράγεται από την κλήση προς serialEvent
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import processing.serial.*;
Serial serie;
void setup()
{
serie=new Serial(this,“/dev/ttyUSB0”,9600);
serie.bufferUntil(9); // Espera a recibir un tabulador (ASCII 9) antes de llamar a serialEvent
}
void draw()
{
}
void serialEvent(Serial comunicaciones)
{
println(comunicaciones.readString()); // Imprime en una línea diferente cada valor separado originalmente por tabuladores
}
|
Διαγράψτε τα δεδομένα που είναι αποθηκευμένα στο buffer. Η ξεκάθαρη μέθοδος.
με τη μέθοδο clear
Μπορείτε να διαγράψετε τα δεδομένα που βρίσκονται αυτήν τη στιγμή στο ρυθμιστικό. Αυτή η μέθοδος μπορεί να χρησιμοποιηθεί, για παράδειγμα, για να ξεκινήσει μια νέα συνεδρία λήψης δεδομένων αγνοώντας τα δεδομένα που απομένουν από την προηγούμενη.
Τυπική εφαρμογή επεξεργασίας για ανάγνωση δεδομένων μέσω της σειριακής θύρας
Τέλος, είναι βολικό να ανακεφαλαιωθούν οι λειτουργίες του αντικειμένου Serial
de Επεξεργασία που χρησιμοποιούνται πιο συχνά, περνώντας από ένα τυπικό παράδειγμα λήψης δεδομένων μέσω της σειριακής θύρας για να σχεδιάσετε ένα γράφημα με αυτά, σε αυτήν την περίπτωση στοιβαγμένων περιοχών.
Εισαγάγετε τη σειριακή βιβλιοθήκη
1
|
import processing.serial.*;
|
Προσδιορισμός πρωτοκόλλου δεδομένων (διαχωριστές)
1
2
|
static final String SEPARADOR=“\t”; // Los datos de cada sensor se separan con un tabulador
static final char TERMINADOR=10; // Cada grupo de datos se termina con un código ASCII 10 → Nueva línea → \n
|
Προσδιορίστε το αντικείμενο της κλάσης Serial
1
|
Serial conexion_sensores;
|
Δημιουργήστε το αντικείμενο κλάσης Serial ορίζοντας τη σειριακή θύρα που χρησιμοποιείται
1
|
conexion_sensores=new Serial(this,“/dev/ttyUSB1”,9600);
|
Διαμόρφωση του buffer σειριακής θύρας
1
|
conexion_sensores.bufferUntil(TERMINADOR);
|
Εφαρμόστε έναν χειριστή για το Σειριακό συμβάν
1
|
void serialEvent(Serial serie)
|
Ανάγνωση σειριακής προσωρινής μνήμης
1
|
String[] texto_valor=serie.readString().split(SEPARADOR);
|
Προετοιμάστε τα δεδομένα που λαμβάνονται
1
2
3
4
5
|
float[] valor=new float[texto_valor.length];
for(int numero_valor=0;numero_valor<texto_valor.length;numero_valor++)
{
valor[numero_valor]=parseFloat(texto_valor[numero_valor]);
}
|
Τερματισμός σειριακών επικοινωνιών
1
2
|
conexion_sensores.clear();
conexion_sensores.stop();
|
Το παράδειγμα κώδικα παρακάτω απεικονίζει αυτήν τη σύνοψη με μια λειτουργική (αν και πολύ απλή) εφαρμογή που δημιουργεί ένα γράφημα περιοχής με τις τιμές που λαμβάνονται μέσω της σειριακής θύρας, κάτι παρόμοιο με αυτό που δείχνει το παρακάτω κινούμενο σχέδιο.
Για να μην χαθείτε στο υπόλοιπο πρόγραμμα και εστιάστε την προσοχή σας σε σειριακές επικοινωνίες με Επεξεργασία, επισημαίνονται οι γραμμές κώδικα που αντιστοιχούν στις προηγούμενες λειτουργίες.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
import processing.serial.*;
static final byte ROJO=0,VERDE=1,AZUL=2,OPACIDAD=3;
static final int CANTIDAD_SENSORES=3;
static final int CANTIDAD_VALORES=20;
static final String NOMBRE_FONDO=“fondo.png”;
static final int[][] COLOR_LINEA={{0x44,0x88,0xCC,0xFF},{0xFF,0xAA,0x00,0xFF},{0xCC,0x44,0xAA,0xFF}};
static final int[][] COLOR_AREA={{0x44,0x88,0xCC,0x88},{0xFF,0xAA,0x00,0x88},{0xCC,0x44,0xAA,0x88}};
static final int[] COLOR_FONDO={0xFF,0xFF,0XFF};
static final float GROSOR_LINEA=2.0;
static final float DIAMETRO_MARCA=8.0;
static final float VALOR_MINIMO=0.0; // Valor mínimo de la suma de todos los componentes
static final float VALOR_MAXIMO=100.0; // Valor máximo de la suma de valores
static final String SEPARADOR=“\t”; // Los datos de cada sensor se separan con un tabulador
static final char TERMINADOR=10; // Cada grupo de datos se termina con un código ASCII 10 → Nueva línea → \n
Serial conexion_sensores;
float[][] valor_sensor=new float[CANTIDAD_SENSORES][CANTIDAD_VALORES];
float coeficiente_valor;
float[] vertical_area=new float[CANTIDAD_VALORES];
float[] vertical_marca=new float[CANTIDAD_VALORES];
PImage fondo;
void setup()
{
size(792,396,P2D); // El tamaño de la ventana no se puede establecer con variables en setup (usar settings)
surface.setResizable(false);
surface.setTitle(“consumo relativo comparado”);
noLoop();
smooth(4);
conexion_sensores=new Serial(this,“/dev/ttyUSB1”,9600);
conexion_sensores.bufferUntil(TERMINADOR);
for(int numero_sensor=0;numero_sensor<CANTIDAD_SENSORES;numero_sensor++)
{
for(int numero_valor=0;numero_valor<CANTIDAD_VALORES;numero_valor++)
{
valor_sensor[numero_sensor][numero_valor]=0.0;
}
}
fondo=loadImage(NOMBRE_FONDO);
coeficiente_valor=height/(VALOR_MAXIMO–VALOR_MINIMO);
//strokeCap(ROUND); // El modo del final de líneas por defecto es redondeado
//ellipseMode(CENTER); // Por defecto el modo de elipse es desde el centro
if(DIAMETRO_MARCA>GROSOR_LINEA) // Si la marca no es visible hay que configurar el tipo de esquina
{
strokeJoin(ROUND); // El modo de esquina por defecto es en ángulo
}
}
void draw()
{
for(int numero_valor=0;numero_valor<valor_sensor[0].length;numero_valor++)
{
vertical_area[numero_valor]=height;
for(int numero_sensor=0;numero_sensor<valor_sensor.length;numero_sensor++)
{
vertical_area[numero_valor]-=(valor_sensor[numero_sensor][numero_valor]–VALOR_MINIMO)*coeficiente_valor;
}
vertical_marca[numero_valor]=vertical_area[numero_valor];
}
if(fondo==null)
{
background(COLOR_FONDO[ROJO],COLOR_FONDO[VERDE],COLOR_FONDO[AZUL]);
}
else
{
image(fondo,0,0);
}
strokeWeight(GROSOR_LINEA);
for(int numero_sensor=0;numero_sensor<valor_sensor.length;numero_sensor++)
{
stroke
(
COLOR_LINEA[numero_sensor][ROJO],
COLOR_LINEA[numero_sensor][VERDE],
COLOR_LINEA[numero_sensor][AZUL],
COLOR_LINEA[numero_sensor][OPACIDAD]
);
fill
(
COLOR_AREA[numero_sensor][ROJO],
COLOR_AREA[numero_sensor][VERDE],
COLOR_AREA[numero_sensor][AZUL],
COLOR_AREA[numero_sensor][OPACIDAD]
);
beginShape();
for(int numero_valor=valor_sensor[numero_sensor].length–1;numero_valor>=0;numero_valor—)
{
vertex(numero_valor*width/(valor_sensor[numero_sensor].length–1),vertical_area[numero_valor]);
}
for(int numero_valor=0;numero_valor<valor_sensor[numero_sensor].length;numero_valor++)
{
vertical_area[numero_valor]+=(valor_sensor[numero_sensor][numero_valor]–VALOR_MINIMO)*coeficiente_valor;
vertex(numero_valor*width/(valor_sensor[numero_sensor].length–1),vertical_area[numero_valor]);
}
endShape(CLOSE);
if(DIAMETRO_MARCA>0)
{
noStroke();
fill
(
COLOR_LINEA[numero_sensor][ROJO],
COLOR_LINEA[numero_sensor][VERDE],
COLOR_LINEA[numero_sensor][AZUL],
COLOR_LINEA[numero_sensor][OPACIDAD]
);
for(int numero_valor=0;numero_valor<valor_sensor[numero_sensor].length;numero_valor++)
{
ellipse
(
numero_valor*width/(valor_sensor[numero_sensor].length–1),
vertical_marca[numero_valor],
DIAMETRO_MARCA,
DIAMETRO_MARCA
);
vertical_marca[numero_valor]=vertical_area[numero_valor];
}
}
}
}
void stop() // Al terminar un Applet. No hay garantía de que se ejecute y, como estas operaciones se realizan al terminar, en realidad no son necesarias y solo se incluyen para recordar el uso de clear y stop
{
conexion_sensores.clear(); // Solo para ilustrar la posibilidad de borrar los datos que queden en el buffer
conexion_sensores.stop(); // Solo para ilustrar la posibilidad de terminar las comunicaciones serie y liberar el puerto que se está usando
}
void serialEvent(Serial serie)
{
String[] texto_valor=serie.readString().split(SEPARADOR);
float[] valor=new float[texto_valor.length];
for(int numero_valor=0;numero_valor<texto_valor.length;numero_valor++)
{
valor[numero_valor]=parseFloat(texto_valor[numero_valor]);
}
nuevo_valor(valor_sensor,valor);
redraw();
}
void nuevo_valor(float[][] valor_sensor, float[] valor)
{
for(int numero_sensor=0;numero_sensor<valor_sensor.length;numero_sensor++)
{
for(int numero_valor=1;numero_valor<valor_sensor[0].length;numero_valor++)
{
valor_sensor[numero_sensor][numero_valor–1]=valor_sensor[numero_sensor][numero_valor];
}
valor_sensor[numero_sensor][valor_sensor[0].length–1]=valor[numero_sensor];
}
}
|
Δημοσίευση σχολίου