2013-07-31 2 views
4

Я пытался часами собрать простую строку объекта JSON на ардуине, чтобы отправить его на запущенный узел Raspberry Pi.Есть ли ограничения на длину строки в Arduino?

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

"{" + 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-запросу (из примера проекта).

Любая идея, что может произойти?

EDIT: Ok, Я сократил свою строку следующим образом:

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

+0

Быстрый глупый вопрос: разве у вас есть разделитель строк без экранирования в любой из строк, которые вы объединяете? –

+0

К сожалению, нет. Как вы можете видеть из моего редактирования, он начал работать, как только я сократил имена ключей («сообщение» до «м», «выхлоп», «отменить» до «eT» и т. Д.). Таким образом, это определенно кажется проблемой длины строки или как минимум, проблема, проявляющаяся как таковая. – Dermot

ответ

2

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

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

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

+0

Несмотря на то, что все ответы здесь были правильными и полезными, ваша ссылка на функцию freememory помогла мне подтвердить, что это определенно является причиной ошибки. – Dermot

4

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

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

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

2

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

Вы могли бы найти this link интересный (я не писал):

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

  1. Класс Строка

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

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

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

0

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

Смежные вопросы