微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从串口接收数据作为处理编程中的浮点数

如何解决从串口接收数据作为处理编程中的浮点数

下面是来自arduino的代码

<div id="screen" class="screen">
  <div id="menu_bar" class="menu-bar">
    <div id="logo" class="logo" data-flip-id="logo">
      <img id="logo_image" src="https://i.imgur.com/rkBwgtt.png" />
      
      <!-- <div id="pie" class="pie">
          <svg height="100%" width="100%" viewBox="0 0 20 20" data-percentage="50">
            <circle r="10" cx="10" cy="10" fill="white" />
            <circle r="5" cx="10" cy="10" fill="transparent" stroke="tomato" stroke-width="10"
              transform="rotate(-90) translate(-20)" />
          </svg>
        </div> // can remove this // -->

    </div>
    <div id="title" class="title">Title</div>
    <div id="menu_button" class="menu-button"> <img id="menu_image" src="https://i.imgur.com/l6GysYf.png"> </div>
  </div>
  <div id="display" class="display">
    <div id="speech_bubble" class="speech-bubble">
      <div id="logo_animation" class="logo-animation" data-flip-id="logo">
        <img id="logo_animation_image" src="https://media0.giphy.com/media/Z1oYdpUd9Txyop1jdH/giphy.gif?cid=790b7611436e68e9fdddc32ce5e4e6c3a4730caba6ef8f0c&rid=giphy.gif&ct=s">
      </div>
    </div>
  </div>
</div>

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

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

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

解决方法

你需要:

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

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

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

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

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

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

根据 g00se 在下面评论中的建议,尝试使用 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,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,hex(bytesFromSimulink),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;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。