תקשורת טורית עם עיבוד
הכיתה הסדרתית
הפעולות לשימוש בתקשורת טורית תהליך מוגדרים בכיתה Serial
.הפעולה הראשונה שיש לבצע כדי להשתמש בהם בתוכנית (סקיצה) יהיה לשלב אותו בקוד עם import processing.serial.*;
.
מעמד Serial
יש לו חמישה בנאים שונים בהתאם לפרמטרים המצוינים. הפרמטר היחיד הנדרש הוא אובייקט האב (הורה) שבדרך כלל מתאימה לתוכנית הראשית (נגיד, חלון התוכנית) של הכיתה PApplet
. כרגיל ההורה יהיה התוכנית הנכתבת (ה סקיצה הנוכחי), הערך של פרמטר חובה ראשון זה יהיה this
.
חמשת הפרמטרים האחרים שניתן להעביר לבנאי הם ① המהירות, ② שם היציאה הטורית ③ ה שִׁוּוּי בשימוש בפרוטוקול, ④ סיביות הנתונים ו⑤ סיביות העצירה. הפרמטרים המועברים בתדירות הגבוהה ביותר, בנוסף לאובייקט האב הנדרש, הם שם היציאה והמהירות.
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 גנו / לינוקס). למעט בהקשרים מוגבלים מאוד שבהם החומרה שאיתה עובדים ידועה לחלוטין (כגון מערכת במצב קיוסק), היא בדרך כלל לא מושמטת ויציאת היעד מצוינת במפורש.
צילום המסך למעלה מציג את הפלט של מערכת גנו / לינוקס בעל ארבע יציאות טוריות RS-232 (ttyS0 a ttyS3) וחמישה מתאמים משני סוגים (ttyACM0 a ttyACM1 y ttyUSB0 a ttyUSB2).
על מנת לגשת ליציאות הטוריות, המשתמש חייב להשתייך לקבוצה שאליה המערכת מקצה אותן, בדרך כלל tty o חיוג חיוג. בצילום המסך של התמונה למעלה אתה יכול לראות שהיציאות הטוריות הרשומות עם ls /dev/tty[ASU]* -la
שייכים לקבוצה חיוג חיוג שיש להם הרשאות גישה לקריאה וכתיבה.
פרמטרים של פרוטוקול סדרתי
La שִׁוּוּי של תקשורת טורית בא לידי ביטוי ב תהליך בתור דמות (char
) שיכול לקחת את הערכים: ① N
(אף לא אחד) כדי לא לזהות את שִׁוּוּי, ② E
(גם) כדי לציין כי קצת זוגיות שווה, ③ O
(מוזר) כדי לציין כי קצת זוגיות הוא מוזר, ④ M
(סימן) כדי להפוך תמיד לאפס את קצת זוגיות ו- ⑤ S
(שטח) לעשות תמיד אחד את קצת זוגיות. ערך ברירת המחדל, אם לא מועבר לבנאי כפרמטר, הוא N
(חטא שִׁוּוּי).
מספר פיסות מידע, שהוא שמונה כברירת מחדל, מציין את מספר הביטים המרכיבים את מטען הנתונים נטו (הנקרא תו או לפעמים מילה) שמועבר בכל יחידה בסיסית של המסגרת. הפרמטר המציין את מספר סיביות הנתונים מבוטא כמספר שלם (int
).
לבסוף, הפרמטר החמישי האפשרי מציין את משך הציון הסופי, מבוטא כ פיסות לעצור (פיסות לעצור), אשר מצוין כמספר המיוצג ב נקודה צפה (float
) שיכול לקחת את הערכים 1.0
(ערך ברירת המחדל אם הפרמטר לא מועבר לבנאי), 1.5
, או 2.0
.
בונים של הכיתה הסדרתית
הרשימה הבאה מציגה את השילובים השונים של פרמטרים שניתן להעביר לבנאי המחלקה 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
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
}
|
קרא נתונים מיציאה טורית
כדי שהתוכנית תוכל לבצע משימות אחרות בזמן שהנתונים מתקבלים דרך היציאה הטורית, נהוג לאחסן ב-a חיץ את הנתונים שמגיעים ולקרוא אותם במידת הצורך. למרות שבדרך כלל לא מאוד יעיל, אתה יכול לעצור את היישום כדי לטעון את כל הנתונים הזמינים; עם זאת, הדבר הנפוץ ביותר יהיה לקרוא את המידע כשהוא מגיע, בכל איטרציה של 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
ו - חיץ המחרוזת ריקה, מחזירה ערך -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) מאוחסנים עם שני בתים, הערך שנבחר להחזיר בעת קריאה 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
כאשר ב חיץ סדרה לא מוצאת את הקוד שצוין בארגומנט המועבר אליו (בייט אחד).
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[]
). אם מספר שלם מועבר כפרמטר, מקסימום מספר הבתים המצוין במספר זה נקרא והם מוחזרים גם כווקטור.
יש דרך שלישית לשימוש readBytes
, יעיל יותר, שלוקח כארגומנט וקטור בתים שבו התוכן של ה- חיץ סִדרָה. אופן השימוש הזה readBytes
מחזיר מספר שלם (int
) המייצג את מספר הבתים שנקראו.
השיטה readBytesUntil
עובד בצורה דומה אך כולל פרמטר ראשון המייצג את הערך של ה-byte שאם נמצא ב- חיץ, יציין את סיום הקריאה. בשיטה זו, הפרמטר הקובע את המספר המרבי של בתים שייקראו אינו הגיוני שכן הכמות תיקבע על ידי הקוד המיוחד.
לבדיקת פעולת השיטה 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 בתים (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) בכל פעם. אבל יש בעיה שכבר דיברו עליה: Arduino שולח את הפסוקים של פדריקו גרסיה לורקה של הדוגמה מקודדת כטקסט בפורמט UTF-8, שאינו זה שבו נעשה שימוש תהליך (Java), מה אתה מעדיף Utf-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));
}
}
}
|
קרא את הנתונים האחרונים שהתקבלו. שיטות אחרון ו-lastChar.
בעוד שאר שיטות הקריאה ("סוג read
») הם טוענים את המידע של חיץ סדרה באותו סדר שהגיעה (FIFO), בשתי השיטות הללו ה-byte האחרון שהגיע ל- חיץ סִדרָה. השיטה last
מחזירה את הערך של הבית האחרון בתור a int
y lastChar
מחזירה את הערך בתור a char
.
ניהול מאגר טורי
למרות שהשיטות שנראו עד כה פונקציונליות לחלוטין, הן לא תמיד מייצגות את הדרך הטובה ביותר לנצל את הגישה ליציאה הטורית. כדי לטעון את הנתונים, הם צריכים לבדוק מעת לעת את המצב של חיץ סדרה וקרא את הנתונים הזמינים בחלק חוזר של הקוד. בדרך כלל, דרך יעילה יותר היא לקרוא את הנתונים רק כאשר אתה יודע שהם זמינים.
קרא את היציאה הטורית כאשר הנתונים מתקבלים. האירוע הסדרתי.
כדי לגשת ל חיץ סדרתי כאשר הנתונים מתקבלים, ניתן לנצל את האירוע הסדרתי על ידי ניהולו באמצעות הגדרת השיטה 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
אתה יכול להגדיר לאחסן נתונים עד שמגיע ערך מיוחד ולאחר מכן להעלות את האירוע הסדרתי. הפרמטר המועבר לשיטה זו הוא א 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
|
קבע את האובייקט של המחלקה Serial
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];
}
}
|
לפרסם תגובה