2016-06-22 5 views
2

Arduino Uno/Nano(ATmega328)からESP8266にATコマンドを送信し、応答として受け取った文字列の終わりを解析してESPそれが成功したかどうか(まだ別のコマンドを受け取る準備ができているかどうか)を確認します。 Get AT command responseATコマンドの応答(Arduinoのコード実行順序の理解)

しかし、私もここに他の人が興味を持つかもしれないがカバーされていない特定の問題を持っている...

まず、A:私は、コマンド応答AT解析すると、ここで前に議論されていることを承知しています関数が呼び出され、ATコマンドをESPに送信してThingSpeak(データログサーバー)に接続します。これは手動モードで正常に動作し、応答を解析しようとしたときにも接続されますが、返される最初の行だけを解析します。例えば、シリアルモニターで予想される出力は次のようになります。

c私は接続を開始するために入力するだけでコマンド文字です
c 
AT+CIPSTART="TCP","api.thingspeak.com",80 
CONNECT 

OK 
Connected to ThingSpeak! 

。次のように

実際の応答は、しかし、次のとおりです。以下のコードに示すように

c 
AT+CIPSTART="TCP","api.thingspeak.com",80 
Cannot connect to ThingSpeak! 


CONNECT 

OK 

これは、それが応答を受信する前に解析関数が終了していることを意味...、10秒のタイムアウトがあります現在指定されています。 20秒のタイムアウトがあっても、手動で実行すると約1秒で応答が到着するという事実にもかかわらず、同じことが起こります。

構文解析機能をテストするために、"80"を検索してみましたが、これは応答の最初の行の最後に見つかったため真となりました。 "OK"または"OK\r\n"を検索するかどうかにかかわらず、結果は同じです。falseを返し、残りの応答が受信されます。

boolean waitForResponse(String target, unsigned long timeout) 
{ 
    unsigned long startTime = millis(); 
    String responseBuffer; 
    char charIn; 

    //keep checking for ESP response until timeout expires 
    while ((millis() - startTime) < timeout) 
    { 
    if (ESP.available()) 
    { 
     responseBuffer += ESP.read(); 
    } 
    } 
    Serial.println(responseBuffer); 
    if (responseBuffer.endsWith(target)) 
    { 
    return true; 
    } else { 
    return false; 
    } 
} 

void openCxn() 
{ 
    ESP.print("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80"); 
    delay(500); 
    if (waitForResponse("80",10000L)) 
    { 
    Serial.println("Connected to ThingSpeak!"); 
    } else { 
    Serial.println("Cannot connect to ThingSpeak!"); 
    } 
} 

フル応答が受信される前に、それは(もタイムアウト期間内)を返す理由を任意のアイデア:

ここでは、コードですか?それはendsWith()の機能と関係がありますか?

したがって、最初の行だけでなく応答全体を解析する方法はありますか?

私は、回答の最後にのみ興味があります(例:"OK"または"OK\r\n")。

+1

おそらくあなたが受け取るものは、 "(String :: endsWith')" 80 "ではなく" 80 "となります。 – tofro

答えて

0

完全な応答が受信される前に返される理由は何ですか(タイムアウト期間内でも)?

はい、あなたの主な問題は、これは、UART(またはいくつかの他のシリアルIOバッファ)が空になるたびwaitForResponse関数の戻りになり、次の

if (ESP.available()) 

です - あなたが望むものではありません。あなたが望むのは、"\r\n"で終わる回線を受け取るまで、シリアルポートから読み取ることです。

endsWith()関数とは関係がありますか?

はい、それはあなたがランダムデータチョッピングはシリアルパスに発生したものに、モデムからの応答行の末尾に一致するようにしようとしているので、ESP.availableと組み合わせて別の問題です。あなたが非常に運が良ければ、これはオンライン上の境界線になりますが、そうでない可能性が最も高く、あなたはそれに頼るべきではありません。

これは、非同期シリアル通信の任意の種類に適用されるframingとして知られている一般的なプロトコルの問題です。モデム通信の場合、フレーミング文字は\r\nです。

は自分を支持を行うと、それは前の文字が\rだったと現在の文字が\nあるし、それがこれまで読んで、すべてを返すまで、1文字ずつ読み込むreadline機能を実装します。

次にモデム応答データを読み取るための専用のその機能を使用しています。これは、の中間結果コードCONNECTと同様にの最終結果コード(例:OKなど)の両方に適用されます。 Iモデム出力を処理するbeforeのみ正しい方法が完了行に出力を分割することであることを特徴とするように応答ラインが次に

if (responseLine.equals("CONNECT\r\n")) ... 

又は

if (isFinalResultCode(responseLine)) ... 

のように単純であることができる「解析」その時点で1行を反復処理します。


+ CMGS応答データAT解析するとき唯一の例外です。

+0

あなたの返答には多くの感謝があります!それがこんなに早くけれども返し、なぜ私はまだ理解していない ... '「UART(またはいくつかの他のシリアルIOバッファ)が空である時はいつでもこれはwaitForResponseの関数の戻り値になります。」' バッファが空の場合、ループは終了しますが、タイムアウトループ内にあるため、ループは再び繰り返されます。 なぜタイムアウトに次回に到着する次の文字をキャッチしないのですか? – AntInvent

+0

@AntInventはその部分が間違っています。タイムアウトまでループし続けます。しかし、「endsWith」問題は本物です。 1行以上の行を読むと、ほとんどの場合、それはあなたのロジックが失敗します。 – hobbs

+0

真実、私は答えを書くのを始める前にそれを逃した。すべての行を1行ずつ解析するようにコードフローを変換する必要があります。そうしないと、プログラムは 'AT + CIPSTART'が' ERROR'などを返すケースを処理しません。 – hlovdal

0

あなたの後にはあなたは本当に間違っていますあなたはokを受け取ったにもかかわらずあなたが目標の文字列で終わらないので、より多くのものを読み返したかもしれないので。

responseBufferが終了するかどうかをテストする必要があります。ターゲットを返します。trueを返します。whileループで新しいCharを受け取ったときにのみ、それを返します。 タイムアウトした後はfalseを返します。