5

我正在测试我的 Arduino UNO 的串行传输速度。根据我的要求,我必须将 3KB/s 从主机 PC 传输到 Arduino。我编写了一个非常简单的程序,它回复结果,Serial.available()然后在 Arduino IDE 的串行监视器中对其进行测试。我已经开始发送字符,直到达到最大值,即 63 个字节。我对此感到非常惊讶,因为我在某处读到 Arduino 有一个 128 字节的串行缓冲区。

无论如何,我已经制定了一个非常简单的协议,它以 48 字节数据包(实际上是 49 字节,因为标题字符)传输数据。主机发送一个d字符,然后发送 48 个字节的数据。为了测试传输的有效性,我发送了一个从 0 到 47 的简单字节序列,该序列在 Arduino 端得到验证。如果验证失败,UNO 将开始闪烁 PIN13 上的板载 LED。一旦发送了字节,主机就会等待一个简单k字符的确认。一旦完成处理实际数据包,Arduino 就会发送此信息。

主机程序测量传输的数据包数量并在 1 秒后显示。波特率为 9600,PC 成功传输约 16 个数据包/秒(约 800 字节/秒),这还不错。我试图通过将双方的波特率提高到 57600 来改善这一点;但是,发送的数据包数量只增加了一点。我不知道问题是什么。也许我已经达到了 USB 串行转换器的某种限制?


这是我的代码。

PC(Java,我使用jSSC进行串口通信)

  package hu.inagy.tapduino.server;

  import jssc.SerialPort;
  import jssc.SerialPortException;

  /**
   * Test Arduino communication.
   */
  public class App
  {

    private static void testComm(SerialPort port) throws SerialPortException {
      long runningSeconds = 0;
      long time = System.currentTimeMillis();
      long numberOfPackets = 0;
      boolean packetSent = false;
      while (runningSeconds < 10) {
        long currentTime = System.currentTimeMillis();
        if (currentTime - time > 1000) {
          runningSeconds++;
          time = currentTime;
          System.out.println(numberOfPackets + " packets/s");
          numberOfPackets = 0;
        }

        if (!packetSent) {
          packetSent = true;
          port.writeByte((byte) 'd');
          for (int i = 0; i < 48; i++) {
            port.writeByte((byte) i);
          }
        } else {
          byte[] received = port.readBytes();
          if (received != null) {
            if (received.length > 1) {
              throw new IllegalStateException("One byte expected, instead got: " + received.length);
            }

            char cmd = (char) received[0];
            if ('k' != cmd) {
              throw new IllegalStateException("Expected response 'k', instead got: " + cmd);
            }
            packetSent = false;
            numberOfPackets++;
          }
        }

      }
    }

    public static void main(String[] args)
    {
      SerialPort port = new SerialPort("COM7");

      try {
        if (!port.openPort()) {
          throw new IllegalStateException("Failed to open port.");
        }
        port.setParams(57600, 8, 1, 0);
      } catch (SerialPortException e) {
        throw new IllegalStateException("Exception while setting up port.", e);
      }

      try {
        // Wait 1.5sec for Arduino to boot successfully.
        Thread.sleep(1500);
      } catch (InterruptedException e) {
        throw new IllegalStateException("Interrupt while waiting?", e);
      }

      try {
        testComm(port);
      } catch (SerialPortException exc) {
        throw new IllegalStateException("Failure while testing communication.", exc);
      } finally {
        try {
          if (!port.closePort()) {
            throw new IllegalStateException("Failed to close port.");
          }
        } catch (SerialPortException e) {
          throw new IllegalStateException("Exception while closing port.", e);
        }
      }
    }
  }

阿杜诺

void setup() {
   pinMode(13, OUTPUT);
   Serial.begin(57600);
}

boolean error = false;

void loop() {
  if (error) {
      digitalWrite(13, HIGH);
      delay(1000);
      digitalWrite(13, LOW);
      delay(1000);
  } else {
    while (Serial.available()<49);
    char cmd = Serial.read();
    if ('d'!=cmd) {
       error=true;
       return;
    }

    for (int i=0; i<48; i++) {
       int r = Serial.read();
       if (r!=i) {
         error=true;
         return;
       } 
    }

    Serial.write('k');
  }

}
4

4 回答 4

5

NagyI,jSSC 方法 writeByte(byte b) 与 writeBytes(new byte[]{b}) 相同。例如:

serialPort.writeByte((byte)0xFF);
serialPort.writeBytes(new byte[]{(byte)0xFF});

这些字符串是等价的。writeByte() 方法为您要发送的每个字节创建一个新的字节数组。在 Java 中创建对象是一项昂贵的操作,这就是为什么如果您需要高速数据传输,请使用准备好的字节数组,如您的答案。问候,阿列克谢。

于 2012-05-08T09:09:44.457 回答
3

我找到了解决方案。jSSC 的 writeByte 函数在这种情况下效率非常低。如果我在 Java 中预先制作了 49 字节的缓冲区,然后立即将其传递给 jSSC,我将获得非常大的速度提升。

    byte[] sendBuffer = new byte[49];
    sendBuffer[0] = 'd';

    for (byte i = 0; i < 48; i++) {
      sendBuffer[i + 1] = i;
    }
    port.writeBytes(sendBuffer);

在 Arduino 论坛上,一位成员向我建议波特率 345600,它现在给了我 ~240 个数据包/秒(~12KB/秒)。

于 2012-05-06T19:12:54.067 回答
3

您是否尝试过将此行添加到您的 Arduino setup() 函数中?:

// this will make the Arduino wait a max of only 100ms per incoming 
// set of serial data, before moving on
Serial.setTimeout(100); 

在这里阅读:http: //arduino.cc/en/Serial/SetTimeout

默认情况下,Arduino 有 1 秒超时,如果您只是使用 Serial.read() 来读取新数据,则必须经过该超时。请参阅我的回复以获取更多信息和更简洁的处理方式(而不是仅仅减少超时,我们可以搜索终止字符并完全停止需要超时)Matlab serial interface with Arduino is very slow

于 2015-03-06T03:55:33.950 回答
0

最近,我使用本教程通过电缆将 Arduino UNO 设备连接到 PC:Arduino 和 Java

于 2012-05-06T19:28:09.040 回答