对于大学作业,我正在编写一个Java应用程序,它将为交互式LED表格运行一些游戏逻辑。桌子本身受2个Arduino Duemilanove或1个Arduino Mega 2560的控制。
要向Arduino提供有关应以哪种颜色点亮哪些LED的信息,我通过串行端口将数据从Raspberry Pi 3b +发送到Arduino。由于表格由14个LED灯带组成,每个LED灯带14个LED,并且每个LED都有3个颜色值(RGB),因此我将表格的数据存储在int [14] [14] [3]数组中。
在将数组发送到Arduino之前,我创建了它的JSON对象(使用Jackson库),然后使用jSerialComm将其作为字符串发送。根据我使用的Arduino设置,我还可以在创建JSON对象之前将整个数组传输到JSON或将其拆分为两个int [7] [14] [3]数组。
当我使用2个Arduinos和jSerialComm时,由于数据以错误的顺序到达串行端口,所以我现在得到了一个新的Arduino Mega 2560(因为其他SO问题表明,由于PL2303模块过时,可能会出现错误的数据顺序),并且再次尝试,结果相同。经过一些进一步的研究,我现在尝试使用JSSC代替jSerialComm,但是仍然显示出相同的结果。
我用来将数据发送到arduino的java类看起来像这样(注释过的代码是我使用jSerialComm / 2 Arduino的代码):
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上的处理如下:
#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])时:
[[[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0, 0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0] ,[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0],[0,0,0] ,[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[ 0,0,0],[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[ 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()开始):
可以看到第一个RGB值已正确传输,但是在少于一个完整的LED灯条之后,数据以错误的顺序到达,并且(如您在图片末尾所见)在某些时候完全停止显示向上,这可能表示不再读取任何数据。
我一直在尝试诸如PL2303过时或损坏的情况下更改Arduino之类的事情,以及尝试用于串行通信的不同库,但是我无法弄清楚自己在做什么错。我已经花了30多个小时尝试各种无济于事的方法,所以事情真的让我感到沮丧。
更新
根据B.Letz的建议,我正确设置了数据,停止和奇偶校验位(现在是8个数据,1个停止且没有奇偶校验位)。通过阅读arduino反馈,我仍然得到相同的结果,但是经过一些星期的学习,我意识到问题可能出在我的Serial.print显然导致了Arduino的巨大滞后,因此它无法正确,及时地处理所有数据。在执行处理之前删除了第一个Serial.print调用之后,我现在看到正在传输的第一个矩阵已由Arduino正确打印。但是,由于某种原因,所有进一步传输的数据都会由Arduino打印null
。我会尝试扩展超时,以防由于Arduino端超时而导致空指针出现。
更新2
与我的假设相反,重新配置超时并不能解决问题。我还发现,在发送第一个JSON对象后,Arduino打印null
到控制台,并且在收到第二个JSON对象之后才向我发送第一个JSON对象。但是,这是我唯一一次从Arduino获得除null
以外的任何反馈的情况。我还注意到,当我通过串行监视器发送JSON字符串时,Arduino立即打印正确的字符串 BUT ,它还会打印一个空的新行,并且不响应任何形式的任何新数据
答案 0 :(得分:0)
解决方案的第一步是每次读取新字符时都删除不必要的Serial.print()
调用。删除此行后,我可以确认数据正确到达。
正如我在第二篇更新中提到的,反馈已转移:
我还发现,在发送第一个JSON对象后,Arduino将null打印到控制台,并且仅在收到第二个JSON对象后才向我发送第一个JSON对象。但是,这是我唯一一次从Arduino获得任何反馈的情况,除了null
发生这种情况是由于在调用read()
函数之前,我在Java应用程序端没有等待足够长的时间来等待数据到达。解决此问题后,我始终会收到正确的字符串。
尝试使用DynamicJsonDocument
和StaticJsonDocument
进行不同的配置我现在最终使用了DynamicJsonDocument
,但是StaticJsonDocument
也可能在这里工作。
一个相当不愉快的问题是,在void process
的内部for循环中,我无意中将计数器变量与外部for循环的计数器变量进行了比较,尽管我能够在for-之外的那一点上检索正确的数据。循环。
此问题中的问题得以解决,但是现在出现了更大的问题,因为我一开始实现代码就无法从接收到的JSON对象中检索任何数据用于控制LED并在我的代码中的任何时候调用row[i].setPixelColor(j, row[i].Color(values[i][j][0], values[i][j][1], values[i][j][2]));
。因此,总结一下这个特定的调用是代码无法正常工作的实际原因。
我将为该新问题打开一个新问题,因为它在主题上不属于该问题,但是一旦编写,我将在此处添加引用。
更新
有关使用Adafruit的NeoPixel库解决7个以上LED灯条的新问题,可以找到here。