Komunikacja szeregowa z przetwarzaniem
Klasa seryjna
Operacje, w których należy używać komunikacji szeregowej Przetwarzanie są zdefiniowane w klasie Serial
.Pierwsza operacja, którą należy wykonać, aby użyć ich w programie (szkic) będzie włączenie go do kodu za pomocą import processing.serial.*;
.
Klasa Serial
Posiada pięć różnych konstruktorów w zależności od wskazanych parametrów. Jedynym wymaganym parametrem jest obiekt nadrzędny (roślina mateczna), który zwykle odpowiada głównemu programowi (powiedzmy, oknu programu) klasy PApplet
. Jak zwykle rodzicem będzie pisany program (plik szkic current), wartość tego pierwszego obowiązkowego parametru będzie wynosić this
.
Pozostałych pięć parametrów, które można przekazać konstruktorowi, to ① prędkość, ② nazwa portu szeregowego, ③ parytet użyte w protokole, ④ bity danych i ⑤ bity stopu. Najczęściej przekazywanymi parametrami, oprócz wymaganego obiektu nadrzędnego, są nazwa portu i prędkość.
La prędkość komunikacji szeregowej jest liczbą całkowitą (int
) to domyślnie ustawiona jest wartość 9600 jeśli ten parametr nie zostanie przekazany do konstruktora.
Dostępne porty szeregowe. Metoda listowa
El nazwa portu ma postać określoną przez system, w ten sposób np. w Dystrybucje Linuksa będzie coś takiego /dev/ttyS4 / dev / ttyACM3 o / dev / ttyUSB1 (w zależności od typu portu), natomiast w systemie Windows będzie to mniej więcej coś takiego COM12. Jeśli port nie jest fizycznie powiązany z urządzeniem, program zwykle nie będzie wiedział, którego portu użyć. Powszechnym sposobem wyboru portu jest uzyskanie listy dostępnych portów, pokazanie jej użytkownikowi i umożliwienie mu wybrania tego, którego chce używać. Metoda Serial.list()
zwraca wektor ciągów tekstowych (String
) z nazwami portów dostępnych w systemie.
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());
}
|
Port używany domyślnie przez bibliotekę Serial
jest pierwszym z zwracanych przez metodę list
(pewno COM1 w systemie Windows lub /dev/ttyS0 en GNU / Linux). Z wyjątkiem bardzo ograniczonych kontekstów, w których sprzęt, na którym pracuje się, jest ściśle znany (np. system w trybie kiosku), zwykle nie jest on pomijany i wyraźnie wskazany jest port docelowy.
Powyższy zrzut ekranu przedstawia dane wyjściowe systemu GNU / Linux który ma cztery porty szeregowe RS 232 (ttyS0 a ttyS3) i pięć adapterów dwóch typów (ttyACM0 a ttyACM1 y ttyUSB0 a ttyUSB2).
Aby uzyskać dostęp do portów szeregowych, użytkownik musi należeć do grupy, do której system je przypisuje tty o połączenie telefoniczne. Na zrzucie ekranu powyższego obrazu widać, że porty szeregowe wymienione na liście ls /dev/tty[ASU]* -la
należą do grupy połączenie telefoniczne który ma na nich uprawnienia do odczytu i zapisu.
Parametry protokołu szeregowego
La parytet komunikacji szeregowej jest wyrażony w Przetwarzanie jako postać (char
), które mogą przyjmować wartości: ① N
(Żaden), aby nie wykryć parytet, ② E
(nawet), aby wskazać, że Bit parzystości jest parzysta, ③ O
(nieparzysty), aby wskazać, że Bit parzystości jest dziwne, ④ M
(znak), aby zawsze robić Bit parzystości i ⑤ S
(przestrzeń), aby zawsze uczynić jednego Bit parzystości. Wartość domyślna, jeśli nie została przekazana do konstruktora jako parametr, to N
(bez parytet).
Liczba bity danych, domyślnie osiem, wskazuje liczbę bitów tworzących ładunek danych netto (zwany znakiem lub czasem słowem), który jest przesyłany w każdej podstawowej jednostce ramki. Parametr wskazujący liczbę bitów danych wyrażony jest liczbą całkowitą (int
).
Wreszcie piąty możliwy parametr wskazuje czas trwania oceny końcowej, wyrażony jako zatrzymać bity (zatrzymaj bity), który jest oznaczony jako liczba przedstawiona w zmiennoprzecinkowy (float
), które mogą przyjmować wartości 1.0
(wartość domyślna jeśli parametr nie jest przekazywany do konstruktora), 1.5
lub 2.0
.
Konstruktory klasy Serial
Na poniższej liście przedstawiono różne kombinacje parametrów, które można przekazać do konstruktora klasy Serial
:
Serial(padre)
Serial(padre,puerto)
Serial(padre,velocidad)
Serial(padre,puerto,velocidad)
Serial(padre,puerto,velocidad,paridad,bits_datos,bits_parada)
Zakończ komunikację szeregową. Metoda zatrzymania.
Aby zwolnić port szeregowy przypisany podczas tworzenia instancji Serial
, i że inne aplikacje systemowe mogą z niej korzystać, komunikacja z tą metodą jest kończona stop
, który nie otrzymuje parametrów.
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
}
|
Wyślij dane przez port szeregowy. Metoda zapisu
Aby wysłać dane, klasa Serial
de Przetwarzanie zawiera metodę write
za pomocą którego możesz przesyłać ① ciągi tekstowe (String
), ② bajtów lub ③ wektorów bajtów (byte[]
). Warto o tym pamiętać byte
en Przetwarzanie (Na Java) reprezentuje liczbę całkowitą z zakresu od -128 do 127 i domyślnie łańcuchy używają kodowania 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
}
|
Odczyt danych z portu szeregowego
Aby program mógł wykonywać inne zadania podczas odbierania danych przez port szeregowy, zwykle przechowuje się je w formacie a bufor otrzymane dane i w razie potrzeby odczytać je. Chociaż zwykle nie jest to zbyt wydajne, możesz zatrzymać aplikację, aby załadować wszystkie dostępne dane; Jednak najczęstszą rzeczą będzie odczytywanie informacji w miarę ich pojawiania się, w każdej iteracji draw
, gdy dostępna jest określona ilość lub otrzymano specjalny kod.
Ilość danych dostępnych w buforze. Dostępna metoda
Aby dowiedzieć się, czy dane dotarły do bufor seria, metoda available
zwraca liczbę bajtów, które zostały już w tym zapisane bufor. W obu przypadkach operacje odczytu mogą zwrócić wartość specjalną (np -1
o null
) podczas próby załadowania danych z bufor seria, gdy jest pusta.
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”);
}
|
Ładuj po jednym bajcie na raz. Metoda odczytu
Główne metody zajęć Serial
służące do odczytu informacji odbieranych przez port szeregowy to te typu „type read
» różnią się między sobą przede wszystkim rodzajem danych, w jakich przekazują otrzymane informacje.
read
służy do dostarczania bajtów odbieranych przez port szeregowy jako wartość z zakresu od 0 do 255. Jako typ danych byte
de Przetwarzanie reprezentuje zakres od -128 do 127, a nie od 0 do 255, konieczne jest użycie int
w celu reprezentowania zakresu zwracanego przez read
. Jeśli spróbujesz czytać za pomocą read
i bufor ciąg jest pusty, zwraca wartość -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());
}
}
|
Odczytaj znaki z portu szeregowego. Metoda readChar
Metoda readChar
jest podobny a read
ale zwraca wartość w formacie char
zamiast int
. Podobnie jak wewnętrznie, char
en Przetwarzanie (Na Java) są przechowywane z dwoma bajtami, wartością wybraną do zwrócenia podczas odczytu readChar
d bufor jest pusta seria 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());
}
}
|
Załaduj ciąg tekstowy. Metody readString i readStringUntil.
Metoda readString
zwraca obiekt String
utworzone na podstawie wszystkich danych dostępnych w bufor serii w momencie konsultacji.
Metoda readString
tworzy ciąg tekstowy przy założeniu, że bajty odebrane przez port szeregowy mają format ASCII więc tej metody odczytu nie można używać w przypadku innych kodowań.
Jeśli chodzi o przeczytanie bufor serial z readString
gdy jest pusty, zwracaną wartością jest null
.
Metoda readStringUntil
dodać do readString
możliwość zwrotu informacji załadowanych do pliku bufor seria dzieląca ją znakiem specjalnym (kodem), który jest przekazywany jako parametr. Taki sposób odczytania otrzymanej informacji pozwala wyróżnić zarówno separatory, jak i terminatory, które pomagają zinterpretować otrzymaną informację.
Metoda readStringUntil
przynieść z powrotem null
kiedy w bufor series nie znajduje kodu określonego w przekazanym jej argumencie (jeden bajt).
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
}
}
}
|
W poniższym kodzie dla Arduino wysyła trzy wiadomości przez port szeregowy. Pierwsze dwa kończą się zakładką, więc pojawią się w konsoli. Przetwarzanie, natomiast trzeci, choć zostanie przesłany przez port szeregowy, nie zostanie przez niego odczytany readStringUntil(9)
ponieważ nie kończy się na karcie (z kodem 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()
{
}
|
Przeczytaj bloki danych. Metody readBytes i readBytesUntil.
Przedstawione powyżej metody służą do odczytu danych w określonych formatach, do odczytu bloków danych surowych lub w formacie, który nie jest przewidziany w Przetwarzanie metody są stosowane readBytes
y readBytesUntil
Metoda readBytes
spróbuj odczytać dane dostępne w pliku bufor seria. Jeśli do metody nie zostanie przekazany żaden parametr readBytes
wszystkie dostępne dane są odczytywane i zwracane w postaci wektora (byte[]
). Jeśli jako parametr zostanie przekazana liczba całkowita, odczytywana jest maksymalna liczba bajtów wskazywana przez tę liczbę i są one również zwracane jako wektor.
Istnieje trzeci sposób użycia readBytes
, bardziej wydajny, który przyjmuje jako argument wektor bajtowy, w którym zawartość bufor seria. Ten sposób użycia readBytes
zwraca liczbę całkowitą (int
) reprezentująca liczbę odczytanych bajtów.
Metoda readBytesUntil
działa w podobny sposób, ale zawiera pierwszy parametr reprezentujący wartość bajtu, który, jeśli zostanie znaleziony w bufor, wskaże koniec odczytu. W tej metodzie parametr określający maksymalną liczbę bajtów, które zostaną odczytane, nie ma sensu, ponieważ o ilości będzie decydował specjalny kod.
Aby przetestować działanie metody readBytes
Załóżmy, że następujący kod dla Arduino który wysyła SMS-a przez port szeregowy.
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()
{
}
|
Poniższy przykładowy program dla Przetwarzanie odczytuje tekst z portu szeregowego w 32-bajtowych blokach (TOTAL_BYTES). Aby sprawdzić, czy to działa, pokazuje to przez konsolę jako znaki, wymuszając typ odbieranych bajtów 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 poniższym zrzucie ekranu możesz zobaczyć, jak są one wyświetlane w konsoli Przetwarzanie dane, które zostały załadowane w blokach o (maksymalnie) 32 bajtach (TOTAL_BYTES) za każdym razem. Ale jest problem, o którym była już mowa: Arduino przesyła wersety Federico Garcia Lorca przykładu zakodowanego jako tekst w formacie UTF-8, który nie jest tym używanym Przetwarzanie (Java), co wolisz UTF-16 więc ci, którzy nie odpowiadają rangi ASCII do druku są interpretowane nieprawidłowo.
Aby rozwiązać ten problem, można załadować zestawy znaków (charset) i zdefiniuj nowy obiekt String
zmuszając go do reprezentowania go za pomocą kodowania UTF-8 jak pokazano w poniższym przykładowym kodzie.
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));
}
}
}
|
Przeczytaj najnowsze otrzymane dane. Metody last i lastChar.
Podczas gdy pozostałe metody odczytu („type read
») ładują informacje o bufor serię w tej samej kolejności, w jakiej przybyła (FIFO), w przypadku tych dwóch metod ostatni bajt, który osiągnął bufor seria. Metoda last
zwraca wartość ostatniego bajtu jako a int
y lastChar
zwraca wartość jako a char
.
Zarządzanie buforem szeregowym
Chociaż dotychczasowe metody są doskonale funkcjonalne, nie zawsze stanowią najlepszy sposób wykorzystania dostępu do portu szeregowego. Aby załadować dane, muszą okresowo sprawdzać stan bufor serii i odczytaj dane dostępne w powtarzającej się części kodu. Ogólnie bardziej skutecznym sposobem jest odczytywanie danych tylko wtedy, gdy wiesz, że są one dostępne.
Odczyt portu szeregowego po odebraniu danych. Wydarzenie seryjne.
Aby uzyskać dostęp do bufor serial po odebraniu danych, zdarzenie Serial można wykorzystać, zarządzając nim poprzez definicję metody serialEvent
. Ta metoda wykorzystuje port szeregowy, który ją uruchamia, jako argument.
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());
}
|
Rozmiar bufora szeregowego. Metoda buforowa.
Jeśli znasz liczbę bajtów tworzących blok przydatnych danych, możesz dalej optymalizować ten styl odczytu danych. bufor seria przez serialEvent
. Metoda buffer
pozwala ustawić liczbę bajtów, które będą przechowywane w pliku bufor przed uruchomieniem wydarzenia seryjnego. Metoda oczekuje jako parametru liczby całkowitej reprezentującej liczbę bajtów.
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());
}
}
|
Wypełniaj bufor aż do otrzymania wartości. Metoda buforaUntil.
Zamiast ustawiać wywołanie metody serialEvent
dla ilości danych w pliku bufor, przy użyciu metody bufferUntil
możesz skonfigurować przechowywanie danych do momentu pojawienia się specjalnej wartości, a następnie wywołać zdarzenie Serial. Parametr przekazywany do tej metody to a int
który reprezentuje wartość wygenerowaną przez wywołanie 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
}
|
Usuń dane zapisane w buforze. Jasna metoda.
z metodą clear
Możesz usunąć dane znajdujące się aktualnie w pliku bufor. Metodą tą można na przykład rozpocząć nową sesję odbioru danych ignorując dane pozostałe z poprzedniej.
Typowa aplikacja przetwarzająca do odczytu danych przez port szeregowy
Na koniec wygodnie jest podsumować działanie obiektu Serial
de Przetwarzanie które są częściej używane, przechodząc przez typowy przykład odbierania danych przez port szeregowy, aby narysować z nimi wykres, w tym przypadku obszarów skumulowanych.
Zaimportuj bibliotekę Serial
1
|
import processing.serial.*;
|
Określ protokół danych (separatory)
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
|
Określ obiekt klasy Serial
1
|
Serial conexion_sensores;
|
Utwórz instancję obiektu klasy Serial, ustawiając używany port szeregowy
1
|
conexion_sensores=new Serial(this,“/dev/ttyUSB1”,9600);
|
Skonfiguruj bufor portu szeregowego
1
|
conexion_sensores.bufferUntil(TERMINADOR);
|
Zaimplementuj procedurę obsługi zdarzenia Serial
1
|
void serialEvent(Serial serie)
|
Przeczytaj bufor szeregowy
1
|
String[] texto_valor=serie.readString().split(SEPARADOR);
|
Kondycjonuj otrzymane dane
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]);
}
|
Zakończ komunikację szeregową
1
2
|
conexion_sensores.clear();
conexion_sensores.stop();
|
Przykładowy kod poniżej ilustruje to podsumowanie funkcjonalną (choć bardzo prostą) aplikacją, która generuje wykres warstwowy z wartościami odbieranymi przez port szeregowy, coś podobnego do tego, co pokazuje poniższa animacja.
Aby nie zgubić się w dalszej części programu i skupić uwagę na komunikacji szeregowej Przetwarzanie, podświetlone zostaną linie kodu odpowiadające poprzednim operacjom.
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];
}
}
|
Zamieść komentarz