Есть ли ограничения на длину строки в Arduino?

Я пытался в течение нескольких часов собрать простую строку объекта JSON на arduino для отправки на узел Raspberry Pi.

Я не могу успешно построить строку. Я попытался построить строку все за один раз:

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

Я также попытался использовать строку.функция 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 ответов


процессор Atmel имеет довольно ограниченное управление памятью, поэтому его легко получить фрагментированную память. Помните, что стек времени выполнения и куча также ограничены.

статическая строка может быть помещена в PROGMEM также

существует также функция freememory на arduino.cc это покажет вам, сколько у вас свободной памяти.


arduino имеет очень ограниченную память -- около 2K для ваших данных (32K для вашей программы во вспышке). Под обложками класс String выполняет вызов realloc для каждой конкатенации строк. Это может привести к фрагментированной памяти, где нет ни одного смежного блока памяти, доступного для строки.

Я бы предложил вам прекратить использовать класс String и просто выделить большой буфер в начале и добавить к нему, но вам нужно будет иметь представление о том, насколько он велик будет до того, как вы его выделите.

Если вам нравится жить опасно, вы можете посмотреть исходный код для класса String и посмотреть, можете ли вы заставить его предварительно выделить большой буфер, но я не вижу документированного способа сделать это.


У меня были аналогичные трудности при попытке построить JSON с использованием класса Arduino String. В конце концов я сдался, потому что понял, что пытаюсь навязать большую системную технику крошечной встроенной системе. Теперь я использую предварительно выделенные массивы символов и функции C, такие как sprintf для обработки строк, и кодирую данные самым компактным способом, который я могу использовать из своего приложения.

вы можете найти этой ссылке интересно (я его не писал):

пять вещей, которые я никогда не использую в проектах Arduino....

  1. класс String

на лице, если это, класс String в библиотеке Arduino упрощает обработку строк. Он предоставляет множество функций для выполнения вещей, которые вы не можете легко сделать, если вы представляете строки как указатели на массивы символов, как обычно в C. Так в чем проблема?

проблема в том, что строковые операции выделяют память динамически и жесткими способами чтобы предсказать, когда входы в программу являются переменными, в сочетании с тем, что Arduinos имеют очень ограниченное количество ОЗУ (2K на Arduino Uno). Динамическое выделение памяти обычно вызывает фрагментацию памяти. Это означает, что ваша программа может работать правильно на некоторых входах или короткое время, но сбой с другими входами или через более длительное время из-за истощения памяти. Смотри http://critical.eschertech.com/2010/07/30/dynamic-memory-allocation-in-critical-embedded-systems/ подробнее о том, почему динамическое выделение памяти-плохая идея во встроенном программном обеспечении, реализованном на C/C++.

когда я могу использовать String? При написании быстрого и грязного эскиза, чтобы попробовать что-то, до тех пор, пока он не должен держаться вместе более нескольких минут!


У меня была аналогичная проблема с длиной строки, но почти во всех случаях я был ограничен длиной буфера SPI 64. Если задержки вводятся в код специально, или слишком много операторов печати, я бы предложил всегда помнить о возможных переполнениях.