Comunicações seriais com processamento
A classe serial
As operações para usar comunicações seriais em Tratamento são definidos na classe Serial
.A primeira operação a realizar para utilizá-los em um programa (esboço) será incorporá-lo ao código com import processing.serial.*;
.
A aula Serial
Possui cinco construtores diferentes dependendo dos parâmetros indicados. O único parâmetro obrigatório é o objeto pai (principal) que geralmente corresponde ao programa principal (digamos, a janela do programa) da classe PApplet
. Como normalmente o pai será o programa que está sendo escrito (o esboço atual), o valor deste primeiro parâmetro obrigatório será this
.
Os outros cinco parâmetros que podem ser passados ao construtor são ① a velocidade, ② o nome da porta serial ③ o paridade usados no protocolo, ④ os bits de dados e ⑤ os bits de parada. Os parâmetros passados com mais frequência, além do objeto pai necessário, são o nome da porta e a velocidade.
La velocidade de comunicação serial é um número inteiro (int
) que o padrão é o valor 9600 se este parâmetro não for passado para o construtor.
Portas seriais disponíveis. O método de lista
El nome da porta tem a forma determinada pelo sistema, desta forma, por exemplo em Distribuições Linux será algo como / dev / ttyS4 / dev / ttyACM3 o / dev / ttyUSB1 (dependendo do tipo de porta), enquanto no Windows será algo como COM12. A menos que uma porta esteja fisicamente associada a um dispositivo, o programa normalmente não saberá qual porta usar. Uma forma comum de selecionar a porta é obter uma lista das disponíveis, mostrá-la ao usuário e permitir que ele escolha aquela que deseja utilizar. O método Serial.list()
retorna um vetor de strings de texto (String
) com os nomes das portas disponíveis no 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());
}
|
A porta usada por padrão pela biblioteca Serial
é o primeiro daqueles retornados pelo método list
(certamente COM1 no Windows ou / dev / ttyS0 en GNU / Linux). Exceto em contextos muito limitados em que o hardware com o qual se trabalha é estritamente conhecido (como um sistema em modo quiosque), normalmente não é omitido e a porta de destino é expressamente indicada.
A captura de tela acima mostra a saída de um sistema GNU / Linux que possui quatro portas seriais RS-232 (ttyS0 a ttyS3) e cinco adaptadores de dois tipos (ttyACM0 a ttyACM1 y ttyUSB0 a ttyUSB2).
Para acessar as portas seriais o usuário deve pertencer ao grupo ao qual o sistema as atribui, normalmente tty o discar. Na captura de tela da imagem acima você pode ver que as portas seriais listadas com ls /dev/tty[ASU]* -la
pertence ao grupo discar que tem permissões de acesso de leitura e gravação neles.
Parâmetros de protocolo serial
La paridade de comunicações seriais é expresso em Tratamento como personagem (char
) que pode assumir os valores: ① N
(Nenhum) para não detectar o paridade, ② E
(até) para indicar que bit de paridade é par, ③ O
(estranho) para indicar que bit de paridade é estranho, ④ M
(marca) para sempre fazer o bit de paridade e ⑤ S
(espaço) para sempre fazer um bit de paridade. O valor padrão, se não for passado ao construtor como parâmetro, é N
(sem paridade).
Número bits de dados, que é oito por padrão, indica o número de bits que compõem a carga útil de dados líquidos (chamada de caractere ou às vezes de palavra) que é transmitida em cada unidade básica do quadro. O parâmetro que indica o número de bits de dados é expresso como um número inteiro (int
).
Por fim, o quinto parâmetro possível indica a duração da nota final, expressa como parar bits (parar bits), que é indicado como um número representado em ponto flutuante (float
) que pode assumir os valores 1.0
(o valor padrão se o parâmetro não for passado para o construtor), 1.5
um 2.0
.
Construtores da classe Serial
A lista a seguir mostra as diferentes combinações de parâmetros que podem ser passados para o construtor da classe Serial
:
Serial(padre)
Serial(padre,puerto)
Serial(padre,velocidad)
Serial(padre,puerto,velocidad)
Serial(padre,puerto,velocidad,paridad,bits_datos,bits_parada)
Encerrar as comunicações seriais. O método de parada.
Para liberar a porta serial, atribuída ao instanciar Serial
, e que outros aplicativos do sistema possam usá-lo, as comunicações serão encerradas com o método stop
, que não recebe parâmetros.
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
}
|
Envie dados pela porta serial. O método write
Para enviar dados, a classe Serial
de Tratamento incorpora o método write
com o qual você pode transmitir ① strings de texto (String
), ② bytes ou ③ vetores de bytes (byte[]
). É interessante lembrar que byte
en Tratamento (No Java) representa um número inteiro entre -128 e 127 e, por padrão, strings usam a codificação 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
}
|
Ler dados da porta serial
Para que o programa possa realizar outras tarefas enquanto os dados são recebidos pela porta serial, é comum armazenar em um amortecer os dados que chegam e lê-los quando apropriado. Embora normalmente não seja muito eficiente, você pode parar o aplicativo para carregar todos os dados disponíveis; Porém, o mais comum será ler a informação à medida que ela chega, seja em cada iteração de draw
, quando uma determinada quantidade estiver disponível ou um código especial for recebido.
Quantidade de dados disponíveis no buffer. O método disponível
Para saber se os dados chegaram amortecer série, o método available
retorna o número de bytes que já foram armazenados neste amortecer. Em ambos os casos, as operações de leitura podem retornar um valor especial (como -1
o null
) ao tentar carregar dados de amortecer série quando vazia.
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”);
}
|
Carregue um byte de cada vez. O método de leitura
Os principais métodos da classe Serial
que servem para ler as informações recebidas por uma porta serial são aqueles do "tipo read
» que se diferenciam entre si, principalmente, pelo tipo de dados em que entregam as informações recebidas.
read
é usado para entregar os bytes recebidos pela porta serial como um valor entre 0 e 255. Conforme o tipo de dados byte
de Tratamento representa o intervalo entre -128 e 127 e não entre 0 e 255, é necessário usar um int
para representar o intervalo retornado por read
. Se você tentar ler com read
e pelo amortecer string está vazia, retorna valor -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());
}
}
|
Leia caracteres da porta serial. O método readChar
O método readChar
é similar a read
mas retorna um valor no formato char
em vez de um int
. Como internamente, o char
en Tratamento (No Java) são armazenados com dois bytes, valor escolhido para retornar na leitura com readChar
um amortecer série vazia é 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());
}
}
|
Carregue uma string de texto. Os métodos readString e readStringUntil.
O método readString
retorna um objeto String
formado a partir de todos os dados disponíveis no amortecer série no momento da consulta.
O método readString
cria a string de texto assumindo que os bytes recebidos pela porta serial estão no formato ASCII portanto, este método de leitura não pode ser usado para outras codificações.
Se for sobre ler o amortecer série com readString
quando vazio, o valor de retorno é null
.
O método readStringUntil
adicionar à readString
a capacidade de retornar informações carregadas no amortecer série dividindo-a por um caractere especial (código) que é passado como parâmetro. Esta forma de ler a informação recebida permite-nos distinguir tanto separadores como terminadores que ajudam a interpretar a informação recebida.
O método readStringUntil
trazer de volta null
quando no amortecer series não encontra o código especificado no argumento passado a ela (um 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
}
}
}
|
No código a seguir para Arduino envia três mensagens pela porta serial. Os dois primeiros terminam em uma aba, então aparecerão no console. Tratamento, enquanto o terceiro, embora seja enviado pela porta serial, não será lido com readStringUntil(9)
já que não termina em uma aba (com código ASCII
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()
{
}
|
Leia blocos de dados. Os métodos readBytes e readBytesUntil.
Os métodos vistos acima são utilizados para leitura de dados com formatos específicos, para leitura de blocos de dados brutos ou com formato não previsto em Tratamento métodos são usados readBytes
y readBytesUntil
O método readBytes
tente ler os dados disponíveis no amortecer Series. Se nenhum parâmetro for passado para o método readBytes
todos os dados disponíveis são lidos e retornados em um vetor (byte[]
). Se um número inteiro for passado como parâmetro, um máximo do número de bytes indicados por este número é lido e também retornado como um vetor.
Existe uma terceira maneira de usar readBytes
, mais eficiente, que toma como argumento um vetor de bytes no qual o conteúdo do amortecer Series. Essa forma de usar readBytes
retorna um número inteiro (int
) que representa o número de bytes que foram lidos.
O método readBytesUntil
funciona de forma semelhante, mas inclui um primeiro parâmetro que representa o valor do byte que, se encontrado no amortecer, indicará o final da leitura. Neste método, o parâmetro que determina o número máximo de bytes que serão lidos não faz sentido, pois a quantidade será determinada pelo código especial.
Para testar o funcionamento do método readBytes
Vamos supor o seguinte código para Arduino que envia um texto pela porta serial.
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()
{
}
|
O programa de exemplo a seguir para Tratamento lê texto da porta serial em blocos de 32 bytes (TOTAL_BYTES). Para verificar se funciona, ele mostra através do console como caracteres, forçando o tipo dos bytes recebidos a 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]);
}
}
}
}
|
Na captura de tela a seguir você pode ver como eles são exibidos no console Tratamento os dados que foram carregados em blocos de (máximo) 32 bytes (TOTAL_BYTES) cada vez. Mas há um problema que já foi falado: Arduino tem enviado os versos de Federico Garcia Lorca do exemplo codificado como texto no formato UTF-8, que não é o usado Tratamento (Java), o que você prefere UTF-16 então aqueles que não correspondem à classificação do ASCII imprimíveis são interpretados incorretamente.
Para resolver este problema, os conjuntos de caracteres podem ser carregados (conjunto de caracteres) e defina um novo objeto String
forçando-o a ser representado com codificação UTF-8 conforme mostrado no código de exemplo a seguir.
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));
}
}
}
|
Leia os últimos dados recebidos. Os métodos last e lastChar.
Enquanto o resto dos métodos de leitura (o "tipo read
») eles carregam as informações do amortecer série na mesma ordem em que chegou (FIFO), com esses dois métodos o último byte que atingiu o amortecer Series. O método last
retorna o valor do último byte como um int
y lastChar
retorna o valor como um char
.
Gerenciamento de buffer serial
Embora os métodos vistos até agora sejam perfeitamente funcionais, nem sempre representam a melhor forma de explorar o acesso à porta serial. Para carregar os dados, eles precisam verificar periodicamente o status do amortecer série e leia os dados disponíveis em uma parte repetida do código. Uma maneira geralmente mais eficiente é ler os dados somente quando você sabe que eles estão disponíveis.
Leia a porta serial quando os dados são recebidos. O evento em série.
Para acessar o amortecer serial quando os dados são recebidos, o evento Serial pode ser explorado gerenciando-o através da definição do método serialEvent
. Este método usa a porta serial que o inicia como argumento.
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());
}
|
Dimensione o buffer serial. O método buffer.
Se você souber o número de bytes que compõem um bloco de dados úteis, poderá otimizar ainda mais esse estilo de leitura dos dados. amortecer série através serialEvent
. O método buffer
permite definir o número de bytes que serão armazenados no amortecer antes de lançar um evento serial. O método espera como parâmetro um número inteiro que represente a quantidade de bytes.
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());
}
}
|
Preencha o buffer até que um valor seja recebido. O método bufferUntil.
Em vez de definir a chamada do método serialEvent
para uma quantidade de dados no amortecer, com o método bufferUntil
você pode configurar para armazenar dados até que um valor especial chegue e então gerar o evento Serial. O parâmetro passado para este método é um int
que representa o valor produzido pela chamada para 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
}
|
Exclua os dados armazenados no buffer. O método claro.
Com o método clear
Você pode excluir os dados que estão atualmente no amortecer. Este método pode ser utilizado, por exemplo, para iniciar uma nova sessão de recepção de dados ignorando os dados restantes da anterior.
Aplicação típica de processamento para leitura de dados através da porta serial
Finalmente, é conveniente recapitular as operações do objeto Serial
de Tratamento que são mais comumente utilizados, passando por um exemplo típico de recebimento de dados pela porta serial para desenhar um gráfico com eles, neste caso de áreas empilhadas.
Importe a biblioteca serial
1
|
import processing.serial.*;
|
Determinar protocolo de dados (separadores)
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
|
Determine o objeto da classe Serial
1
|
Serial conexion_sensores;
|
Instancie o objeto da classe Serial definindo a porta serial usada
1
|
conexion_sensores=new Serial(this,“/dev/ttyUSB1”,9600);
|
Configurar o buffer da porta serial
1
|
conexion_sensores.bufferUntil(TERMINADOR);
|
Implemente um manipulador para o evento Serial
1
|
void serialEvent(Serial serie)
|
Ler buffer serial
1
|
String[] texto_valor=serie.readString().split(SEPARADOR);
|
Condicione os dados recebidos
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]);
}
|
Terminar comunicações seriais
1
2
|
conexion_sensores.clear();
conexion_sensores.stop();
|
O código de exemplo abaixo ilustra esse resumo com uma aplicação funcional (embora muito simples) que gera um gráfico de área com os valores que são recebidos pela porta serial, algo semelhante ao que mostra a animação a seguir.
Para não se perder no resto do programa e focar a atenção nas comunicações seriais com Tratamento, as linhas de código que correspondem às operações anteriores são destacadas.
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];
}
}
|
Postar Comentário