从串口接收数据作为处理编程中的浮点数 [英] receive data as float in processing programming from serial port

查看:27
本文介绍了从串口接收数据作为处理编程中的浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是来自arduino的代码:

below is a code from arduino:


typedef union{
  float number;
  uint8_t bytes[4];
} FLOATUNION_t;

FLOATUNION_t myValue;

float getFloat(){ 
 int cont = 0; 
 FLOATUNION_t f; 
 while (cont < 4 ){ 
 f.bytes[cont] = Serial.read() ; 
 cont = cont +1; 
 } 
 return f.number; 
}

是否有任何替代方法来处理编程(java)?

is there any alternative to this for processing programming(java)?

我完全需要一个从串口接收二进制数据的代码,我希望在处理编程中使用浮点类型的数据.

totally i need a code which recieve binary data from serial port and i want that data in float type in processing programming.

最初我通过 Simulink 中的串行发送块发送一些数据来处理编程,我正在使用 processing.serial 库,但我无法获取这些位并将它们转换为浮点数或整数.

originally i am sending some data through serial send block in Simulink to processing programming, i am using processing.serial library , but i could not get thise bits and convert them to float or int.

推荐答案

您需要:

  1. 将每个字节从 Simulink 缓冲一次到 Processing:Serial 的 buffer()/serialEvent()/readBytes(bytesFromSimulink) 可以在这里协同工作很好
  2. 将字节打包成一个 int(根据需要移动字节)并对它们进行 OR 运算:int intBits = bytesFromSimulink[3] <<24 |bytesFromSimulink[2] <<16 |bytesFromSimulink[1] <<8 |bytesFromSimulink[0];
  3. 通过 Float.intBitsToFloat() 将 int 转换为浮点数:floatFromSimulink = Float.intBitsToFloat(intBits);
  1. buffer each byte a time from Simulink into Processing: Serial's buffer() / serialEvent() / readBytes(bytesFromSimulink) could work nicely in tandem here
  2. pack the bytes into a an int (shifting bytes as needed) and OR-ing them: int intBits = bytesFromSimulink[3] << 24 | bytesFromSimulink[2] << 16 | bytesFromSimulink[1] << 8 | bytesFromSimulink[0];
  3. convert the int to a float via Float.intBitsToFloat(): floatFromSimulink = Float.intBitsToFloat( intBits );

这是说明上述想法的基本草图:

Here's a basic sketch to illustrate the ideas above:

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;
}

希望以上能正常工作,但请记住这是未经测试的代码.我认为有两件事可能会出错:

Hopefully the above just works, but bare in mind it's untested code. There are two things I could think could go wrong:

  1. 未按正确顺序到达的字节.(假设 Simulink 连续流式传输串行数据,但处理较晚开始,仅从第 2、3 或 4 个字节而不是第一个字节捕获数据:数据将被移位).您可以尝试使用阻塞循环删除 buffer()/serialEvent() 并一次获取一个字节(例如 if(simulinkPort.available() >= 1) myNewByte = simulinkPort.read();) 并手动将字节计数/打包到字节数组中.您也可以尝试呼叫/响应方法:例如Simulink 不会发送任何数据,直到它收到来自 Processing 的单个字符(假设为A"),然后开始流式传输,因此 Processing 从一开始就准备好一次缓冲 4 个字节.
  2. 我不确定从 Simulink 发送字节的顺序:上面我假设从右到左,但反过来只是交换索引:int intBits = byteFromSimulink[0] <<24 |byteFromSimulink[1] <<16 |byteFromSimulink[2] <<8 |byteFromSimulink[3];
  1. The bytes not arriving in the correct order. (let's say Simulink is continuously streaming serial data, but Processing starts later and only catches data from the 2nd, 3rd or 4th byte instead of the first: data will be shifted). You can try to remove buffer()/serialEvent() with a blocking loop and getting one byte at a time (e.g. if(simulinkPort.available() >= 1) myNewByte = simulinkPort.read();) and counting / packing bytes into the byte array manually. You could also try a call/response approach: e.g. Simulink doesn't send any data until it receives a single character from Processing (let's say 'A'), then starts streaming, so Processing is ready to buffer 4 bytes at a time from the get go.
  2. I'm not sure in which order the bytes are sent from simulink: above I'm assuming right to left, but it's the other way around simply swap indices: int intBits = byteFromSimulink[0] << 24 | byteFromSimulink[1] << 16 | byteFromSimulink[2] << 8 | byteFromSimulink[3];

Java/Processing 中的另一个问题是字节从 -127 到 127,因此您在检查时需要掩码字节:println(myByte & 0xFF);

The other gotcha in Java/Processing is that bytes are from -127 to 127 so you would want mask bytes when inspecting: println(myByte & 0xFF);

基于 g00se 在下面评论中的建议,这里尝试了 ByteBuffer 选项:

Based on g00se's suggestion in the comments bellow here's an attempt at a ByteBuffer option:

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;
}

这篇关于从串口接收数据作为处理编程中的浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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