2017-01-04 6 views
0

私が望むのは、ブルートゥースデバイスHC-05を使用してarduino UNOに読み書きするためにVisual Studioを使用します。前のステップでは、私はVisual Studio C++とArduinoを使ってUSBポート経由で直接通信することができました。私が使用しているコードは基本的にarduino and visual studio c++, 2 way serial communicationと同じです。 arduinoので、私はのようなコマンドを持っている:ArduinoビジュアルスタジオとブルートゥースHC-05

void setup() { 
    // put your setup code here, to run once: 
    Serial.begin(9600); 
    } 


void loop() { 
    // put your main code here, to run repeatedly: 
    if (Serial.available() > 0) { 
     char c = Serial.read(); 
     if (c == '1') 
      Serial.write("FORW"); 
     else if (c == '2') 
      Serial.write("LEFT"); 
     else if (c == '3') 
      Serial.write("RIGTH"); 
     else if (c == '4') 
      Serial.write("BACK"); 
     else if (c == '5') 
      Serial.write("STOP"); 
     else 
     Serial.write("Invalid"); 
    } 

と私/出力(直接ArduinoのUSBを使用して)です:

Connection established!!! 
Enter your command: 1 
arduino: FORW 
Enter your command: 2 
arduino: LEFT 
Enter your command: 3 
arduino: RIGTH 
Enter your command: 6 
arduino: Invalid 
Enter your command: 

私はそれでBluetoothモジュールのHC-05を追加したとき。シリアルモニターを使用して、同じ出力を得ることができますが、私は、Visual Studioを使用する場合は、次の出力のために、それは常に次のように、前回出力されていない現在のものを与えながら、最初の入力は、出力をバック与えたことがない:

Connection established!!! 
Enter your command: 1 
arduino: 
Enter your command: 2 
arduino: FORW 
Enter your command: 1 
arduino: LEFT 
Enter your command: 4 
arduino: FORW 
Enter your command: 6 
arduino: BACK 
Enter your command: 2 
arduino: Invalid 
Enter your command: 

次の手順がエラーを与える可能性がある場合、私は知らない。

  1. をブルートゥースを5V
  2. が供給されて、私はArduinoの宇野と接続したBluetooth TX RXを横断
  3. ブルートゥースHC-05がデフォルトモードになって、私はdidnのそれについて何も変えないでください。
  4. ブルートゥースがPCに接続されている場合、COM4 'DEV-B' & COM5の2つのポートが表示されます。そのため、Visual StudioのコードをCOM4に接続するように変更しました。
  5. ビジュアルスタジオでも示されているArduinoでは、バインドレートは9600に設定されています。

これはどうして起こるのでしょうか?

答えて

0

おそらく問題は10ms以内に以前の通信が届かないことです。

私は普通のC++やVisual Studio(通常は管理されたC++拡張とイベントループを使用します)でプログラミングする経験はあまりありませんが、シリアルポートを処理する必要があるときは、スレッド。

イベントを使用する場合は、SerialPortクラスとそのDataReceivedイベントを使用します。 Visual C++を使用しているので、これを使用することをお勧めします。空のイベントではなく管理対象のコンソールアプリケーションを作成し、イベントの仕組みを見て、VSに基本スケルトンを作成させてください。

複数のスレッドを使用する場合は、1つのスレッドを使用して入力を確認し、もう1つのスレッドを使用してシリアルを確認してください。私はスレッドを開始して処理する方法(あなたはOSやライブラリ関数、おそらくpthreadのものを使う必要があります)を手助けすることはできませんが、2つのスレッド関数は次のようになります:

void thread1() 
{ 
    while (1) 
    { 
     std::cout << "Enter your command: "; 
     std::cin.get(command, 2);  //input command 
     int msglen = strlen(command); 
     if (port->WriteData(command, msglen)); //write to arduino 
     printf("\n(writing success)\n"); 
    } 
} 

void thread2() 
{ 
    while (1) 
    { 
     int n = port->ReadData(data, 4); 
     if (n != -1){ 
      data[n] = 0; 
      cout <<"arduino: " data << endl; 
     } 
     Sleep(10); 
    } 
} 

第三ソリューションは、いくつかのデータがある場合にのみ、入力とシリアルをチェックすることです:あなたはそれを送る、すなわち入力用のプログラムウェイトを作る(複数のコマンドを送信する場合は

std::cout << "Enter your command: "; 

while(1) 
{ 
    if (_kbhit()) 
    { 
     std::cin.get(command, 2);  //input command 
     int msglen = strlen(command); 
     if (port->WriteData(command, msglen)); //write to arduino 
     printf("\n(writing success)\n"); 
     std::cout << "Enter your command: "; 
    } 

    //read from arduino output 
    n = port->ReadData(data, 4); 
    if (n != -1) 
    { 
     data[n] = 0; 
     cout <<"arduino: " data << endl; 
    } 
    Sleep(10); 
} 

これらは解決されています別の入力を待つ)。あなただけの1つのコマンドとし、終了のためにそれを使用したい場合は

、単にいくつかのデータを待つ:

std::cout << "Enter your command: "; 
std::cin.get(command, 2);  //input command 
int msglen = strlen(command); 
if (port->WriteData(command, msglen)); //write to arduino 
printf("\n(writing success)\n"); 

while ((n = port->ReadData(data, 4)) <= 0) 
    Sleep(10); 

data[n] = 0; 
cout <<"arduino: " data << endl; 

最も簡単なほとんどunsuggestedソリューションは、単に睡眠時間を増やすことである(例えば、50ミリ秒)パケットの送受信を可能にする。

もう少し先に、この問題に直面するでしょう。通常、通信(シリアル、イーサネットなど)を使用すると、ドライバがデータを受信した回数を制御することはできません。 「FORW」を受け取ったときは通常ブロックとして受信しますが、「FOR」と「W」、「FO」「RW」、または「F」「ORW」のブロックを受け取ることがあります。または、「FORWLEFT」のように2つの連続したメッセージを受信することもできます。したがって、どちらかを指定する必要があります。

  1. 「ターミネーター」文字は、たとえば#とする必要があります。送信機能はFORW#を送信します。受信した各文字はターミネータを検出してその時点までに受信したすべての文字を処理します。例えば、「FO」を受信する。バッファ(FO)に追加します。ターミネーターなし、処理なし。それからそれは "RW"を受け取る。バッファ(FORW)に追加します。ターミネーターなし、処理なし。それから "#LEFT#"を受信します。バッファに追加します(FORW#LEFT#)。最初のターミネータは5桁目ですので、最初の5バイト(FORW#)を解析し、バッファから削除してください(現在はLEFT#を含んでいます)。それでもターミネーターは、分析します。 #が気に入らなければ、キャリッジリターン(\ n)、スペース、文字列ターミネータ(\ 0)を使うことができます。文字列で使用していないすべての文字は問題ありません。
  2. 各コマンドを正確に同じ長さにします(たとえば4文字)。次に、バッファが4文字以上になるまですべてのバイトを読み込み、最初のnバイトを処理します。
関連する問題