การสื่อสารแบบอนุกรมพร้อมการประมวลผล
คลาสอนุกรม
การดำเนินการเพื่อใช้การสื่อสารแบบอนุกรมค่ะ การประมวลผล ถูกกำหนดไว้ในชั้นเรียน Serial
. การดำเนินการครั้งแรกเพื่อใช้งานในโปรแกรม (ร่าง) จะต้องรวมเข้ากับโค้ดด้วย import processing.serial.*;
.
ระดับ Serial
มีตัวสร้างที่แตกต่างกันห้าตัว ขึ้นอยู่กับพารามิเตอร์ที่ระบุ พารามิเตอร์ที่จำเป็นเพียงอย่างเดียวคือวัตถุหลัก (ผู้ปกครอง) ซึ่งโดยปกติจะสอดคล้องกับโปรแกรมหลัก (เช่น หน้าต่างโปรแกรม) ของชั้นเรียน PApplet
. ตามปกติแล้ว parent จะเป็นโปรแกรมที่กำลังเขียนอยู่ (ไฟล์ ร่าง ปัจจุบัน) ค่าของพารามิเตอร์บังคับตัวแรกนี้จะเป็น this
.
พารามิเตอร์อีกห้าตัวที่สามารถส่งผ่านไปยังตัวสร้างได้คือ 1 ความเร็ว 2 ชื่อของพอร์ตอนุกรม 3 ความเท่าเทียมกัน ที่ใช้ในโปรโตคอล ④ บิตข้อมูล และ ⑤ บิตหยุด พารามิเตอร์ที่ส่งผ่านบ่อยที่สุด นอกเหนือจากออบเจ็กต์พาเรนต์ที่ต้องการแล้ว คือชื่อพอร์ตและความเร็ว
La ความเร็วการสื่อสารแบบอนุกรม เป็นจำนวนเต็ม (int
) ว่า ค่าเริ่มต้นเป็นค่า 9600 หากพารามิเตอร์นี้ไม่ถูกส่งผ่านไปยังตัวสร้าง
พอร์ตอนุกรมที่มีอยู่ วิธีการรายการ
El ชื่อพอร์ต มีรูปแบบที่ระบบกำหนดไว้ดังนี้ เช่น ลีนุกซ์ดิสทริบิวชัน มันจะเป็นอะไรแบบนั้น /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). ยกเว้นในบริบทที่จำกัดมากซึ่งฮาร์ดแวร์ที่กำลังทำงานด้วยเป็นที่รู้จักอย่างเคร่งครัด (เช่น ระบบในโหมดคีออสก์) โดยปกติจะไม่ละเว้นและพอร์ตปลายทางจะถูกระบุอย่างชัดแจ้ง
ภาพหน้าจอด้านบนแสดงผลลัพธ์ของระบบ GNU / Linux ซึ่งมีพอร์ตอนุกรมสี่พอร์ต RS-232 (ttyS0 a ttyS3) และอะแดปเตอร์ห้าตัวสองประเภท (ttyACM0 a ttyACM1 y ttyUSB0 a ttyUSB2).
ในการเข้าถึงพอร์ตอนุกรม ผู้ใช้จะต้องอยู่ในกลุ่มที่ระบบกำหนดไว้ตามปกติ TTY o Dialout. ในภาพหน้าจอด้านบนคุณจะเห็นว่ามีรายการพอร์ตอนุกรมด้วย ls /dev/tty[ASU]* -la
pertenecen อัล grupo Dialout ซึ่งมีสิทธิ์การเข้าถึงแบบอ่านและเขียน
พารามิเตอร์โปรโตคอลแบบอนุกรม
La ความเท่าเทียมกัน ของการสื่อสารแบบอนุกรม ถูกแสดงใน การประมวลผล เป็นตัวละคร (char
) ซึ่งสามารถรับค่าได้: ① N
(ไม่มี) เพื่อไม่ให้ตรวจพบ ความเท่าเทียมกัน, ② E
(แม้) เพื่อแสดงว่า ความเท่าเทียมกันบิต คือคู่, 3 O
(คี่) เพื่อแสดงว่า ความเท่าเทียมกันบิต เป็นเลขคี่ ④ M
(เครื่องหมาย) เพื่อทำให้ ความเท่าเทียมกันบิต และ ⑤ S
(ช่องว่าง) เพื่อสร้างสิ่งหนึ่งเสมอ ความเท่าเทียมกันบิต. ค่าเริ่มต้น หากไม่ส่งผ่านไปยังตัวสร้างเป็นพารามิเตอร์ จะเป็นดังนี้ N
(ปราศจาก ความเท่าเทียมกัน).
จำนวน บิตข้อมูลซึ่งเป็นแปดตามค่าเริ่มต้น ระบุจำนวนบิตที่ประกอบเป็นเพย์โหลดข้อมูลสุทธิ (เรียกว่าอักขระหรือบางครั้งเป็นคำ) ที่ถูกส่งไปในแต่ละหน่วยพื้นฐานของเฟรม พารามิเตอร์ที่ระบุจำนวนบิตข้อมูลจะแสดงเป็นจำนวนเต็ม (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
}
|
ส่งข้อมูลผ่านพอร์ตอนุกรม write.method
ในการส่งข้อมูลชั้นเรียน Serial
de การประมวลผล รวมวิธีการ write
โดยที่ 1 สตริงข้อความสามารถส่งได้ (String
), ไบต์ 2 หรือ 3 ไบต์เวกเตอร์ (byte[]
). เป็นเรื่องที่น่าสนใจที่จะจำไว้ว่า byte
en การประมวลผล (ตอน ชวา) แทนจำนวนเต็มระหว่าง -128 ถึง 127 และตามค่าเริ่มต้น สตริงจะใช้การเข้ารหัส ยูทีเอฟ-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
เมื่อมีสินค้าจำนวนหนึ่งหรือได้รับรหัสพิเศษ
จำนวนข้อมูลที่มีอยู่ในบัฟเฟอร์ วิธีการที่มีอยู่
เพื่อทราบว่าข้อมูลมาถึงแล้วหรือไม่ กันชน ซีรีส์วิธีการ available
ส่งคืนจำนวนไบต์ที่เก็บไว้ในนี้ กันชน. ไม่ว่าในกรณีใด การดำเนินการอ่านสามารถส่งคืนค่าพิเศษ (เช่น -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”);
}
|
โหลดทีละไบต์ วิธีการอ่าน
วิธีการหลักของชั้นเรียน Serial
ที่ทำหน้าที่อ่านข้อมูลที่ได้รับจากพอร์ตอนุกรมนั้นเป็นข้อมูลประเภท " read
» ซึ่งแตกต่างกันโดยหลักๆ ตามประเภทของข้อมูลที่ส่งข้อมูลที่ได้รับ
read
ใช้ในการส่งไบต์ที่ได้รับจากพอร์ตอนุกรมเป็นค่าระหว่าง 0 ถึง 255 เป็นชนิดข้อมูล byte
de การประมวลผล แสดงถึงช่วงระหว่าง -128 ถึง 127 และไม่ใช่ระหว่าง 0 ถึง 255 จำเป็นต้องใช้ int
เพื่อแสดงถึงช่วงที่ส่งกลับโดย read
. หากลองอ่านดูด้วย read
และ y กันชน สตริงว่างเปล่า ส่งกลับค่า -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 การประมวลผล (ตอน ชวา) จะถูกจัดเก็บไว้ 2 ไบต์ ซึ่งเป็นค่าที่เลือกให้ส่งคืนเมื่ออ่านด้วย 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
สร้างสตริงข้อความโดยสมมติว่าไบต์ที่ได้รับจากพอร์ตอนุกรมอยู่ในรูปแบบ ASCII ดังนั้นวิธีการอ่านนี้จึงไม่สามารถใช้กับการเข้ารหัสอื่นได้
หากเป็นเรื่องเกี่ยวกับการอ่าน กันชน ซีรีย์ด้วย readString
เมื่อว่างเปล่าค่าที่ส่งคืนจะเป็น null
.
วิธีการ readStringUntil
เพิ่ม readString
ความสามารถในการส่งคืนข้อมูลที่โหลดลงใน กันชน ซีรีส์แยกด้วยอักขระพิเศษ (รหัส) ที่ถูกส่งเป็นพารามิเตอร์ วิธีการอ่านข้อมูลที่ได้รับนี้ช่วยให้เราสามารถแยกแยะทั้งตัวคั่นและตัวยุติที่ช่วยตีความข้อมูลที่ได้รับ
วิธีการ readStringUntil
นำกลับมา null
เมื่ออยู่ใน กันชน series ไม่พบรหัสที่ระบุในอาร์กิวเมนต์ที่ส่งผ่านไป (หนึ่งไบต์)
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
}
}
}
|
ในรหัสต่อไปนี้สำหรับ แพลตฟอร์มฮาร์ดแวร์ ส่งข้อความสามข้อความผ่านพอร์ตอนุกรม สองรายการแรกสิ้นสุดในแท็บ ดังนั้นรายการเหล่านั้นจะปรากฏในคอนโซล การประมวลผลในขณะที่อันที่สามแม้จะถูกส่งผ่านพอร์ตอนุกรม แต่ก็ไม่สามารถอ่านได้ 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[]
). หากส่งจำนวนเต็มเป็นพารามิเตอร์ ระบบจะอ่านจำนวนไบต์สูงสุดที่ระบุด้วยตัวเลขนี้และส่งคืนเป็นเวกเตอร์ด้วย
มีวิธีที่สามในการใช้ readBytes
มีประสิทธิภาพมากขึ้นซึ่งใช้เป็นอาร์กิวเมนต์เวกเตอร์ไบต์ซึ่งเนื้อหาของ กันชน ชุด. วิธีใช้แบบนี้ readBytes
ส่งกลับจำนวนเต็ม (int
) ซึ่งแสดงถึงจำนวนไบต์ที่ถูกอ่าน
วิธีการ readBytesUntil
ทำงานในลักษณะเดียวกัน แต่รวมพารามิเตอร์แรกที่แสดงถึงค่าของไบต์ที่หากพบใน กันชนจะแสดงการสิ้นสุดของการอ่าน ในวิธีนี้ พารามิเตอร์ที่กำหนดจำนวนไบต์สูงสุดที่จะอ่านไม่สมเหตุสมผล เนื่องจากจำนวนจะถูกกำหนดโดยโค้ดพิเศษ
เพื่อทดสอบการทำงานของวิธีการ readBytes
สมมติว่ารหัสต่อไปนี้สำหรับ แพลตฟอร์มฮาร์ดแวร์ ซึ่งส่งข้อความผ่านพอร์ตอนุกรม
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 ไบต์ (TOTAL_BYTES). เพื่อตรวจสอบว่าใช้งานได้ ระบบจะแสดงผ่านคอนโซลเป็นอักขระ โดยบังคับประเภทไบต์ที่ได้รับ 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 ไบต์ (TOTAL_BYTES) ทุกเวลา. แต่มีปัญหาที่คุยกันไปแล้วคือ แพลตฟอร์มฮาร์ดแวร์ ได้ส่งโองการของ ลอร์กา Federico García ของตัวอย่างที่เข้ารหัสเป็นข้อความในรูปแบบ UTF-8ซึ่งไม่ใช่อันที่ใช้ การประมวลผล (ชวา) คุณชอบอะไร ยูทีเอฟ-16 ดังนั้นผู้ที่ไม่ตรงกับยศ ASCII พิมพ์ได้ถูกตีความไม่ถูกต้อง
เพื่อแก้ปัญหานี้ คุณสามารถโหลดชุดอักขระได้ (ชุดอักขระ) และกำหนดวัตถุใหม่ 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) ด้วยสองวิธีนี้ ไบต์สุดท้ายที่มาถึง กันชน ชุด. วิธีการ last
ส่งกลับค่าของไบต์สุดท้ายเป็น a int
y lastChar
ส่งคืนค่าเป็น a char
.
การจัดการบัฟเฟอร์แบบอนุกรม
แม้ว่าวิธีการที่เห็นจนถึงขณะนี้ใช้งานได้อย่างสมบูรณ์แบบ แต่ก็ไม่ได้แสดงถึงวิธีที่ดีที่สุดในการใช้ประโยชน์จากการเข้าถึงพอร์ตอนุกรมเสมอไป หากต้องการโหลดข้อมูลจะต้องตรวจสอบสถานะของข้อมูลเป็นระยะ กันชน และอ่านข้อมูลที่มีอยู่ในส่วนที่ซ้ำกันของโค้ด โดยทั่วไปวิธีที่มีประสิทธิภาพมากกว่าคือการอ่านข้อมูลเมื่อคุณรู้ว่าข้อมูลนั้นพร้อมใช้งานเท่านั้น
อ่านพอร์ตอนุกรมเมื่อได้รับข้อมูล เหตุการณ์ซีเรียล
เพื่อเข้าถึง กันชน เมื่อได้รับข้อมูลแล้ว เหตุการณ์ Serial ก็สามารถใช้ประโยชน์จากเหตุการณ์ Serial ได้โดยการจัดการผ่านคำจำกัดความของเมธอด 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());
}
|
ปรับขนาดบัฟเฟอร์อนุกรม วิธีการบัฟเฟอร์
หากคุณทราบจำนวนไบต์ที่ประกอบเป็นบล็อกข้อมูลที่เป็นประโยชน์ คุณสามารถปรับรูปแบบการอ่านข้อมูลนี้ให้เหมาะสมยิ่งขึ้นได้ กันชน ซีรีส์ผ่าน serialEvent
. วิธีการ buffer
ช่วยให้คุณสามารถกำหนดจำนวนไบต์ที่จะเก็บไว้ใน กันชน ก่อนเปิดตัวกิจกรรมซีเรียล วิธีการคาดว่าพารามิเตอร์จะเป็นจำนวนเต็มที่แสดงถึงจำนวนไบต์
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());
}
}
|
เติมบัฟเฟอร์จนกว่าจะได้รับค่า วิธีการbufferUntil
แทนที่จะตั้งค่าการเรียกเมธอด serialEvent
สำหรับปริมาณข้อมูลใน กันชนด้วยวิธีการ bufferUntil
คุณสามารถกำหนดค่าให้จัดเก็บข้อมูลได้จนกว่าค่าพิเศษจะมาถึง จากนั้นจึงเพิ่มเหตุการณ์ Serial พารามิเตอร์ที่ส่งไปยังวิธีนี้คือ a 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
}
|
ลบข้อมูลที่เก็บไว้ในบัฟเฟอร์ วิธีการที่ชัดเจน
ด้วยวิธีการ 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
|
กำหนดวัตถุของคลาสอนุกรม
1
|
Serial conexion_sensores;
|
สร้างอินสแตนซ์ของวัตถุคลาส Serial โดยการตั้งค่าพอร์ตอนุกรมที่ใช้
1
|
conexion_sensores=new Serial(this,“/dev/ttyUSB1”,9600);
|
กำหนดค่าบัฟเฟอร์พอร์ตอนุกรม
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];
}
}
|
แสดงความคิดเห็น