String Arduino中的字符串长度有限制吗?

String Arduino中的字符串长度有限制吗?,string,arduino,String,Arduino,几个小时以来,我一直试图在arduino上组合一个简单的JSON对象字符串,以发送到Raspberry Pi运行节点 我似乎无法成功地构建字符串。我已经尝试过一次建成字符串: "{" + string1 + "," + string2 + "," + string3 + "}" etc... 我还尝试使用String.replace函数。每一次,我都会得到一点字符串,或者根本没有。 下面的代码显示了发生的情况: String msg = "{ \"message\" : \"statusUpd

几个小时以来,我一直试图在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, 
字符串长度有限制吗?我在文档中没有发现任何关于此类限制的提及。 除了标准的
以太网
库和通过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

Arduino的内存非常有限——大约2K用于存储数据(32K用于闪存中的程序)。在封面下,String类正在为每个字符串连接执行realloc调用。这可能导致内存碎片,其中没有一个连续的内存块可用于字符串

我建议您停止使用String类,只在开始时分配一个大的缓冲区并附加到它,但在分配它之前,您需要知道它会有多大


如果你想过一种危险的生活,你可以看看String类的源代码,看看是否可以强制它预先分配一个大的缓冲区,但我看不到有文档记录的方法来做到这一点。

Atmel处理器的内存管理相当有限,因此很容易导致内存碎片。请记住,运行时堆栈和堆也是有限的

静态字符串也可以放入PROGMEM中


arduino.cc上还有一个freememory函数,可以显示您有多少可用内存。

我在尝试使用arduino字符串类构建JSON时遇到了类似的困难。最终我放弃了,因为我意识到我试图将大型系统技术强加给一个小型嵌入式系统。现在,我使用预分配的字符数组和sprintf等C函数进行字符串操作,并以我仍然可以从应用程序中使用的最简洁的方式对数据进行编码

你可能会觉得有趣(不是我写的):

我在Arduino项目中从未使用过的五件事

  • 字符串类
  • 从表面上看,Arduino库中的String类使字符串处理更容易。它提供了一系列函数来完成一些在C语言中通常将字符串表示为指向字符数组的指针时无法轻松完成的事情。那么问题出在哪里呢

    问题在于,字符串操作动态分配内存,并且当程序的输入是可变的时,很难预测其分配方式,再加上Arduinos的RAM数量非常有限(Arduino Uno上的2K)。动态内存分配通常会导致内存碎片。这意味着您的程序可能会在某些输入或短时间内正常工作,但由于内存耗尽,会在其他输入或更长时间后崩溃。有关为什么在C/C++实现的嵌入式软件中动态内存分配是一个坏主意的更多信息,请参阅

    我什么时候可以使用字符串?当写一个快速而肮脏的草图来尝试某样东西时,只要它不需要保持在一起超过几分钟


    我在字符串长度方面也有类似的问题,但发现几乎所有情况下我都受到SPI缓冲区长度64的限制。无论是故意在代码中添加延迟,还是有太多的打印语句,我建议您始终注意可能的溢出。

    快速愚蠢的问题:您连接的任何字符串中都没有未转义的字符串定界符吗?不幸的是,没有。从我的编辑中可以看出,它在我缩短键名(“message”到“m”,“exhaustTemp”到“eT”等)后开始工作,因此它显然是一个字符串长度问题,或者至少是一个问题本身。尽管这里的所有答案都是正确的和有用的,您对freememory函数的引用帮助我确认它肯定是错误的原因。