5

私はArduinoデバイスとPCを持っています。ボードで次のコードを試しました。

gpsdata data;

char needtosend;

void setup() {            
  Serial.begin(9600);
  Serial.flush();  
  data.id = 0;
  data.src= 500;
  data.lat= 1;
  data.lon= 2;
  data.alt= 3;
  strcpy(data.date, "test date format");

}

void loop() {


   if(Serial.available() > 0)
   {
    needtosend = Serial.read();
    if ( needtosend == '2')
    {
      data.id = ++data.id % 10;
    }

    byte* buff = (byte*)&data;
    Serial.write(buff, sizeof(data));

   }
   delay (200);

}

PC アプリケーションは C++ で記述され、ブースト ライブラリを使用して Arduino デバイスと通信します。これは PC コードです。

Serial serial("/dev/ttyUSB0",9600);
            gpsdata *data;
            char *values = new char[sizeof(gpsdata)];
    while(true)
    {
        try {

            serial.writeString("2",1);
            serial.read(values,sizeof(gpsdata));
            data = (gpsdata *)values;
            cout<<data->id<<endl;
        } 
        catch(boost::system::system_error& e)
        {
            cout<<"Error: "<<e.what()<<endl;
        }
        catch(timeout_exception& e)
        {
            cout<<"Error: "<<e.what()<<endl;
        }
    }
            delete[] values;


Serial::Serial(std::string port, unsigned int baud_rate): io(), serial(io,port)
{
    serial.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));  
}
void Serial::read(char *data, size_t size)
{
    boost::asio::read(serial,boost::asio::buffer(data,size));
}

void Serial::writeString(const char* s, int length)
{
   boost::asio::write(serial,boost::asio::buffer(s,length))<<std::endl;
}

デバイスの電源を入れて初めて PC アプリケーションを起動すると、文字列 "2" がデバイスに送信され、read() がブロックされ、Arduino からデータを受信しません。アプリケーションを強制終了し、Arduino を再起動せずに再起動すると、すべて正常に動作し始めます。非同期読み取りを試してみましたが、結果は同じで、最初のメッセージで読み取りがタイムアウトし、その後すべてが正常に機能し始めました。PC アプリケーションで受信される 2 番目のメッセージは id 1 で、Arduino が最初のメッセージを受信して​​いないことを意味します。私の間違いはどこですか?

4

4 に答える 4

1

Win7 で Boost asio と Arduino Uno を使用している場合、私のプロジェクトの 1 つでまったく同じ動作が見られました。Boostがシリアルポートを開くと、Arduinoをリセットしてブートローダーをトリガーする信号が送信されているようです(Arduino IDEからコードをアップロードするときに発生するのと同じように見えます).

私が思いついた3つの可能な回避策があります:

  1. Arduino が誤ってリセットされた場合 (Boost がシリアル ポートを開いた場合)、再び動作を開始するまでに数秒かかります。これは、Arduino IDE がコードのアップロードを開始するためにブートローダーが通常与える時間枠のようです。ポートを開いてから数秒待つことで、物事が少しうまく機能するようになる可能性があります。

    serial->open(strPortName);
    SleepEx(2000,false);
    serial->set_option(...);  
    ...
    

    この方法を使用しても、通常、最初の読み取りでデータが文字化けします。ただし、通常は次の読み取りで適切に機能します。

  2. ブートローダーを失います。Arduino IDE とは異なる方法を使用して、6 ピン ISP を介して Arduino をプログラムします。これには、Arduino IDE を捨てて、AVR Studio やある種のハードウェア ISP プログラマーなどを使用することが含まれます。そのルートに行く場合は、これを参照してください: http://www.engblaze.com/tutorial-using-atmel-studio-6-with-arduino-projects/

  3. ライブラリを切り替えます。Boost を使用して上記の動作を見たことがありますが、Boost を使用する前に CTB ライブラリ ( https://iftools.com/opensource/ctb.en.php ) を使用していました。シリアルポート。私のプロジェクトでは、Boost が提供する他の機能を取得するために最初に Boost に切り替えましたが、通信のために CTB に切り替えました。

4番目のオプションは、Arduinoをリセットせずにポートを開く方法をBoost asioの専門家に知らせてもらうことです(CTBはそれを行うことができるので、方法があるはずですが、私はBoostでそれを行う方法を知るのに十分な専門家ではありません) )。

于 2012-11-11T05:40:15.560 に答える
1

ハンスのコメントで述べたように、通信プロトコルがオフになっています。

あなたのArduinoループは基本的に次のように言っています:

値を読み取ります。別の使用可能な値がある場合は、何かを行います。0.2 秒待ちます。その後、繰り返します。

あなたのPCループは言う:

「2」を送信します。次に、値の配列を読み取ります。その後、繰り返します。

あなたが行っていることは、通信の Arduino 側が、送信されているよりも多くの値を待っていることです。Arduino で、Serial.avaliableをポーリングしてから読み取りを行います。

PC では、おそらく変更する必要はありません。

切断して再接続すると、ボー接続を初期化するために送信される余分なビットがあり、それがプロトコルをだまして機能させていました。

編集:シリアルライブラリが接続している設定を必ず確認してください。Qt QextSerialPort ライブラリを使用する前に、Arduino ボードに接続するために以前に使用した設定を次に示します。

port->setFlowControl(FLOW_OFF);
port->setParity(PAR_NONE);
port->setDataBits(DATA_8);
port->setStopBits(STOP_1);
port->setTimeout(500);

役立つと思われる2つのリンクを次に示します。

http://www.webalice.it/fede.tft/serial_port/serial_port.html

https://www.google.com/search?q=arduino+and+boost%3A%3Aasio

于 2012-11-09T18:30:41.533 に答える
0

time ライブラリをインポートしてtime.sleep(2)、行の後に追加するだけSerial.begin(9600);です。

于 2013-03-30T09:24:28.803 に答える
0

Arduino の Web サイトには、ハードウェアの観点からこれに関する非常に徹底的な説明があります。

http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection

この問題に対するいくつかのハードウェア ソリューションについても説明します。

  1. RESET ラインと GND ラインの間に 10uF のコンデンサを接続します。
  2. RESET 間に 120 オームの抵抗を挿入します。
  3. R3 を完全に削除して、Arduino の自動リセット機能を無効にします。
于 2013-02-24T05:18:20.857 に答える