【问题标题】:Are there limits on string length in Arduino?Arduino 中的字符串长度有限制吗?
【发布时间】:2013-07-31 13:59:54
【问题描述】:

我已经尝试了几个小时在 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

【问题讨论】:

  • 快速愚蠢的问题:您连接的任何字符串中都没有未转义的字符串分隔符吗?
  • 很遗憾没有。正如您从我的编辑中看到的那样,一旦我缩短了键名(“message”到“m”,“exhaustTemp”到“eT”等),它就开始工作了,所以它肯定似乎是一个字符串长度问题,或者在至少是一个问题。

标签: string arduino


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 尽管这里的所有答案都是正确且有用的,但您对 freememory 函数的引用帮助我确认这绝对是错误的原因。
    【解决方案3】:

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

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

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

    1. 字符串类

    从表面上看,Arduino 库中的 String 类使字符串处理更容易。它提供了许多函数来完成如果您将字符串表示为指向 char 数组的指针(就像在 C 中通常那样)则无法轻松完成的事情。那么问题出在哪里?

    问题在于,字符串操作以难以预测的方式动态分配内存,程序的输入何时是可变的,再加上 Arduino 的 RAM 数量非常有限(Arduino Uno 上为 2K)。动态内存分配通常会导致内存碎片。这意味着您的程序可能在某些输入或短时间内正常工作,但由于内存耗尽而与其他输入或在较长时间后崩溃。请参阅http://critical.eschertech.com/2010/07/30/dynamic-memory-allocation-in-critical-embedded-systems/,了解为什么动态内存分配在用 C/C++ 实现的嵌入式软件中是一个坏主意。

    什么时候可以使用字符串?当写一个速写草图来尝试一些东西时,只要它不必保持超过几分钟!

    【讨论】:

      【解决方案4】:

      我在字符串长度方面遇到了类似的问题,但在几乎所有情况下我都受到 SPI 缓冲区长度 64 的限制。无论是故意将延迟放入代码中,还是打印语句过多,我'd 建议始终注意可能的溢出。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-12
        • 1970-01-01
        • 2011-01-09
        • 2011-04-19
        • 2013-05-01
        相关资源
        最近更新 更多