Выдает ошибку "NullPointException" в программе Processing

скетч для Proccesing:

Meter m;
import processing.serial.*;
Serial serial;
import controlP5.*;
ControlP5 cp5;
String portName;
int potVal;

void setup() {
  size(400, 200);
  cp5 = new ControlP5(this);
  
  cp5.addButton("open").linebreak();
  cp5.addButton("closePort").linebreak();
  cp5.addButton("ledOn").linebreak();
  cp5.addButton("ledOff").linebreak();
  cp5.addScrollableList("comlist").close();
  
  m = new Meter(this, 100, 10);
  m.setMeterWidth(250);
  m.setUp(0, 1023, 0, 100, -180, 0);
  String[] scaleLabels = {"0", "20", "40", "60", "80", "100"};
  m.setScaleLabels(scaleLabels);
  
  String list[] = Serial.list();
  cp5.get(ScrollableList.class, "comlist").addItems(list);
  
}

void comlist(int n) {
  portName = Serial.list()[n];
}
void open(){
  serial = new Serial(this, portName, 9600);
}
void closePort() {
  serial.stop();
}
void ledOn() {
  serial.write("0,1;");
}
void ledOff() {
  serial.write("0,0;");
}
void draw() {
  background(120);
  m.updateMeter(potVal);
  if (serial != null) {
  if (serial.available() > 0) {
    String str = serial.readStringUntil('\n');
    str = str.trim();
    String data[] = str.split(",");
    switch (int(data[0])) {
      case 0:
      potVal = int(data[1]);
      break;
      case 1:
      break;
      case 2:
      break;
    }
  }
  }
}```

скетч для Ардуино:
```#include <GParser.h>
#include <EncButton.h>
#include <FastIO.h>
#define POT 0
#define BTN 3
EncButton <EB_TICK, 3> btn;
bool flag = 0;

void setup() {
Serial.begin(9600);
pinMode (13, 1);
}

void loop() {
  if (Serial.available()) {
  char buf[50];
  Serial.readBytesUntil(';', buf, 50);
  GParser data (buf, ',');
  int ints[10];
  data.parseInts(ints);

  switch (ints[0]) { 
    case 0: digitalWrite(13, ints[1]);
    break;
  }
 }
 btn.tick();
 static uint32_t tmr = 0;
 if (millis() - tmr > 100) 
 {
  tmr = millis();
  Serial.print(0);
 Serial.print(',');
 Serial.println(analogRead(POT));
 }
 
if (btn.isClick()) 
{
flag = !flag;
Serial.print(1);
Serial.print(',');
Serial.println(flag);
}
}

Так же в окне для ошибок Processing пишется синими буквами примечание указать шрифт. Пробовал любой шрифт, примечание остается. Как я понимаю просит разобраться со шрифтом внутри библиотеки ControlP5. Как зайти в код библиотеки, я не знаю. Но больше интересна ошибка “NullPointException” , которая выскакивает при запуске картинки через несколько секунд, не зависимо от положения потенциометра. Скетчи нашел в инете. У тех кто их создал, все работает на этом этапе. Дальше будет прописываться работа кнопки.

Нечайно скетч Processing отправил со скетчем Ардуино вместе.

Meter m;
import processing.serial.*;
Serial serial;
import controlP5.*;
ControlP5 cp5;
String portName;
int potVal;

void setup() {
  size(400, 200);
  cp5 = new ControlP5(this);
  
  cp5.addButton("open").linebreak();
  cp5.addButton("closePort").linebreak();
  cp5.addButton("ledOn").linebreak();
  cp5.addButton("ledOff").linebreak();
  cp5.addScrollableList("comlist").close();
  
  m = new Meter(this, 100, 10);
  m.setMeterWidth(250);
  m.setUp(0, 1023, 0, 100, -180, 0);
  String[] scaleLabels = {"0", "20", "40", "60", "80", "100"};
  m.setScaleLabels(scaleLabels);
  
  String list[] = Serial.list();
  cp5.get(ScrollableList.class, "comlist").addItems(list);
  
}

