Проблемы с взаимодействием датчика Arduino MPU6050 и обработки - PullRequest
1 голос
/ 28 мая 2020

У меня есть гироскоп и акселерометр MPU6050, подключенные к Arduino по протоколу I2 C. Эти датчики отправляют непрерывный поток данных в последовательный порт с помощью следующих инструкций (в Arduino IDE):

Serial.print(euler[0] * 180/M_PI);
Serial.print(":");
Serial.print(euler[1] * 180/M_PI);
Serial.print(":");
Serial.println(euler[2] * 180/M_PI);

Это взято из примерного скетча, включенного в библиотеку датчика, и он просто отправляет значение yaw / pitch / roll к последовательному порту, разделенные двоеточием.

Теперь самое интересное. Я всегда увлекался визуализацией данных, и поэтому я хочу построить своего рода график этих данных, поступающих из последовательного порта в обработке (это часть более крупного проекта, который включает в себя ультразвуковой датчик c, вроде радара. ).

Итак, я написал небольшой набросок обработки, чтобы уловить эти данные с целью их анализа и визуализации. Это набросок:

import processing.serial.*;

Serial myPort;

String data; //Angle values

String[] splitted; //Array containing splitted data

float yaw, pitch , roll;



void setup()
{
  myPort = new Serial (this, Serial.list()[0], 115200);

}

void draw()
{

  while (myPort.available() > 0) //data arrived fromm serial
  {

    data = myPort.readStringUntil('\n');

    //Data Parsing
    splitted = data.split(":");

    yaw = float(splitted[0]);
    pitch = float(splitted[1]);
    roll = float(splitted[2]);

    println(yaw + "  " + pitch + "  " + roll);


  }



}

Этот код не работает. Есть 2 ошибки, которые чередуются. Один из них:

ArrayIndexOutOfBondsException

А другой:

NullPointerException

Это указывает на "разделенный" массив.

Думаю, проблема у меня. В предыдущей версии скетча обработки я использовал:

readString() function

Я думаю, что, поскольку данные отправляются на последовательный порт в скетче Arduino по одному, скетч обработки иногда ловит только один , или два из значений рыскания, тангажа и крена, в результате чего индекс массива становится cra sh или nullPointerexception, когда в массив не добавляется никакого значения. Затем я изменил '' 'readString' '' на '' 'readStringUntil (' \ n ')' '' ', потому что, возможно, первый пакет будет потерян, но следующий, следующий за ним, всегда будет улавливаться, не нарушая их ( ловлю всю строчку). Но есть те же ошибки, поэтому я думаю, что мой небольшой опыт больше не может помочь в решении проблемы. Мне нужна ваша помощь.

Извините за плохой английский sh, и спасибо за любую помощь.

Ответы [ 2 ]

2 голосов
/ 28 мая 2020

Вы на правильном пути. Вот несколько указателей:

  • вы можете использовать блок try/catch, чтобы скетч не просто sh при ошибке
  • вас можно использовать bufferUntil(), чтобы указать последовательной библиотеке буферизовать байты для вас, пока не встретится новая строка: он хорошо работает в тандеме с serialEvent(), который вызывается автоматически (так что вы не нужно использовать while l oop, что заблокировало бы рендеринг / остальную часть скетча)
  • вы можете проверить (и должны) все, что может go неправильно с данными (null строка, пустая строка, недостаточно значений в строке и т.д. c.)

Вот измененная версия вашего скетча:

import processing.serial.*;

Serial myPort;

float yaw, pitch , roll;

void setup()
{

  String[] portNames = Serial.list();
  // skipp serial setup if there are no ports
  if(portNames.length == 0){
    println("no serial ports found");
    return;
  }

  // try to open serial port, handle error
  try
  {
    myPort = new Serial (this, portNames[0], 115200);
    // buffer bytes(characters) until new line is hit
    myPort.bufferUntil('\n');
  }
  catch(Exception e)
  {
    println("error opening port: " + portNames[0]);
    println("double check the port is present and not used by other applications (e.g. SerialMonitor)");
    e.printStackTrace();
  }

}

void draw()
{

  background(0);
  text(String.format("yaw: %.2f \npitch: %.2f \nroll: %.2f", yaw, pitch, roll), 5, 15);
}

// serialEvent gets called when there's new data: no need an explicit blocking while loop
void serialEvent(Serial port){
  try
  {
    // read string from serial  
    String rawSerialString = port.readString();
    // exit on null string
    if(rawSerialString == null)
    {
      println("received null string, skipping this serial message");
      return;
    }
    // exit on empty string
    if(rawSerialString.length() == 0)
    {
      println("received empty string, skipping this serial message");
      return;
    }

    // trim white space (\r, \n, etc.)
    rawSerialString = rawSerialString.trim();
    // split and convert to float
    float[] rotations = float(rawSerialString.split(":"));

    // exit if message got jumbled up and values are missing
    if(rotations.length < 3)
    {
      println("received less than 3 values, skipping this serial message");
      return;
    }

    // finally extract values
    yaw   = rotations[0];
    pitch = rotations[1];
    roll  = rotations[2];

    println(yaw + "  " + pitch + "  " + roll);

  }
  catch(Exception e)
  {
    println("error reading/parsing serial data");
    e.printStackTrace();
  }

}
0 голосов
/ 28 мая 2020

Очевидно, вы получаете строки с менее чем двумя двоеточиями.

Отсюда трудно сказать, что вы должны делать, но проверка длины разделенного массива в любом случае была первым шагом. Либо через if, либо как Exception.

...