新しいシリアルコマンドを取得するときに既存のアレイをクリアします

最初のArduinoプロジェクトのビルドを開始していますが、シリアル通信でいくつかの問題が発生しています。

コンソールからシリアルデータを取得し、それを「data」というchar配列に格納します。

次に、新しいコンソールメッセージをArduinoに送信するときに、既存の「データ」配列であり、その配列に新しいデータのみを格納します。

コードの何が問題なのか正確にはわかりません。ネストされたSerial.available()ステートメントは機能しないと思います。しかし、コードを修正する方法がわかりません。

データはArduinoによって正しく保存されますが、新しい文字列が古い文字列に連結されます。

int count = 0; char data[30]; boolean dataComplete = false; void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0){ if (dataComplete == true){ Serial.println("There is data already, clearing..."); char data[30]; dataComplete = false; } if (dataComplete == false){ Serial.println("New command, collecting..."); while (Serial.available()>0){ char character = Serial.read(); data[count] = character; count++; } dataComplete = true; } } Serial.print("Command received: "); Serial.println(data); delay(1000); } 

よろしくお願いします!

回答

配列をクリアするには、次のようにします。

for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0; 

または

memset(data, 0, sizeof(data)); 

、これはライブラリ関数を使用して同じことを行います。

ただし、文字列のための文字(ここでは「文字列」オブジェクトを参照していません)はゼロバイトで終了します。最初のバイトのみをゼロにする必要があります。

data[0] = (char)0; 

回答

まず、これは空白が重要である理由の優れた例です。コードをそのまま読むのは本当に難しいです。それをざっと読むと、2番目のifステートメントが最初のステートメントの外にあるように見えます。

修正されたコード:

int count = 0; char data[30]; boolean dataComplete = false; void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0){ if (dataComplete == true){ Serial.println("There is data already, clearing..."); char data[30]; dataComplete = false; } if (dataComplete == false){ Serial.println("New command, collecting..."); while (Serial.available()>0){ char character = Serial.read(); data[count] = character; count++; } dataComplete = true; } } Serial.print("Command received: "); Serial.println(data); delay(1000); } 

また、新しいデータがあるかどうかに関係なく、反復ごとに「Commandreceived:」を出力するように見えます(ただし、これは意図された機能である可能性があります)。

前述のように、変数をクリアするのではなく、新しい変数を作成するだけです。この問題を修正するには、をクリアしてリセットする必要がありますcount。ただし、2番目のコマンドが1つより短い場合は、カウントをリセットするだけでは機能しません。以前。

また、なぜdataComplete変数を使用してコードを複雑にするのですか?以下のコードを簡略化しました:

int count = 0; char data[30]; boolean dataComplete = false; void setup() { Serial.begin(9600); } void loop() { if (Serial.available()){ Serial.println("New command, collecting..."); count = 0; data[] = ""; while (Serial.available()){ char character = Serial.read(); data[count] = character; count++; } } Serial.print("Command received: "); Serial.println(data); delay(1000); } 

回答

これはおそらくそうではありません意図したとおりに実行します。

Serial.println("There is data already, clearing..."); char data[30]; 

出力には、data配列をクリアしていると表示されますが、 「そのようなことはしていません。実際、グローバルdataから独立したdataという新しいローカル変数を宣言しています。あなたのプログラムのトップですでに宣言しています。ローカル変数は、宣言されているスコープ内(最も近い囲みの{ }内)にのみ存在します。

代わりに、count変数は受信したデータの量を追跡します。したがって、おそらく次のようにします。

Serial.println("There is data already, clearing..."); count = 0; 

プログラムが予期せず動作する原因となるのはこれだけではありませんが、少なくともに記載されている問題は修正されるはずです。

コメント

  • データにはnullターミネータも必要です:data[count]='\0';の後にdata[count]='\0';を追加しますdataComplete = true;
  • はい、'は正しいですが、より大きな問題は、送信者が一時停止以外のデータ送信の終了を示します。また、これはシリアルであるため、すべてのキャラクターが送信されるまでに十分な時間がかかります。
  • お二人に感謝します。コードが間違っていて、" count = 0 "に変更しても機能しました。また、入力コマンドの終了を示す区切り文字を追加しました。これで、意図したとおりに機能します。ただし、" data "配列を空にする唯一の方法は、@ JRobertで示されているようにforループを使用することでした。コマンドは、古いコマンドよりも短くても機能します。

回答

質問の要点を説明します、および作成者が達成しようとしていたこと。

このコードは実際には全体として機能しません。データは上書きされ、継続的にループし続けます…とにかくここに元のコードの実用的な例があります。

このメソッドは配列をクリアすることを好みます:

 for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0; 

これが実際の例です。 (シリアルモニターでキャリッジリターンを選択してください)

 char message[32]; uint8_t incomingByte = 0; uint8_t BufferPos = 0; int clearbyte = 0; void setup() { Serial.begin(9600); Serial.println("\n String conversion testing"); } void loop() { if (BufferPos >= 32) { Serial.print("Buffer Full\n"); BufferPos = 00; incomingByte = 0; } if (Serial.available()) { incomingByte = Serial.read(); message[BufferPos++]= incomingByte; switch(incomingByte) { case "\n": case " ": break; case "\r": Serial.println(message); for( int i = 0; i < sizeof(message); ++i ) message[i] = (char)0; BufferPos= 0; incomingByte= 0; } } } 

回答

この質問に対するすべてのコメントを読みましたが、すべてのコードは非常に冗長でした。その後、単純な関数と行の少ないコードを作成します。この場合、このコードは正常に機能すると思います

baudrateを115200未満に設定した場合、メッセージをchar配列に保存するためにdelay()を追加する必要があります

void loop() { char data[255]; uint8_t k = 0; while (Serial.available()) { data[k] = Serial.read(); k++; } for (int i = 0; i < k; i++) { Serial.print(data[i]); data [i] = "\0"; } //delay(50); } 

コメント

  • char data[] = {};は、長さがゼロの配列を提供します。データを入れようとするのは悪い考えです。
  • @NickGammonに同意します。回答を編集して、"うまくいくと思います"をテストしたら、明確なyes / noに置き換えてください。 コード。
  • @NickGammon修正してくれてありがとう、コードを修正しました

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です