void comlist(int n) {
  portName = Serial.list()[n];
}
void open(){
  serial = new Serial(this, portName, 9600);
}
void closePort() {
  serial.stop();
}
void ledOn() {
  serial.write("0,1;");
}
void ledOff() {
  serial.write("0,0;");
}
void draw() {
  background(120);
  m.updateMeter(potVal);
  if (serial != null) {
  if (serial.available() > 0) {
    String str = serial.readStringUntil('\n');
    str = str.trim();
    String data[] = str.split(",");
    switch (int(data[0])) {
      case 0:
      potVal = int(data[1]);
      break;
      case 1:
      break;
      case 2:
      break;
    }
  }
  }
}

скетч для Ардуино:

#include <EncButton.h>
#include <FastIO.h>
#define POT 0
#define BTN 3
EncButton <EB_TICK, 3> btn;
bool flag = 0;

void setup() {
Serial.begin(9600);
pinMode (13, 1);
}

void loop() {
  if (Serial.available()) {
  char buf[50];
  Serial.readBytesUntil(';', buf, 50);
  GParser data (buf, ',');
  int ints[10];
  data.parseInts(ints);

  switch (ints[0]) { 
    case 0: digitalWrite(13, ints[1]);
    break;
  }
 }
 btn.tick();
 static uint32_t tmr = 0;
 if (millis() - tmr > 100) 
 {
  tmr = millis();
  Serial.print(0);
 Serial.print(',');
 Serial.println(analogRead(POT));
 }
 
if (btn.isClick()) 
{
flag = !flag;
Serial.print(1);
Serial.print(',');
Serial.println(flag);
}
}

А теперь там где отделил скетчи, в скетче Ардуино не чайно потерял первую библиотеку.

вот это интересный кусок.
Вы получаете из порта строчку и делите ее по запятым.
Кто вам сказал, что оператор int() из String делает целое?

Поправка - хотя нет, это же Процессинг… там так можно

А что, Processing этот место ошибки показывать не умеет?

Постоянно указывает на эту строчку и пишет “NullPointException”

str = str.trim();

Скорее всего этот самый str и есть Null. Проверьте.
Если так и есть, смотрите выше по коду, почему так получается.

Честно не знаю, но в образце работает.

Stream.readStringUntil() | Arduino Documentation
The entire String read from a stream, up to the terminator character. If the terminator character can’t be found, or if there is no data before the terminator character, it will return NULL.
Смотрите, что там у Вас такое в порт приходит.

 m.updateMeter(potVal);
  if (serial != null) {
  if (serial.available() > 0) {
    String str = serial.readStringUntil('\n');
    str = str.trim();
    String data[] = str.split(",");

Заменил значение (serial.available() > 0) на (serial.available() > 100), и все заработало. Даже если потенциометр устанавливать в ноль, все ок. Буду разбираться почему.

спасибо за информацию. сейчас попробую понять почему при значении 0 считалось как нет данных до разделителя, хотя потенциометр передавал данные согласно шкале на картинке в Processing. А, показывало до появления этой ошибки, а потом все зависало. То есть терялись данные.

Если написать значение больше 2 (или любое число начиная от двух и больше) вместо (serial.available() > 0), то скетч работает. Почему пока так и не понял. В скетче ардуино прописал передачу данных в буфер через определенные периоды, может с этим связано, но все равно точно не понимаю. Могу предположить что из за плохого контакта подключения данные скачут то в ноль то обратно, и только значение (serial.available() > 2) (и более) позволяет программе успевать с вычислениями.

Что тут понимать-то.
У вас от Ардуины приходит пустая строка, в которой только служебный символ окончания строки. После разделения пустой строки по запятым (которых в ней нет) - получается NULL и он дает ошибку.
Когда вы ставите (serial.available() > 2) - код принимает только не пустые строки, в которых что-то есть - и ошибка не возникает.

Спасибо большое, а подскажите пожалуйста, почему при (serial.available() > 1) проблема оставалась?

видимо потому, что

может состоять из двух байт \r\n