Arduino Serial.write 只发送了一半的数据
Arduino Serial.write only sends half of the data
我正在尝试将几条短裤从 Arduino Pro 转移到 Java 程序。问题是,我告诉 Arduino 发送的数据只有一半被实际发送了。
设置
Arduino 草图
我的 Arduino 草图是这样的:
// Mux control pins
#define s0 8
#define s1 9
#define s2 10
#define s3 11
// Mux in "SIG" pin
#define SIG_pin 3
byte lineEnd = 10; // ASCII-NL
void setup() {
/*
* Mux und Flex
*/
// Define Digital Pin 8,9,10 and 11 as Output
// The most right Bit is the lowest! The highest 2 Bits are not accessible!
// --> B[-][-][13][12][11][10][9][8]
DDRB = B00001111;
// Write LOW to Pin 8,9,10 and 11
PORTB = B00000000;
Serial.begin(SERIAL_PORT_SPEED);
delay(500);
}
void loop()
{
printMux(0);
printMux(1);
printMux(2);
printMux(3);
printMux(4);
printMux(5);
printMux(6);
printMux(7);
printMux(8);
printMux(9);
printMux(10);
printMux(11);
printMux(12);
printMux(13);
printMux(14);
Serial.write('\n');
delay(17);
}
void printMux(byte channel){
// Write the channel to Pin 8,9,10 and 11
// I'm using direct Port Manipulation to speed the whole thing up
PORTB = channel;
unsigned char bytes[2];
int val = analogRead(SIG_pin);
bytes[0] = (unsigned int) val >> 8;
bytes[1] = val;
Serial.write(bytes[0]);
Serial.write(bytes[1]);
}
Sketch 通过多路复用器读取 15 个 Flex 传感器的值,并将这些值作为字节写入串行。使用 Serial.print 不是一个选项,因为将值写入 ASCII 字节需要相当长的时间,而且要发送的字节更多。
Java 计划
在 Java 方面,我使用 Java 简单串行连接获取 Ardiuno 的串行输出,然后将字节解析回短裤。
import java.util.ArrayDeque;
import jssc.SerialPort;
import jssc.SerialPortException;
public class SerialTest {
final static int ASCII_NL = 10;
final static int ASCII_COMMA = 42;
final static String BLUETOOTH_PORT = "COM10";
final static String USB_PORT = "COM3";
final static boolean USE_BLUETOOTH = false;
public static void main(String[] args) {
final SerialPort sp = new SerialPort(USE_BLUETOOTH ? BLUETOOTH_PORT
: USB_PORT);
final ArrayDeque<Byte> byteVector = new ArrayDeque<>(48);
try {
sp.openPort();
sp.setParams(SerialPort.BAUDRATE_115200, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
Runnable r = new Runnable() {
@Override
public void run() {
while (true) {
try {
byte[] bytesRead = sp.readBytes(60);
if (bytesRead != null) {
for (byte b : bytesRead) {
if (b == ASCII_NL) {
// We have to wait for a whole line
// as a short is a 2 byte value
// 15 shorts produce 30 bytes
if (byteVector.size() == 30) {
byte[] buffer = new byte[byteVector
.size()];
for (int i = 0; i < byteVector
.size(); i++) {
buffer[i] = byteVector.poll();
}
extractValues(buffer);
}
byteVector.clear();
} else {
byteVector.add(b);
}
}
}
} catch (SerialPortException e) {
e.printStackTrace();
}
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t = new Thread(r);
t.start();
} catch (SerialPortException e) {
e.printStackTrace();
}
}
static void extractValues(byte[] buffer) {
for(byte b : buffer) {
System.out.print(b + " ");
}
System.out.println();
}
}
问题
至于测试目的,我只将接收到的字节打印到控制台。我期望这样的输出:
1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32
那些是 30 个字节,所以我们收到了 15 个短裤。
问题是输出看起来像这样:
1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
只有一半的字节被正确传输,其余的被发送为0
。
进一步的测试证实了这一点。当我将 Arduino Sketch 更改为仅发送 10 个值并相应地修改 Java 程序时,它会打印出 10 个值,后跟 10 个零。 Arduino 等发送的 4 个值也是如此。
为什么会这样?我是不是通过串口发送了太多数据,所以它在读取时只发送 0?我的 Java 程序有问题吗?这可能是 Java 简单串行通信库中的错误吗?
编辑
错误出在 Java SimpleSerialConnection 的某处,在更改为 Ardulink 与 Arduino 通信后,它几乎完美无缺。我正在为 JSSC 提交错误报告,案例已结案。
将您的问题拆分成多个部分:
- 用可靠的终端程序捕获Arduino的串口通信。
- 使用不同的程序来模拟所需的输出并查看您的 Java 代码是否正确捕获它。
- 限制输出以查看问题是否消失(会指向某些缓冲区溢出)
- 用ascii通信代替二进制,分析更方便
换句话说:确保它运行,然后调整性能。
我正在尝试将几条短裤从 Arduino Pro 转移到 Java 程序。问题是,我告诉 Arduino 发送的数据只有一半被实际发送了。
设置
Arduino 草图
我的 Arduino 草图是这样的:
// Mux control pins
#define s0 8
#define s1 9
#define s2 10
#define s3 11
// Mux in "SIG" pin
#define SIG_pin 3
byte lineEnd = 10; // ASCII-NL
void setup() {
/*
* Mux und Flex
*/
// Define Digital Pin 8,9,10 and 11 as Output
// The most right Bit is the lowest! The highest 2 Bits are not accessible!
// --> B[-][-][13][12][11][10][9][8]
DDRB = B00001111;
// Write LOW to Pin 8,9,10 and 11
PORTB = B00000000;
Serial.begin(SERIAL_PORT_SPEED);
delay(500);
}
void loop()
{
printMux(0);
printMux(1);
printMux(2);
printMux(3);
printMux(4);
printMux(5);
printMux(6);
printMux(7);
printMux(8);
printMux(9);
printMux(10);
printMux(11);
printMux(12);
printMux(13);
printMux(14);
Serial.write('\n');
delay(17);
}
void printMux(byte channel){
// Write the channel to Pin 8,9,10 and 11
// I'm using direct Port Manipulation to speed the whole thing up
PORTB = channel;
unsigned char bytes[2];
int val = analogRead(SIG_pin);
bytes[0] = (unsigned int) val >> 8;
bytes[1] = val;
Serial.write(bytes[0]);
Serial.write(bytes[1]);
}
Sketch 通过多路复用器读取 15 个 Flex 传感器的值,并将这些值作为字节写入串行。使用 Serial.print 不是一个选项,因为将值写入 ASCII 字节需要相当长的时间,而且要发送的字节更多。
Java 计划
在 Java 方面,我使用 Java 简单串行连接获取 Ardiuno 的串行输出,然后将字节解析回短裤。
import java.util.ArrayDeque;
import jssc.SerialPort;
import jssc.SerialPortException;
public class SerialTest {
final static int ASCII_NL = 10;
final static int ASCII_COMMA = 42;
final static String BLUETOOTH_PORT = "COM10";
final static String USB_PORT = "COM3";
final static boolean USE_BLUETOOTH = false;
public static void main(String[] args) {
final SerialPort sp = new SerialPort(USE_BLUETOOTH ? BLUETOOTH_PORT
: USB_PORT);
final ArrayDeque<Byte> byteVector = new ArrayDeque<>(48);
try {
sp.openPort();
sp.setParams(SerialPort.BAUDRATE_115200, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
Runnable r = new Runnable() {
@Override
public void run() {
while (true) {
try {
byte[] bytesRead = sp.readBytes(60);
if (bytesRead != null) {
for (byte b : bytesRead) {
if (b == ASCII_NL) {
// We have to wait for a whole line
// as a short is a 2 byte value
// 15 shorts produce 30 bytes
if (byteVector.size() == 30) {
byte[] buffer = new byte[byteVector
.size()];
for (int i = 0; i < byteVector
.size(); i++) {
buffer[i] = byteVector.poll();
}
extractValues(buffer);
}
byteVector.clear();
} else {
byteVector.add(b);
}
}
}
} catch (SerialPortException e) {
e.printStackTrace();
}
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t = new Thread(r);
t.start();
} catch (SerialPortException e) {
e.printStackTrace();
}
}
static void extractValues(byte[] buffer) {
for(byte b : buffer) {
System.out.print(b + " ");
}
System.out.println();
}
}
问题
至于测试目的,我只将接收到的字节打印到控制台。我期望这样的输出:
1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32
那些是 30 个字节,所以我们收到了 15 个短裤。
问题是输出看起来像这样:
1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
只有一半的字节被正确传输,其余的被发送为0
。
进一步的测试证实了这一点。当我将 Arduino Sketch 更改为仅发送 10 个值并相应地修改 Java 程序时,它会打印出 10 个值,后跟 10 个零。 Arduino 等发送的 4 个值也是如此。
为什么会这样?我是不是通过串口发送了太多数据,所以它在读取时只发送 0?我的 Java 程序有问题吗?这可能是 Java 简单串行通信库中的错误吗?
编辑
错误出在 Java SimpleSerialConnection 的某处,在更改为 Ardulink 与 Arduino 通信后,它几乎完美无缺。我正在为 JSSC 提交错误报告,案例已结案。
将您的问题拆分成多个部分:
- 用可靠的终端程序捕获Arduino的串口通信。
- 使用不同的程序来模拟所需的输出并查看您的 Java 代码是否正确捕获它。
- 限制输出以查看问题是否消失(会指向某些缓冲区溢出)
- 用ascii通信代替二进制,分析更方便
换句话说:确保它运行,然后调整性能。