Comunicazioni seriali con elaborazione
La classe seriale
Le operazioni per utilizzare le comunicazioni seriali Processando sono definiti nella classe Serial
.La prima operazione da eseguire per utilizzarli in un programma (sketch) sarà quello di incorporarlo nel codice con import processing.serial.*;
.
Classe Serial
Ha cinque diversi costruttori a seconda dei parametri indicati. L'unico parametro obbligatorio è l'oggetto principale (genitore) che di solito corrisponde al programma principale (ad esempio, la finestra del programma) della classe PApplet
. Come normalmente il genitore sarà il programma in fase di scrittura (il sketch corrente), il valore di questo primo parametro obbligatorio sarà this
.
Gli altri cinque parametri che possono essere passati al costruttore sono ① la velocità, ② il nome della porta seriale ③ il parità utilizzati nel protocollo, ④ i bit di dati e ⑤ i bit di stop. I parametri passati più frequentemente, oltre all'oggetto genitore richiesto, sono il nome della porta e la velocità.
La velocità delle comunicazioni seriali è un numero intero (int
) quello il valore predefinito è 9600 se questo parametro non viene passato al costruttore.
Porte seriali disponibili. Il metodo della lista
El nome del porto ha la forma determinata dal sistema, in questo modo, ad esempio in Distribuzioni Linux sarà qualcosa del genere /dev/ttyS4 / dev / ttyACM3 o /dev/ttyUSB1 (a seconda del tipo di porta), mentre su Windows sarà qualcosa di simile COM12. A meno che una porta non sia fisicamente associata a un dispositivo, il programma normalmente non saprà quale porta utilizzare. Un modo comune per selezionare la porta è ottenere un elenco di quelle disponibili, mostrarlo all'utente e consentirgli di scegliere quella che desidera utilizzare. Il metodo Serial.list()
restituisce un vettore di stringhe di testo (String
) con i nomi delle porte disponibili sul sistema.
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());
}
|
La porta utilizzata per impostazione predefinita dalla libreria Serial
è il primo di quelli restituiti dal metodo list
(certamente COM1 su Windows o /dev/ttyS0 en GNU / Linux). Tranne che in contesti molto limitati in cui l'hardware con cui si lavora è strettamente noto (come un sistema in modalità chiosco), solitamente non viene omesso e la porta di destinazione è espressamente indicata.
Lo screenshot qui sopra mostra l'output di un sistema GNU / Linux che ha quattro porte seriali RS-232 (ttyS0 a ttyS3) e cinque adattatori di due tipi (ttyACM0 a ttyACM1 y ttyUSB0 a ttyUSB2).
Per poter accedere alle porte seriali l'utente deve appartenere normalmente al gruppo a cui il sistema le assegna tty o chiamare fuori. Nello screenshot dell'immagine sopra puoi vedere che le porte seriali elencate con ls /dev/tty[ASU]* -la
appartenere al gruppo chiamare fuori che ha permessi di accesso in lettura e scrittura su di essi.
Parametri del protocollo seriale
La parità delle comunicazioni seriali vedi expresa en Processando come personaggio (char
) che può assumere i valori: ① N
(nessuna) per non rilevare il parità, ② E
(anche) per indicare che il bit di parità è pari, ③ O
(dispari) per indicare che il bit di parità è strano, ④ M
(marchio) per fare sempre il bit di parità e ⑤ S
(spazio) per farne sempre uno il bit di parità. Il valore predefinito, se non passato al costruttore come parametro, è N
(senza parità).
Numero bit di dati, che per impostazione predefinita è otto, indica il numero di bit che compongono il carico utile dei dati netti (chiamato carattere o talvolta parola) trasmesso in ciascuna unità di base del frame. Il parametro che indica il numero di bit di dati è espresso come numero intero (int
).
Infine, il quinto parametro possibile indica la durata del voto finale, espressa come bit di arresto (bit di arresto), che è indicato come un numero rappresentato in virgola mobile (float
) che può assumere i valori 1.0
(il valore predefinito se il parametro non viene passato al costruttore), 1.5
o 2.0
.
Costruttori della classe Serial
L'elenco seguente mostra le diverse combinazioni di parametri che possono essere passati al costruttore della classe Serial
:
Serial(padre)
Serial(padre,puerto)
Serial(padre,velocidad)
Serial(padre,puerto,velocidad)
Serial(padre,puerto,velocidad,paridad,bits_datos,bits_parada)
Terminare le comunicazioni seriali. Il metodo di arresto.
Per rilasciare la porta seriale, assegnata durante l'istanziazione Serial
e che altre applicazioni di sistema possano utilizzarlo, le comunicazioni vengono interrotte con il metodo stop
, che non riceve parametri.
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
}
|
Invia dati tramite la porta seriale. Il metodo write
Per inviare i dati, la classe Serial
de Processando incorpora il metodo write
con cui è possibile trasmettere ① stringhe di testo (String
), ② byte o ③ vettori di byte (byte[]
). È interessante ricordarlo byte
en Processando (At Java) rappresenta un numero intero compreso tra -128 e 127 e, per impostazione predefinita, le stringhe utilizzano la codifica UTF all'16 ottobre.
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
}
|
Leggere i dati dalla porta seriale
Affinché il programma possa eseguire altre attività mentre i dati vengono ricevuti tramite la porta seriale, è normale archiviarli in un file bufferizzare i dati che arrivano e leggerli quando opportuno. Sebbene di solito non sia molto efficiente, puoi interrompere l'applicazione per caricare tutti i dati disponibili; Tuttavia, la cosa più comune sarà leggere le informazioni man mano che arrivano, in ciascuna iterazione draw
, quando è disponibile una determinata quantità o è stato ricevuto un codice speciale.
Quantità di dati disponibili nel buffer. Il metodo disponibile
Per sapere se i dati sono arrivati bufferizzare serie, il metodo available
restituisce il numero di byte che sono già stati memorizzati in questo bufferizzare. In entrambi i casi, le operazioni di lettura possono restituire un valore speciale (come -1
o null
) quando si tenta di caricare dati da bufferizzare serie quando vuoto.
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”);
}
|
Carica un byte alla volta. Il metodo di lettura
I principali metodi della classe Serial
che servono per leggere le informazioni ricevute da una porta seriale sono quelle di tipo " read
» che differiscono tra loro, principalmente, per il tipo di dati in cui forniscono le informazioni ricevute.
read
viene utilizzato per fornire i byte ricevuti dalla porta seriale come un valore compreso tra 0 e 255. Come tipo di dati byte
de Processando rappresenta il range compreso tra -128 e 127 e non tra 0 e 255, è necessario utilizzare un int
per rappresentare l'intervallo restituito da read
. Se provi a leggere con read
e il bufferizzare la stringa è vuota, restituisce valore -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());
}
}
|
Leggere i caratteri dalla porta seriale. Il metodo readChar
Il metodo readChar
è simile a read
ma restituisce un valore in formato char
invece di a int
. Come internamente, il char
en Processando (At Java) vengono memorizzati con due byte, il valore scelto da restituire durante la lettura readChar
un bufferizzare la serie vuota è 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());
}
}
|
Carica una stringa di testo. I metodi readString e readStringUntil.
Il metodo readString
restituisce un oggetto String
formato da tutti i dati disponibili in bufferizzare serie al momento della consultazione.
Il metodo readString
crea la stringa di testo presupponendo che i byte ricevuti dalla porta seriale siano nel formato ASCII quindi questo metodo di lettura non può essere utilizzato per altre codifiche.
Se si tratta di leggere il bufferizzare serie con readString
quando vuoto, il valore restituito è null
.
Il metodo readStringUntil
aggiungere a readString
la possibilità di restituire le informazioni caricate nel file bufferizzare series dividendolo per un carattere speciale (codice) che viene passato come parametro. Questo modo di leggere le informazioni ricevute ci permette di distinguere sia separatori che terminatori che aiutano a interpretare le informazioni ricevute.
Il metodo readStringUntil
Portare indietro null
quando nel bufferizzare series non trova il codice specificato nell'argomento passato (un 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
}
}
}
|
Nel seguente codice per Arduino invia tre messaggi attraverso la porta seriale. I primi due terminano in una scheda, quindi appariranno nella console. Processando, mentre il terzo, anche se verrà inviato tramite la porta seriale, non verrà letto readStringUntil(9)
poiché non termina con una scheda (con code 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()
{
}
|
Leggere blocchi di dati. I metodi readBytes e readBytesUntil.
I metodi visti sopra servono per leggere dati con formati specifici, per leggere blocchi di dati grezzi o con formato non previsto Processando vengono utilizzati metodi readBytes
y readBytesUntil
Il metodo readBytes
prova a leggere i dati disponibili nel file bufferizzare serie. Se al metodo non viene passato alcun parametro readBytes
tutti i dati disponibili vengono letti e restituiti in un vettore (byte[]
). Se come parametro viene passato un numero intero, viene letto al massimo il numero di byte indicati da questo numero e vengono restituiti anche come vettore.
Esiste un terzo modo di utilizzo readBytes
, più efficiente, che prende come argomento un vettore di byte in cui inserire il contenuto del file bufferizzare serie. Questo modo di usare readBytes
restituisce un numero intero (int
) che rappresenta il numero di byte letti.
Il metodo readBytesUntil
funziona in modo simile ma include un primo parametro che rappresenta il valore del byte che, se trovato nel bufferizzare, indicherà la fine della lettura. In questo metodo il parametro che determina il numero massimo di byte che verranno letti non ha senso poiché la quantità sarà determinata dal codice speciale.
Per testare il funzionamento del metodo readBytes
Assumiamo il seguente codice per Arduino che invia un testo attraverso la porta seriale.
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()
{
}
|
Il seguente programma di esempio per Processando legge il testo dalla porta seriale in blocchi da 32 byte (TOTAL_BYTES). Per verificare che funzioni, li mostra tramite la console come caratteri, forzando il tipo dei byte ricevuti 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]);
}
}
}
}
|
Nello screenshot seguente puoi vedere come vengono visualizzati nella console Processando i dati che sono stati caricati in blocchi di (massimo) 32 byte (TOTAL_BYTES) ogni volta. Ma c'è un problema di cui si è già parlato: Arduino ha inviato i versi di Federico García Lorca dell'esempio codificato come testo in formato UTF-8, che non è quello utilizzato Processando (Java), cosa preferisci UTF all'16 ottobre quindi coloro che non corrispondono al rango del ASCII stampabili vengono interpretati in modo errato.
Per risolvere questo problema è possibile caricare i set di caratteri (set di caratteri) e definire un nuovo oggetto String
costringendolo ad essere rappresentato con la codifica UTF-8 come mostrato nel seguente codice di esempio.
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));
}
}
}
|
Leggi gli ultimi dati ricevuti. I metodi last e lastChar.
Mentre il resto dei metodi di lettura (il "type read
») caricano le informazioni del bufferizzare serie nello stesso ordine in cui è arrivata (FIFO), con questi due metodi l'ultimo byte che ha raggiunto il file bufferizzare serie. Il metodo last
restituisce il valore dell'ultimo byte come a int
y lastChar
restituisce il valore come a char
.
Gestione buffer seriale
Sebbene i metodi visti finora siano perfettamente funzionanti, non sempre rappresentano il modo migliore per sfruttare l'accesso alla porta seriale. Per caricare i dati è necessario verificare periodicamente lo stato dei file bufferizzare serie e leggere i dati disponibili in una parte ripetuta del codice. Un modo generalmente più efficiente è leggere i dati solo quando sai che sono disponibili.
Leggere la porta seriale quando vengono ricevuti i dati. L'evento seriale.
Per accedere al bufferizzare serial alla ricezione dei dati, è possibile sfruttare l'evento Serial gestendolo tramite la definizione del metodo serialEvent
. Questo metodo utilizza la porta seriale che lo avvia come argomento.
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());
}
|
Dimensionare il buffer seriale. Il metodo del buffer.
Se conosci il numero di byte che compongono un blocco di dati utili, puoi ottimizzare ulteriormente questo stile di lettura dei dati. bufferizzare serie attraverso serialEvent
. Il metodo buffer
consente di impostare il numero di byte che verranno archiviati nel file bufferizzare prima di lanciare un evento seriale. Il metodo prevede come parametro un numero intero che rappresenta il numero di 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());
}
}
|
Riempire il buffer finché non viene ricevuto un valore. Il metodo bufferUntil.
Invece di impostare la chiamata al metodo serialEvent
per una quantità di dati nel file bufferizzare, con il metodo bufferUntil
è possibile configurare per archiviare i dati fino all'arrivo di un valore speciale e quindi generare l'evento Serial. Il parametro passato a questo metodo è a int
che rappresenta il valore prodotto dalla chiamata a 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
}
|
Elimina i dati memorizzati nel buffer. Il metodo chiaro.
Con il metodo clear
È possibile eliminare i dati attualmente presenti nel file bufferizzare. Questo metodo può essere utilizzato, ad esempio, per avviare una nuova sessione di ricezione dati ignorando i dati rimanenti della precedente.
Tipica applicazione di elaborazione per la lettura dei dati tramite la porta seriale
Infine è conveniente ricapitolare le operazioni dell'oggetto Serial
de Processando quelli più comunemente utilizzati, ripercorrendo un tipico esempio di ricezione dei dati tramite la porta seriale per tracciarne un grafico, in questo caso di aree impilate.
Importa la libreria seriale
1
|
import processing.serial.*;
|
Determinare il protocollo dati (separatori)
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
|
Determinare l'oggetto della classe Serial
1
|
Serial conexion_sensores;
|
Istanziare l'oggetto classe Serial impostando la porta seriale utilizzata
1
|
conexion_sensores=new Serial(this,“/dev/ttyUSB1”,9600);
|
Configurare il buffer della porta seriale
1
|
conexion_sensores.bufferUntil(TERMINADOR);
|
Implementare un gestore per l'evento Serial
1
|
void serialEvent(Serial serie)
|
Leggi il buffer seriale
1
|
String[] texto_valor=serie.readString().split(SEPARADOR);
|
Condizionare i dati ricevuti
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]);
}
|
Terminare le comunicazioni seriali
1
2
|
conexion_sensores.clear();
conexion_sensores.stop();
|
Il codice di esempio riportato di seguito illustra questo riepilogo con un'applicazione funzionale (anche se molto semplice) che genera un grafico ad area con i valori che vengono ricevuti tramite la porta seriale, qualcosa di simile a quanto mostra l'animazione seguente.
Per non perdersi nel resto del programma e focalizzare l'attenzione sulle comunicazioni seriali con Processando, vengono evidenziate le righe di codice che corrispondono alle operazioni precedenti.
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];
}
}
|
Invia commento