8

几个小时以来,我一直在尝试在 arduino 上组合一个简单的 JSON 对象字符串,以发送到 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 函数进行字符串操作,并以我仍然可以在我的应用程序中使用的最紧凑的方式对数据进行编码。

You might find this link interesting (I didn't write it):

Five things I never use in Arduino projects....

  1. The String class

On the face if it, the String class in the Arduino library makes string handling easier. It provides a host of functions to do things that you can’t easily do if you represent strings as pointers to char arrays, as is usual in C. So what’s the problem?

The problem is that String operations allocate memory dynamically and in ways that are hard to predict when the inputs to the program are variable, combined with the fact that Arduinos have a very limited amount of RAM (2K on the Arduino Uno). Dynamic memory allocation typically causes memory fragmentation. This means that your program may work correctly for some inputs or a short while, but crashes with other inputs or after a longer time, due to memory exhaustion. See http://critical.eschertech.com/2010/07/30/dynamic-memory-allocation-in-critical-embedded-systems/ for more about why dynamic memory allocation is a bad idea in embedded software implemented in C/C++.

When might I use String? When writing a quick-and-dirty sketch to try something out, as long it doesn’t have to hold together for more than a few minutes!

于 2013-08-04T04:34:43.003 回答
0

I was having a similar problem with string length, but found in almost all cases that I was being limited by SPI buffer length of 64. Whether delays are put into the code on purpose, or there are too many print statements, I'd suggest always being mindful of possible overflows.

于 2014-09-26T17:24:53.823 回答