Глобальные переменные занимают много места в динамической памяти.

Я использую две простые библиотеки (см. 1, 2) Я нашел в Интернете свой код на Arduino Uno, к сожалению, я также использую ROS, и все эти библиотеки занимают много места , когда я компилирую свой код, я получаю эту ошибку:

Global variables use 2,112 bytes (103%) of dynamic memory, leaving -64 bytes for local variables. Maximum is 2,048 bytes.

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

Кажется, я не совсем понимаю концепцию глобальных переменных. Например, я изменил все переменные double в библиотеках на переменные float, но это совсем не изменило использование динамической памяти. Как я могу использовать меньше памяти?

, 👍2

Обсуждение

Вы поместили свои строковые литералы во флэш-память?, @KIIV

Я сократил их до 1 буквы, чтобы посмотреть, насколько это уменьшит размер, но размещение во флэш-памяти не решит проблему, так как ее недостаточно., @Natjo

Что ж, тогда вы должны предоставить свой код, чтобы мы могли его попробовать..., @KIIV

Я проверил, и около 75% глобальных переменных уже используются библиотеками, которые я использую. Поскольку они с открытым исходным кодом, я прыгал, чтобы изменить их. Они представлены в ссылках, которые я дал в своем вопросе., @Natjo

Очень общее описание: переменным, которые зависают (глобальные, статические и т. Д.), Присваивается собственное место в памяти в ОЗУ, переменным с ограниченной областью действия временно назначается место в памяти в ОЗУ в области, называемой стеком, и переменные, которые никогда не изменяются. можно поместить в память программ. На встроенном процессоре это обычно означает помещение переменной во флэш-память., @st2000

Это совет «с ходу», поэтому это всего лишь комментарий, а не ответ, но, если вам не хватает памяти, почему бы не переключиться на Arduino на базе ARM. Многие Arduino на базе ARM имеют гораздо больше памяти, чем, скажем, Uno., @st2000

Сколько из этих объектов вы создаете? Наиболее очевидным кандидатом на экономию памяти является double lastInputs[100] в классе PID_ATune. Он занимает 400 байт. Если вы сократите этот массив, убедитесь, что вы не получаете к нему доступ из связей., @Edgar Bonet

@EdgarBonet Я уменьшил число до 80, помогло, спасибо! Почему это не меняет потребление памяти, если я изменяю двойное число на плавающее?, @Natjo

@Jonas, потому что в Arduino double и float имеют одинаковый размер: https://www.arduino.cc/en/Reference/Float или https://www.arduino.cc/en/Reference/Double., @Mali

Первая библиотека определяет класс PID_ATune, который содержит множество элементов, включая массив из 100 double, т.е. 400 байтов для каждого экземпляра PID_ATune. Не уверен, что там нужно так много двойников, но вы можете сначала попытаться уменьшить это число., @jfpoilpret

Вы решили это, я столкнулся с той же самой проблемой! так как в настоящее время я использую библиотеку автонастройки! и не может оптимизировать пример кода! пожалуйста помоги, @Mutaz alHawash

К сожалению, я не смог решить проблему. Я думаю, что в то время я перешел на более крупный микроконтроллер. Извиняюсь. Вы могли бы попробовать использовать исходный код библиотеки автонастройки напрямую и настроить ее?, @Natjo


3 ответа


Лучший ответ:

2

Когда вы пишете программу, часть памяти может быть определена во время компиляции из-за ее предопределения (float и double в Arduino — не модель Due — используйте 4 байтов каждый - в Due double использует 8 байтов для 64-битной точности).

Но есть часть памяти, о которой можно узнать только во время выполнения; где мы говорим об объектах (или массивах, определяемых пользовательским вводом). В этих случаях программам необходимо динамически выделять память, для чего в язык C++ встроены операторы new и delete. Дополнительная информация: Динамическая память.

Вы должны управлять созданием объектов и массивов (они создаются с помощью new, а затем удаляются с помощью delete).

Если ваши требования превышают ресурсы любого Arduino (кроме Arduino Due), вам следует перейти на модель Due, которая имеет больше памяти и вычислительной мощности (но меняет 5 В на 3,3 В, будьте осторожны).

,

Существует также Mega 2560, который имеет ту же архитектуру, что и Uno (AVR), но в 4 раза больше оперативной памяти., @Edgar Bonet


2

@jonas У меня была похожая проблема, не совсем превышающая лимит. Одна вещь, которую вы можете сделать, это переместить строки во Flash. <pgmspace.h> есть определение PSTR, которое помещает литерал во flash имя шаблона, которое мы обычно используем просто strcpy, нам нужно использовать strcpy_P. strcpy_P указывает, что строка будет получена из флэш-памяти и скопирована в пространство SRAM. Как только он окажется в памяти SRAM, мы сможем манипулировать им, как захотим. например:

setPatternName((char*)PSTR("My PatternName"));

void setPatternName(const char* text) {
  memset(patternName, MAX_PATTERN_NAME_LEN + 1, 0 );
  strcpy_P(patternName, text);
  int length = strlen(patternName);
}

Это должно привести к значительному сокращению использования памяти.

,

1
char buf[50];

char* tm1Txt (byte num){
  if (num == 0){strcpy_P(buf, (char*) F("t1 - Задepжka koмaнды xoд"));}
  if (num == 1){strcpy_P(buf, (char*) F("t2 - Bpeмя cepвoфиkcaции "));}
  if (num == 2){strcpy_P(buf, (char*) F("t3 - Bpeмя дoтягивания   "));}
  if (num == 3){strcpy_P(buf, (char*) F("t4 - Bpeмя тopмoжeния    "));}
  if (num == 4){strcpy_P(buf, (char*) F("t5 - Наложениe тормоза   "));}
  if (num == 5){strcpy_P(buf, (char*) F("t6 - Снятия нагр воздуха "));}
  return buf;
}
,