8

私は何時間もかけて、単純な JSON オブジェクト文字列を arduino にまとめて、Raspberry Pi の実行中のノードに送信しようとしました。

文字列を正常に構築できないようです。私は一度に文字列を構築しようとしました:

"{" + string1 + "," + string2 + "," + string3 + "}" etc...

また、String.replace 関数を使用してみました。ひもが少し残るか、まったくなくなるたびに。以下のコードは、何が起こっているかを示しています。

String msg = "{ \"message\" : \"statusUpdate\", ";
String active = " \"active\" : TOKEN, ";
String intakeTemp = " \"intakeTemp\" : TOKEN, ";
String intakeHumid = " \"intakeHumid\" : TOKEN, ";
String exhaustTemp = " \"exhaustTemp\" : TOKEN, ";
String exhaustHumid = " \"exhaustHumid\" : TOKEN, ";
String targetHumid = " \"targetHumid\" : TOKEN, ";
String completed = " \"taskCompleted\" : TOKEN }";


if(isActive)
  active.replace("TOKEN","true");
else
  active.replace("TOKEN","false");

intakeTemp.replace("TOKEN",floatToString(intakeTemperature,0));
intakeHumid.replace("TOKEN",floatToString(intakeHumidity,0));
exhaustTemp.replace("TOKEN",floatToString(exhaustTemperature,0));
exhaustHumid.replace("TOKEN",floatToString(exhaustHumidity,0));
targetHumid.replace("TOKEN",floatToString(targetHumidity,0));

if(taskFinished)
  taskCompleted.replace("TOKEN","true");
else
  taskCompleted.replace("TOKEN","false");



  String body = msg;
  Serial.println(body);
  body += active;
  Serial.println(body);
  body += intakeTemp;
  Serial.println(body);
  body += intakeHumid;
  Serial.println(body);
  body += exhaustTemp;
  Serial.println(body);
  body += exhaustHumid;
  Serial.println(body);
  body += targetHumid;
  Serial.println(body);
  body += taskCompleted;
  Serial.println(body);

上記のコードの最後のビットからわかるように、文字列が構築されているときに、シリアル モニターに出力しています。ただし、ここに私のシリアル出力があります:

