2

Arduino Uno / Nano (ATmega328)からESP8266に AT コマンドを送信し、応答として受信した文字列の末尾を解析して、ESP がどのように反応したか、およびそれが成功したかどうか (および別のコマンドを受信する準備ができているかどうか) を確認しようとしています。まだ)。AT コマンド応答の解析については、ここで以前に説明したことを認識しています。

AT コマンドの応答を取得する

しかし、ここで取り上げられていない特定の問題があり、ここにいる他の人にも興味があるかもしれません...

最初に、AT コマンドを ESP に送信して ThingSpeak (データログ サーバー) に接続する関数が呼び出されます。これは手動モードでは正常に機能し、応答を解析しようとしたときにも接続します、返された最初の行のみを解析します。たとえば、シリアル モニタで期待される出力は次のようになります。

c
AT+CIPSTART="TCP","api.thingspeak.com",80
CONNECT

OK
Connected to ThingSpeak!

c接続を開始するために入力するコマンド文字はどこにありますか。

ただし、実際の応答は次のとおりです。

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


CONNECT

OK

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

解析機能をテストするために、検索して"80"みましたが、これは応答の最初の行の最後にあるため、true が返されました。検索して"OK""OK\r\n"結果が同じでも false を返し、THEN の残りの応答を受け取ります。

コードは次のとおりです。

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") だけです。

4

2 に答える 2

0

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

はい、あなたの主な問題は次のとおりです

if (ESP.available())

これにより、UART (またはその他のシリアル IO バッファ) が空になるたびに、waitForResponse 関数が返されます。これは望ましくありません。で終わる回線を受信するまで、シリアルポートから読み取る必要があります"\r\n"

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

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

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

前の文字と現在の文字がreadline一致するまで 1 文字ずつ読み取り、それまでに読み取ったすべての文字を返す関数を実装してください。\r\n

次に、その関数をモデム応答データの読み取り専用に1使用します。これは、中間結果コードCONNECT最終結果コード(などOK) の両方に適用されます。応答行を「解析」すると、次のように簡単になります。

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

また

if (isFinalResultCode(responseLine)) ...

に述べたように、モデム出力を処理する唯一の正しい方法は、出力を完全な行に分割し、一度に 1 行ずつ繰り返すことです。


1 唯一の例外は、AT+CMGS 応答データを解析する場合です。

于 2016-06-22T19:57:20.210 に答える