ArrayIndexOutOfBoundsException: 2 — Выход за пределы массива?

#arrays #string #split #arduino #processing

#массивы #строка #разделение #arduino #обработка

Вопрос:

Я отправляю 3 значения датчика из Arduino на обработку и разделяю строку на три элемента в массиве. Иногда, когда я запускаю программу, я получаю ошибку ArrayIndexOutOfBoundsException: 2, и, насколько я понимаю, это означает, что я пытаюсь получить доступ к элементу в массиве, которого там нет. Что я делаю не так?

Мой код из Processing и Arduino приведен ниже:

ОБРАБОТКА:

 import processing.serial.*;

Serial port;
float background;
float r1;
int a;
int b;
int c;
PrintWriter output;
Databox Data1 = new Databox(20, 20);
Databox Data2 = new Databox(20, 190);
Databox Data3 = new Databox(20, 360);

void setup() {
  size (690, 530);
  port = new Serial(this, "COM3", 9600);
  output = createWriter(hour()   "."   minute()   "."   second()   ".txt");
}

void draw() {
  background(60, 40);
  Data1.drawDataboxHumi();
  Data2.drawDataboxTemp();
  Data3.drawDataboxMoist();

  if (port.available() > 0) {
    String inString = port.readStringUntil('n');
    if (inString != null) {
      inString = trim(inString);
      String[] data = split(inString, '#');

      a = int(data[0]);
      b = int(data[1]);
      c = int(data[2]);

      output.println("Tidspunkt:"   " "   hour()   ":"   minute()   ":"   second()   " - " 
          "Luftfugtighed:"   a  "%"   " "  "Temperatur:"   b   " "   "Jordfugtighed:"   " "   c);
      output.flush();
    }
  }
}
 

ARDUINO:

 #include <dht.h>

dht DHT;

#define DHT11_PIN 7

void setup() {
  Serial.begin(9600);
  pinMode(A0, INPUT);
}

void loop() {
  int SensorValue = analogRead(A0); 
                                      

  int chk = DHT.read11(DHT11_PIN);

  Serial.print(DHT.humidity);
  Serial.print("#");
  Serial.print(DHT.temperature);
  Serial.print("#");
  Serial.print(SensorValue);
  Serial.println("#");
  delay(1500);
}
 

Комментарии:

1. как упоминает @ocrdu, данные могут быть потеряны или обработка может открыть порт, когда Arduino находится в середине отправки: может возникнуть ситуация, когда «пакет» может быть потерян. if(data.length == 4) Также дважды проверьте перед синтаксическим анализом a,b,c

Ответ №1:

Попробуйте проверить (путем печати), что port.readStringUntil('n') возвращается точно каждый раз, и таким же образом проверьте, что от него осталось после trim() .

Иногда может быть readStringUntil() время ожидания, а затем возвращается 0 только строка без каких-либо # s, которая будет split в массив из 1 элемента. Он также может каким-то образом считывать ложные данные, оставшиеся в буфере, с тем же эффектом.

Единственный способ выяснить это — проверить inString , как сказано выше.

Вы могли бы предотвратить ошибку во время выполнения, выполнив проверку количества элементов в String[] data , прежде чем обращаться к отдельным элементам массива, но это не решает основную проблему. Тем не менее, это может быть достаточно хорошо для ваших целей.

Замечание:

Вам не нужно отправлять последнюю (третью) # из Arduino; вам нужно только две для разделения Arduino String на три части, а наличие трех # s может привести к split получению четырех частей. Однако n в конце потребуется a .

Комментарии:

1. Похоже, время ожидания не истекло. Я удалил 3-й «#», но никаких видимых улучшений. Когда я его удаляю, 3-й вывод данных «sensorValue» отображается как 0 при обработке при запуске программы.

2. Выведите на экран, какой inString находится после строки String inString = port.readStringUntil(‘n’); точно, и какой inString находится после строки inString = trim(inString); Я подозреваю, что это скажет вам, что не так.

3. Кроме того, попробуйте проверить, работает ли он правильно, если вы уменьшите значение delay() на Arduino до 800; readStringUntil() имеет время ожидания по умолчанию 1 сек. Также смотрите Отредактированный ответ.

4. Trim, казалось, ничего не делал, поэтому я удалил его. Код основан на старом упражнении, которое я делал пару месяцев назад, так что это был просто остаток от этого. Похоже, проблема также устранена. Я вставил if-оператор if (data.length == 4){ a = int(data[0]); b = int(data[1]); c = int(data[2]); } после String[] data = split(inString, ‘#’); и, похоже, он выполнил свою работу. В массиве 4 элемента, но я не могу заставить его работать только с 3, удалив «#» в Arduino

5. Это предотвратит возникновение ошибки во время выполнения, но не решит основную проблему.