{ "message" : "statusUpdate", 
{ "message" : "statusUpdate",  "active" : false, 
{ "message" : "statusUpdate",  "active" : false,  "intakeTemp" : 0.0, 
{ "message" : "statusUpdate",  "active" : false,  "intakeTemp" : 0.0,  "intakeHumid" : 0.0, 
{ "message" : "statusUpdate",  "active" : false,  "intakeTemp" : 0.0,  "intakeHumid" : 0.0,  "exhaustTemp" : 0.0, 
{ "message" : "statusUpdate",  "active" : false,  "intakeTemp" : 0.0,  "intakeHumid" : 0.0,  "exhaustTemp" : 0.0, 
{ "message" : "statusUpdate",  "active" : false,  "intakeTemp" : 0.0,  "intakeHumid" : 0.0,  "exhaustTemp" : 0.0, 
{ "message" : "statusUpdate",  "active" : false,  "intakeTemp" : 0.0,  "intakeHumid" : 0.0,  "exhaustTemp" : 0.0, 

文字列の長さに制限はありますか?ドキュメントでそのような制限についての言及は見つかりませんでした。標準Ethernetライブラリと HTTP リクエスト経由で送信するコード (サンプル プロジェクトから) を除いて、スケッチには他に多くのことはありません。

何が起こっているのでしょうか?

編集:わかりました、次のように文字列を短縮しました:

String msg = "{ \"m\" : \"status\", ";
String active = " \"a\" : TOKEN, ";
String intakeTemp = " \"iT\" : TOKEN, ";
String intakeHumid = " \"iH\" : TOKEN, ";
String exhaustTemp = " \"eT\" : TOKEN, ";
String exhaustHumid = " \"eH\" : TOKEN, ";
String targetHumid = " \"tH\" : TOKEN, ";
String dryerJustFinished = " \"f\" : TOKEN }";

案の定、それは機能し始めました:

{ "m" : "status", 
{ "m" : "status",  "a" : false, 
{ "m" : "status",  "a" : false,  "iT" : 0.0, 
{ "m" : "status",  "a" : false,  "iT" : 0.0,  "iH" : 0.0, 
{ "m" : "status",  "a" : false,  "iT" : 0.0,  "iH" : 0.0,  "eT" : 0.0, 
{ "m" : "status",  "a" : false,  "iT" : 0.0,  "iH" : 0.0,  "eT" : 0.0,  "eH" : 0.0, 
{ "m" : "status",  "a" : false,  "iT" : 0.0,  "iH" : 0.0,  "eT" : 0.0,  "eH" : 0.0,  "tH" : 0.0, 
{ "m" : "status",  "a" : false,  "iT" : 0.0,  "iH" : 0.0,  "eT" : 0.0,  "eH" : 0.0,  "tH" : 0.0,  "f" : false }

つまり、制限があります。これはメモリの制限ですか?

ちなみにハードウェアはArduino Uno R3

4

4 に答える 4

7

arduino のメモリは非常に限られています。データ用に約 2K (フラッシュ内のプログラム用に 32K) です。内部では、String クラスはすべての文字列連結に対して realloc 呼び出しを行っています。これにより、文字列に使用できる単一の連続したメモリ ブロックがない断片化されたメモリが発生する可能性があります。

String クラスの使用をやめて、最初に大きなバッファーを割り当てて追加することをお勧めしますが、割り当てる前にその大きさを把握する必要があります。

危険な生活をしたい場合は、String クラスのソース コードを見て、大きなバッファーを事前に割り当てるように強制できるかどうかを確認できますが、それを行うための文書化された方法は見当たりません。

于 2013-07-31T16:22:46.693 に答える
4

Atmel プロセッサのメモリ管理はかなり制限されているため、メモリが断片化されやすくなります。実行時のスタックとヒープも制限されていることに注意してください。

静的文字列も PROGMEM に入れることができます

arduino.ccには、空きメモリの量を表示するfreememory関数もあります。

于 2013-07-31T22:08:39.123 に答える
3

Arduino String クラスを使用して JSON を構築しようとすると、同様の問題が発生しました。最終的にはあきらめました。大規模なシステム技術を小さな組み込みシステムに押し込もうとしていることに気づいたからです。今では、事前に割り当てられた char 配列と sprintf などの C 関数を文字列操作に使用し、アプリケーションから引き続き使用できる最もコンパクトな方法でデータをエンコードしています。

このリンクは興味深いかもしれません(私が書いたものではありません):

Arduinoプロジェクトで私が絶対に使わない5つのこと....

  1. 文字列クラス

表面的には、Arduino ライブラリの String クラスを使用すると、文字列の処理が簡単になります。C ではよくあることですが、文字列を char 配列へのポインターとして表すと簡単にできないことを行うための関数が多数用意されています。では、何が問題なのでしょうか?

問題は、文字列操作がメモリを動的に割り当て、プログラムへの入力が可変である場合に予測しにくい方法で、Arduino の RAM の量が非常に限られている (Arduino Uno では 2K) という事実と相まってです。動的メモリ割り当ては、通常、メモリの断片化を引き起こします。これは、プログラムが一部の入力または短時間では正しく動作する可能性があることを意味しますが、他の入力で、または長時間経過すると、メモリの枯渇によりクラッシュします。C/C++ で実装された組み込みソフトウェアで動的メモリ割り当てが悪い考えである理由の詳細については、http://critical.eschertech.com/2010/07/30/dynamic-memory-allocation-in-critical-embedded-systems/を参照してください。 .

どのような場合に String を使用できますか? 何かを試すために簡単なスケッチを書くときは、数分以上まとめておく必要がない限り!

于 2013-08-04T04:34:43.003 に答える