5

Arduino UNO のシリアル転送速度をテストしています。私の要件では、ホスト PC から Arduino に 3KB/s を転送する必要があります。私は非常に単純なプログラムを作成しました。これは、結果を返信Serial.available()し、Arduino IDE のシリアル モニターでテストします。最大の 63 バイトに達するまで、文字の送信を開始しました。Arduinoには128バイトのシリアルバッファがあるとどこかで読んだので、これにはかなり驚きました。

とにかく、私はデータを 48 バイトのパケット (実際にはヘッダー文字のために 49 バイト) で送信する非常に単純なプロトコルを作成しました。ホストはd文字を送信し、次に 48 バイトのデータを送信します。送信の有効性をテストするために、Arduino側で検証される0から47までの単純なバイトシーケンスを送信しています。検証に失敗すると、UNO は PIN13 のオンボード LED を点滅させ始めます。バイトが送信されると、ホストは単純なk文字である確認を待ちます。実際のパケットの処理が完了すると、Arduino はこれを送信します。

ホスト プログラムは、送信されたパケットの数を測定し、1 秒後に表示します。9600 のボー レートで、PC は 1 秒あたり約 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() を使用する場合、経過する必要があります。詳細とこれを処理するためのよりクリーンな方法については、こちらの私の回答を参照してください (タイムアウトを減らすだけでなく、終了文字を検索して、タイムアウトを完全に不要にすることができます) : Arduino との Matlab シリアル インターフェイスが非常に遅い

于 2015-03-06T03:55:33.950 に答える
0

最近、このチュートリアルを使用して、ケーブルを介して Arduino UNO デバイスを PC に接続しました: Arduino and Java

于 2012-05-06T19:28:09.040 に答える