三维数组到达串口顺序错误 [英] Three-dimensional array arrives in wrong order at serial port

查看:28
本文介绍了三维数组到达串口顺序错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于大学作业,我正在编写一个 Java 应用程序,该应用程序将为交互式 LED 表运行一些游戏逻辑.桌子本身由 2 个 Arduino Duemilanove 或 1 个 Arduino Mega 2560 控制.

For an university assignment I'm writing a java application that will run some game logic for an interactive LED table. The table itself is being controlled by either 2 Arduino Duemilanove or 1 Arduino Mega 2560.

为了向 Arduino(s) 提供有关哪些 LED 应该以哪种颜色点亮的信息,我通过串行端口从 Raspberry Pi 3b+ 向 Arduinos 发送数据.由于该表由 14 个 LED 灯条组成,每个 LED 灯条有 14 个 LED,每个 LED 有 3 个颜色值 (RGB),因此我将有关该表的数据存储在一个 int[14][14][3] 数组中.

To give the Arduino(s) information about which LEDs should be lit in which color I send the data over the serial port from a Raspberry Pi 3b+ to the Arduinos. As the table consists of 14 LED strips with 14 LEDs per LED strip and each LED has 3 color values (RGB) I store the data about the table in an int[14][14][3] array.

在将数组发送到 Arduino 之前,我创建了它的 JSON 对象(使用 Jackson 库),然后使用 jSerialComm 将数组作为字符串发送.根据我使用的 Arduino 设置,在创建 JSON 对象之前,我还可以将整个数组传输到 JSON 或将其拆分为两个 int[7][14][3] 数组.

Before sending the array to the Arduino I create a JSON object of it (using the Jackson library) and then send the array as a String using jSerialComm. Depending on which Arduino setup I use I also either transfer the whole array to JSON or split it into two int[7][14][3] arrays before creating the JSON object.

当我使用 2 个 Arduinos 和 jSerialComm 时,数据以错误的顺序到达串行端口,我现在得到了一个新的 Arduino Mega 2560(因为其他 SO 问题表明可能由于过时的 PL2303 模块而导致错误的数据顺序)和再次尝试,结果相同.经过一些进一步的研究,我现在尝试使用 JSSC 而不是 jSerialComm,但仍然出现相同的结果.

As the data arrived in the wrong order at the serial port when I used 2 Arduinos and jSerialComm I now got a new Arduino Mega 2560 (as other SO questions suggested the wrong data order might occur due to an outdated PL2303 module) and tried it again with the same result. After some further research I now tried using JSSC instead of jSerialComm but still the same result shows up.

我用来将数据发送到 arduino 的 java 类如下所示(注释掉的代码是我使用 jSerialComm/2 Arduinos 的代码):

The java class that I use to send the data to the arduino looks like this (the outcommented code being the code where I used jSerialComm / 2 Arduinos):

package de.pimatrix.backend;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fazecast.jSerialComm.SerialPort;

import jssc.SerialPortException;

public class SerialThread implements Runnable {

    public static SerialPort arduino1, arduino2;
    private int[][][] matrix = new int[14][14][3];

    private int[][][] matrixLeft = new int[7][14][3];
    private int[][][] matrixRight = new int[7][14][3];

    private Socket localHost;
    private Matrix matrixData;
    private ObjectInputStream in;

