0

私は Arduino と APC220 ワイヤレス トランシーバーを持っています。SoftwareSerial クラスを使用して APC からデータを読み込むライブラリを作成しています。i私はもともと、読み取り可能なデータがない場合でも変数がインクリメントされるため、セグ フォールトを引き起こしていた以下の (間違った) コードから始めました。たまたま機能した場合 (たまたまデータがすぐに利用可能になった場合)、この関数の実行には約 6 ミリ秒かかりました。i++;ステートメントを適切な場所 (すぐ上の右中括弧の上) に配置すると、関数の実行に 270 ミリ秒以上かかります。この関数には速度が重要なので、このような劇的な時間の増加を引き起こすステートメントの配置についてはどうなのか疑問に思っています。

以下のコードでは、buffは as として宣言されchar buff[10];、sSerial は のインスタンスです。SoftwareSerial

unsigned long updateLocation(Marker* marker) {
    this->sSerial->print('~');
    //initiate request from vision system
    this->sSerial->flush();
    this->sSerial->print('#');
    this->sSerial->print(marker->num);
    this->sSerial->print('*');
    this->sSerial->flush();
    unsigned long start = millis();
    int state = 0, i = 0;
    while((millis() - start) < 600) {
        if(this->sSerial->available()) {
            buff[i] = this->sSerial->read();
            if(buff[i] == ',') {
                buff[i] = 0;
                switch(state) {
                    case 0:
                        i = -1;
                        state++;
                        break;
                    case 1:
                        marker->x = atof(buff);
                        i = -1;
                        state++;
                        break;
                    case 2:
                        marker->y = atof(buff);
                        i = -1;
                        state++;
                        break;
                    case 3:
                        marker->theta = atof(buff);
                        i = -1;
                        return (millis() - start);
                        break;
                    default:
                        return 0;
                        break;
                }
            }
            // Correct location for i++; takes 270 ms to execute
        }
        // Incorrect location for i++; Takes 6 ms to execute
        i++;
    }
    this->sSerial->print('~');
    this->sSerial->flush();
    return 0;
}
4

1 に答える 1

0

からの準備ができて待っているデータがあると仮定するとsSerial、 の配置に実質的な違いはありませんi++

ほとんどの場合、データの準備ができていません。の不適切な配置によりi++、セグメンテーション違反を引き起こすiサイズよりも大きくなります。buff

適切な配置を使用すると、コードは最大 600 ミリ秒ブロックされ、到達して戻るのに十分なデータが到着するのを待ちますcase 3。平均して、それが発生するのに 270 ミリ秒かかることがわかります。

シリアルから読み取るのではなく、文字列に対して直接動作する同じ関数のタイミングをとることによって、この理論を自分でテストできます。

a) ボーレートを上げる b) 使用できるより効率的なソフトウェア シリアル実装があるかどうかを確認する c) ハードウェア シリアルに切り替える。現在、デバッグ出力にハードウェア シリアルのみを使用している場合は、それを切り替えることができます。FTDI アダプター (eBay では 6 ~ 10 ドル) を使用して、ソフトウェア シリアルを USB にパイプし、時間に敏感な機能用にハードウェア シリアルを予約します。

待機中ずっとブロックされないように、コードを再構成することもできます。利用可能なものを読み込んでグローバルに保存し、メインループに戻ってデータが再び利用可能になるまで別のことをすることができます。

編集: APC220 が最大 9600 ボーであることがわかりました。これはかなり遅いため、ボトルネックはソフトウェア シリアルではない可能性があります (ただし、テストする必要があります)。ボトル ネックが単にボー レートである場合、システムが待機中に他の処理を実行できる場合は、入力待機をブロックしないようにコードを最適化する必要があります。

于 2016-11-21T17:38:57.610 に答える