你需要:
- 将 Simulink 中的每个字节一次缓冲到处理中:串行的
buffer() / serialEvent() / readBytes(bytesFromSimulink) 在这里可以很好地协同工作
- 将字节打包成一个int(根据需要移动字节)并
OR-ing它们:
int intBits = bytesFromSimulink[3] << 24 | bytesFromSimulink[2] << 16 | bytesFromSimulink[1] << 8 | bytesFromSimulink[0];
- 通过
Float.intBitsToFloat()将int转换为float:floatFromSimulink = Float.intBitsToFloat( intBits );
这里有一个基本草图来说明上述想法:
import processing.serial.*;
// how many bytes are expecting sent in one go
final int SERIAL_BUFFER_SIZE = 4;
// pre-allocate serial read buffer
byte[] bytesFromSimulink = new byte[SERIAL_BUFFER_SIZE];
// float from bytes
float floatFromSimulink;
// serial port reference
final String PORT_NAME = "COM2";
final int BAUD_RATE = 115200;
Serial simulinkPort;
void setup(){
size(300, 300);
try{
simulinkPort = new Serial(this, PORT_NAME, BAUD_RATE);
// only fire serialEvent() when the right number of bytes has been buffered
simulinkPort.buffer(SERIAL_BUFFER_SIZE);
}catch(Exception e){
println("error opening serial port(" + PORT_NAME + "): double check the port name, wiring and make sure the port isn't already open in another application");
e.printStackTrace();
exit();
}
}
void draw(){
background(0);
// format bytes to hex and float to 2 decimal places
text(String.format("hex: %s\nfloat: %.2f", hex(byteFromSimulink), floatFromSimulink),
10, 15);
}
void serialEvent(Serial port) {
port.readBytes(bytesFromSimulink);
// pack bytes into a 32bit int (shifting each byte accordingly): double check the byte order (e.g. LSB / MSB)
int intBits = bytesFromSimulink[3] << 24 |
bytesFromSimulink[2] << 16 |
bytesFromSimulink[1] << 8 |
bytesFromSimulink[0];
// convert int to to float
floatFromSimulink = Float.intBitsToFloat( intBits );
}
// pretty-print byte array
String hex(byte[] data){
String output = "";
for(byte singleByte : data){
output += hex(singleByte) + ' ';
}
return output;
}
希望以上内容可以正常工作,但请记住它是未经测试的代码。
我认为有两件事可能会出错:
- 字节未按正确顺序到达。 (假设 Simulink 连续流式传输串行数据,但处理稍后开始,仅从第 2、3 或 4 个字节而不是第一个字节捕获数据:数据将被移位)。您可以尝试使用阻塞循环删除
buffer()/serialEvent(),一次获取一个字节(例如if(simulinkPort.available() >= 1) myNewByte = simulinkPort.read();)并手动将字节计数/打包到字节数组中。您也可以尝试呼叫/响应方法:例如Simulink 不会发送任何数据,直到它从 Processing 接收到单个字符(比如“A”),然后开始流式传输,因此 Processing 从一开始就准备好一次缓冲 4 个字节。
- 我不确定从 simulink 发送字节的顺序:上面我假设从右到左,但它只是交换索引的另一种方式:
int intBits = byteFromSimulink[0] << 24 | byteFromSimulink[1] << 16 | byteFromSimulink[2] << 8 | byteFromSimulink[3];
Java/Processing 中的另一个问题是字节从 -127 到 127,因此在检查时需要屏蔽字节:println(myByte & 0xFF);
根据 g00se 在下面 cmets 中的建议,这里尝试使用 ByteBuffer 选项:
import java.nio.ByteBuffer;
import processing.serial.*;
// how many bytes are expecting sent in one go
final int SERIAL_BUFFER_SIZE = 4;
// pre-allocate serial read buffer
ByteBuffer bytesFromSimulink;
// float from bytes
float floatFromSimulink;
// serial port reference
final String PORT_NAME = "COM2";
final int BAUD_RATE = 115200;
Serial simulinkPort;
void setup(){
size(300, 300);
try{
simulinkPort = new Serial(this, PORT_NAME, BAUD_RATE);
// only fire serialEvent() when the right number of bytes has been buffered
simulinkPort.buffer(SERIAL_BUFFER_SIZE);
bytesFromSimulink = ByteBuffer.allocate(SERIAL_BUFFER_SIZE);
}catch(Exception e){
println("error opening serial port(" + PORT_NAME + "): double check the port name, wiring and make sure the port isn't already open in another application");
e.printStackTrace();
exit();
}
}
void draw(){
background(0);
// format bytes to hex and float to 2 decimal places
text(String.format("hex: %s\nfloat: %.2f", hex(bytesFromSimulink), floatFromSimulink),
10, 15);
}
void serialEvent(Serial port) {
// pass new data to the byte buffer
bytesFromSimulink.put(port.readBytes(SERIAL_BUFFER_SIZE));
// set the index back to 0
bytesFromSimulink.rewind();
// read the first (rewinded) 4 bytes as a float
floatFromSimulink = bytesFromSimulink.getFloat();
}
// pretty-print byte array
String hex(ByteBuffer data){
String output = "";
for(int i = 0 ; i < data.limit(); i++){
output += hex(data.get(i)) + ' ';
}
return output;
}