2016-11-18 25 views
0

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

buffchar buff[10];として宣言され、sSerialはデータレディと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; 
} 
+0

'i ++;'がOKとNOKで動作しているコードに '//'コメントを追加して、時間に関する詳細を追加できますか? –

答えて

0

のインスタンスである、i++の配置には効果的な違いはありません。

ほとんどの場合、データは準備ができていません。 i++の誤った配置では、iは、segfaultを引き起こすbuffのサイズよりも急速に大きくなります。

正しい配置で、十分なデータが到着してからcase 3に到達するのを待って、最大600msのコードブロックが返されます。平均して、それが起こるには270ミリ秒かかります。

シリアルから読み込むのではなく、同じ関数を文字列で直接操作することで、この理論を自分でテストできます。

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

コードを再構成して、待ち時間全体をブロックしないようにすることもできます。利用可能なものを読んだり、グローバルに保存したり、メインループに戻ってデータが再び利用できるようになるまで何か他のことをすることができます。

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

+0

この関数は、主コードが継続するために受け取る情報を必要とするため、意図的にブロックするように設計されています。誤った位置に 'i ++ 'が置かれたとき、segが失敗しなかった場合、実行に6msかかりました。これは、関数CANがすばやく動作することを示すようですが、何らかの理由で' i ++ 'が正しい場所に移動します。私が考えることができる唯一のことは、 'while'の定数インクリメントのコンパイラ最適化です。 –

+0

再び、私はそれがデータが来るのを待つ必要がなければ、いつもすぐにそれを動作させると思います。私は自分の理論をテストする方法を提案しました。シリアルの読み込みを排除して、期待しているデータのような文字列を関数に渡します。 – imjosh

関連する問題