    @Override
    public void run() {

        SerialJSONWriter writer = new SerialJSONWriter();

        ServerSocket ss = null;
        localHost = null;
        matrixData = new Matrix(matrix);
        try {
            ss = new ServerSocket(62000); // erstellen eines lokalen Sockets auf Port 62000, um die zu übertragende
                                            // Matrix vom ClientThread
        } catch (IOException e) {
        }

        while (true) {
            try {
                localHost = ss.accept();
            } catch (Exception e) {
                e.printStackTrace();
            }
            initializeInputStream();
            waitForMatrix();
            splitMatrix();

            try {
                writer.tryWrite(matrixRight, matrixLeft);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void splitMatrix() {
        for (int i = 0; i < 14; i++) {
            for (int j = 0; j < 14; j++) {
                if (i <= 6) {
                    matrixRight[i][j][0] = matrix[i][j][0];
                    matrixRight[i][j][1] = matrix[i][j][1];
                    matrixRight[i][j][2] = matrix[i][j][2];
                } else {
                    matrixLeft[i - 7][j][0] = matrix[i][j][0];
                    matrixLeft[i - 7][j][1] = matrix[i][j][1];
                    matrixLeft[i - 7][j][2] = matrix[i][j][2];
                }
            }
        }
    }

    private void initializeInputStream() {
        try {
            InputStream input = localHost.getInputStream();
            in = new ObjectInputStream(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void waitForMatrix() {
        System.out.println("Waiting for Matrix");
        try {
            matrixData = (Matrix) in.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        this.matrix = matrixData.matrix;
    }

    class SerialJSONWriter implements AutoCloseable {

        // Zuweisen der seriellen Ports
//      private final SerialPort /*arduino1, arduino2,*/ arduinoMega;
        private jssc.SerialPort arduinoMega;

        public SerialJSONWriter() {
//          arduino1 = SerialPort.getCommPort("COM5");
//          arduino2 = SerialPort.getCommPort("COM6");
//          arduinoMega = SerialPort.getCommPort("COM7");
            arduinoMega = new jssc.SerialPort("COM7");
            try {
                arduinoMega.openPort();
                arduinoMega.setParams(115200, 8, 1, jssc.SerialPort.PARITY_EVEN);
            } catch (SerialPortException e) {
                e.printStackTrace();
            }
//          arduinoMega.setBaudRate(115200);
//          arduinoMega.setNumDataBits(8);
//          arduinoMega.setNumStopBits(1);
//          arduinoMega.setParity(0);


            // setzen der Timeouts für die Kommunikation mit den Arduinos
//          arduino1.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);
//          arduino2.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);
//          arduinoMega.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);
//          arduino1.setBaudRate(115200);
//          arduino2.setBaudRate(115200);
//          arduinoMega.setBaudRate(115200);
//          arduino1.openPort();
//          arduino2.openPort();
//          arduinoMega.openPort();
//          arduino1.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 0,
//                  0);
//          arduino2.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 0,
//                  0);

//          arduinoMega.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 0,
//                  0);
        }

        public void write() {

        }

        private void tryWrite(Object dataRight, Object dataLeft) throws IOException {
            String dataAsJSONRight = new ObjectMapper().writeValueAsString(dataRight) + "\n";
            String dataAsJSONLeft = new ObjectMapper().writeValueAsString(dataLeft) + "\n";
            try {
                arduinoMega.writeString(dataAsJSONRight);
            } catch (SerialPortException e) {
                e.printStackTrace();
            }
//          for (int i = 0; i < dataAsJSONRight.length(); i++) {
////                arduino1.getOutputStream().write(dataAsJSONRight.getBytes()[i]);
//              System.out.println(dataAsJSONRight);
//              arduinoMega.getOutputStream().write(dataAsJSONRight.getBytes()[i]);
//          }
//          for (int i = 0; i < dataAsJSONLeft.length(); i++) {
////                arduino2.getOutputStream().write(dataAsJSONLeft.getBytes()[i]);
//              arduinoMega.getOutputStream().write(dataAsJSONLeft.getBytes()[i]);
//          }
        }

        @Override
        public void close() throws Exception {
//          arduino1.closePort();
//          arduino2.closePort();
            arduinoMega.closePort();
        }
    }
}

在 Arduino(s) 上,处理过程如下所示:

On the Arduino(s) the processing looks like this:

#include <ArduinoJson.h>
#include <Adafruit_NeoPixel.h>

#define PINROW0 2
#define PINROW1 3
#define PINROW2 4
#define PINROW3 5
#define PINROW4 6
#define PINROW5 7
#define PINROW6 8

#define NUMPIXELS 14 //Amount of pixels per row

Adafruit_NeoPixel row[] = { //Intitialize the array, that contains the addressable LED strips in the Adafruit format
  Adafruit_NeoPixel(NUMPIXELS, PINROW0, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUMPIXELS, PINROW1, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUMPIXELS, PINROW2, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUMPIXELS, PINROW3, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUMPIXELS, PINROW4, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUMPIXELS, PINROW5, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUMPIXELS, PINROW6, NEO_GRB + NEO_KHZ800)
};

#define DELAY 1000 //set refresh cycle to 10 milliseconds
#define NUMSTRIPS 7/*(sizeof(row)/sizeof(row[0]))*/ //Amount of connected LED strips


int values[7][14][3];
int c = 0;
String matrixAsString = "";

void setup() {

  /*Setup serial port on which the Pi connects to the Arduino*/
  Serial.begin(115200); //set baudrate to 115200 Bit per second
  Serial.setTimeout(1000);

  Serial.println(100);

  /*initialize NeoPixel Library*/
  for (int i = 0; i < NUMSTRIPS; i++) {
    row[i].begin();
    row[i].show();
  }
}

void process(String matrixAsString) {
  StaticJsonDocument<4372> doc;
  Serial.println(matrixAsString);
  deserializeJson(doc, matrixAsString);

  for (int i = 0; i < 7; i++) {
    for (int j = 0; i < 14; j++) {
      values[i][j][0] = values[i][j][1] = values[i][j][2] = (int) (doc[i][j][0]);
    }
  }
}

//infinite loop refreshing the matrix
void loop() {

  while (Serial.available()) {
    char c = Serial.read();
    Serial.println(matrixAsString);
    matrixAsString += c;
    if (c == '\n') {
      process(matrixAsString);
      matrixAsString = "";
    }

  }

}

当发送一个半矩阵的数据时(所以一个 int[7][14][3]):

When sending the data for a half matrix (so an int[7][14][3]):

[[[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[255,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]]

[[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[255,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]]

通过 Arduino IDE 中的串行监视器,我从 Arduino 获得此输出(从 void loop 中的 Serial.println() 开始):

through the serial monitor in the Arduino IDE I get this output from the Arduino (as of the Serial.println() in void loop):

正如人们所看到的,第一个 RGB 值被正确传输,但是在不到一个完整的 LED 灯条后,数据以错误的顺序到达并且(如您在图片末尾看到的)在某些时候完全停止显示up,这可能表示不再读取任何数据.

As one can see the first RGB values are transmitted correctly, however after even less than one complete LED strip the data arrives in the wrong order and (as you can see at the end of the picture) at some point completely stops showing up, which probably indicates no data is being read any more.

我一直在尝试很多事情,比如更换 Arduino 以防 PL2303 过时或有缺陷,以及尝试不同的库进行串行通信,但是我无法弄清楚我做错了什么.我已经花了 30 多个小时尝试不同的方法但无济于事,所以事情对我来说变得非常令人沮丧.

I've been trying a hell of things like changing the Arduino in case the PL2303 is outdated or defective as well as trying different libraries for serial communication however I cannot figure out what I'm doing wrong. I've spent over 30 hours trying different approaches to no avail so things are becoming really frustrating for me.

更新

正如 B.Letz 所建议的,我正确设置了数据、停止位和奇偶校验位(现在8 个数据,1 个停止位,无奇偶校验位).通过阅读 arduino 反馈,我仍然得到了相同的结果,但经过一些 tweeking 之后,我意识到问题可能是我的 Serial.print 显然导致了 Arduino 的大量延迟,因此它无法正确及时地处理所有数据.在进行处理之前删除第一个 Serial.print 调用后,我现在看到正在传输的第一个矩阵被 Arduino 正确打印.然而,出于某种原因,对于所有进一步传输的数据,Arduino 打印 null.我将尝试延长超时时间,以防因 Arduino 端超时而出现空指针.

As suggested by B.Letz I got the setup of the data, stop and parity bits right (now being 8 data, 1 stop and no parity bits). By reading the arduino feedback I still got the same results but after some tweeking I recognized that the problem probably was that my Serial.print apparently led to a massive lag on the Arduino so it couldn't handle all the data correctly and in time. After removing the first Serial.print call before doing the processing I now see the first matrix that is being transmitted being printed correctly by the Arduino. However for some reason for all further transmitted data the Arduino prints null. I'll try extending the timeouts in case the null pointer occurs due to a timeout on the Arduino-side.

更新 2

与我的假设相反,重新配置超时并没有解决问题.我还发现在发送第一个 JSON 对象后,Arduino 会将 null 打印到控制台,并且仅在收到第二个 JSON 对象后才向我发送第一个 JSON 对象.然而,这是我唯一一次从 Arduino 得到任何反馈,除了 null.我还注意到,当我通过串行监视器发送 JSON 字符串时,Arduino 会立即打印正确的字符串 BUT 它还打印一个空的新行并且不响应任何类型的任何新数据.

Opposed to my assumption reconfiguring the timeouts didn't solve the problem. I also figured out that after the first JSON Object is sent the Arduino prints null to the console and only sends me the first JSON object after receiving the second JSON object. However this is the only time I get any feedback from the Arduino except null. What I also noticed is that when I send the JSON String over the serial monitor the Arduino instantly prints the correct String BUT it also prints an empty new line and doesn't respond to any new data in any kind.

推荐答案

工作解决方案的第一步是在每次读取新字符时删除不必要的 Serial.print() 调用.删除此行后,我可以确认数据正确到达.我在第二次更新帖子中提到的转移反馈:

The first step for a working solution was removing the unnecessary Serial.print() call everytime a new char was read. After removing this line I could confirm the data arrived properly. The shifted feedback as mentioned in my second update to the post:

我还发现,在发送第一个 JSON 对象后,Arduino 会将 null 打印到控制台,并且仅在收到第二个 JSON 对象后才向我发送第一个 JSON 对象.然而,这是我唯一一次从 Arduino 得到任何反馈,除了 null

I also figured out that after the first JSON Object is sent the Arduino prints null to the console and only sends me the first JSON object after receiving the second JSON object. However this is the only time I get any feedback from the Arduino except null

发生的原因是,在调用 read() 函数之前,我没有在 Java 应用程序端等待足够长的数据到达.解决这个问题后,我总是收到正确的字符串.

occured due to the fact that I didn't wait long enough on the java application side for data to arrive before calling the read() function. After solving this I always received the correct string.

使用 DynamicJsonDocumentStaticJsonDocument 尝试不同的配置我现在最终使用了 DynamicJsonDocument 但也使用了 StaticJsonDocument可能在这里工作过.一个相当不愉快的问题是,在 void process 的内部 for 循环中,我不小心将计数器变量与外部 for 循环的计数器变量进行了比较,尽管我能够在外部检索到正确的数据for 循环.

Trying out different configurations with either DynamicJsonDocument and StaticJsonDocument I now ended up using DynamicJsonDocument however also a StaticJsonDocument might have worked here. A rather unpleasant issue was that in the inner for-loop in void process I accidently compared the counter variable to that of the outer for-loop, although I was able to retrieve the correct data at that point outside of the for-loop.

this 问题中提出的问题因此得到解决,但是现在出现了更大的问题,因为一旦我开始实施代码,我就无法从接收到的 JSON 对象中检索任何数据用于控制 LED 并调用 row[i].setPixelColor(j, row[i].Color(values[i][j][0], values[i][j][1], values[i]][j][2])); 在我的代码中的任何一点.所以总结一下,这个特定的调用是代码不能正常工作的真正原因.

The problem asked in this questions is thereby solved, however a even bigger problem now occured as I'm not able to retrieve any data from the received JSON object as soon as I start implementing the code for controlling the LEDs and call row[i].setPixelColor(j, row[i].Color(values[i][j][0], values[i][j][1], values[i][j][2])); at any point in my code. So to sum things up this specific call is the actual reason that the code doesn't work properly.

我将针对这个新问题提出一个新问题,因为它在主题上不属于这个问题,但是一旦写好,我会在此处添加对它的引用.

更新

关于使用 Adafruit 的 NeoPixel 库解决超过 7 个 LED 灯条的新问题可以在 此处.

The new question regarding addressing more than 7 LED strips using Adafruit's NeoPixel library can be found here.

这篇关于三维数组到达串口顺序错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