Ошибка Low memory available, stability problems may occur.
- Войдите на сайт для отправки комментариев
Здравствуйте.
Использую Arduino UNO
Задача такова - писать на SD карту показания температуры, влажности, освещения.
На данный момент подключил только SD карту и модуль часов DS3231 считываю время и температуру с часов и пишу все это в файл.
Пока тестировал только работу с SD картой все было нормально. Но как только подключил библиотеку часов то памяти SRAM 2KB (ATmega328) сразу стало не хватать. при компиляции выдается предупреждение:
Sketch uses 22 038 bytes (68%) of program storage space. Maximum is 32 256 bytes.
Global variables use 1 718 bytes (83%) of dynamic memory, leaving 330 bytes for local variables. Maximum is 2 048 bytes.
Low memory available, stability problems may occur.
В итоге при создании очередного файла программа зависает.
То есть я правильно понимаю что Arduino UNO не потянет несколько устройств таких как SD карта, часы DS3231, датчик влажности DHT22 и сетевую карту Ethernet ENC28J60?
Или можно поковырять библиотеки уменьшив их размер исключением не востребованных функций, вернее глобальных переменных?
Или есть еще какие либо варианты решения проблемы?
Вот код:
// подключаем библиотеку карты #include <SdFat.h> // подключим библиотеку часов #include <Wire.h> #include <DS3231.h> // CS у нас будет на 8 пине #define SDCSpin 8 // Установим интервал опроса датчиков #define IntervalDataReadMS 2000 // опередели максимальный размер одного файла в 1 килобайт (1 000 байт) #define MaxSizeDataFile 1000 // Файл у нас будет состоять из наименования и номера файла. будет обрезаться по размеру чтобы не был слишком большим. char fileName[13] = "DATA0000.CSV"; //------------------------------------------------------------------------------ // Объявим сам объект SD карты SdFat sd; // Объект файл для создания лог файла SdFile file; // часы DS3231 clock; // структура для хранения даты и времения RTCDateTime dt; //------------------------------------------------------------------------------ void setup() { // Инициализируем serial Serial.begin(9600); delay(1000); // инициализируем часы clock.begin(); // Инициализируем SD карту if (InitSDCard()) { // ищем поседний лог файл который был создан чтобы записать в него дату и событие перезагрузки InitLogFile(); } } //------------------------------------------------------------------------------ // void setup() //------------------------------------------------------------------------------ void loop() { // пишем в файл if (file.open(fileName, FILE_WRITE)) { Serial.println("Write data"); // первая колонка это время dt = clock.getDateTime(); file.print(clock.dateFormat("Y-m-d H:i:s", dt)); file.print("\t"); // вторая колонка это температура с часов clock.forceConversion(); file.print(clock.readTemperature()); file.println(); file.close(); int fram = freeRam(); Serial.print("RAM free - "); Serial.println(fram); } else { sd.errorHalt("ERR open file 1"); } // проверяем не закончился ли у нас файл ControlLogFile(); delay(200); } //------------------------------------------------------------------------------ // void loop() //------------------------------------------------------------------------------ // Функция инициализации карты памяти // В случае неудачной инициализации возвращает false и отсанавливает SD // В случае удачной инициализации возвращает true bool InitSDCard() { // инициализируем SD карту для того чтобы проверить установлена она или нет if (!sd.begin(SDCSpin, SPI_FULL_SPEED)) { // SPI_HALF_SPEED половина скорости SPI интерфейса если не работает полная скорость SPI_FULL_SPEED Serial.println("Не удалась инициализация на полной скорости"); if (!sd.begin(SDCSpin, SPI_HALF_SPEED)) { // не получилось запустить и на половине пишем ошибку и останавливаем SD Serial.println("Не удалась инициализация на половине скорости"); sd.initErrorHalt(); Serial.println("SD карта не инициализирована!!!"); return false; } } return true; } // bool InitSDCard() //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // функция работы с созданием и контролем размера файла. void InitLogFile() { if (!sd.exists(fileName)) { // файла с начальным именем "DATA0000.CSV" не существует. Создаем его if (file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) { Serial.print("Create file - "); Serial.println(fileName); } else { sd.errorHalt("ERR open file"); } // закрываем файл file.close(); } else { // файл существует Serial.print("Old file have - "); Serial.println(fileName); // проверим размер файла и если он больше необходимого то создадим новый ControlLogFile(); } } // void InitLogFile() //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // функция работы с созданием и контролем размера файла. void ControlLogFile() { uint32_t myFileSize; // файл существует while (sd.exists(fileName)) { // открываем файл на чтение и смотрим размер if (file.open(fileName, FILE_READ)) { myFileSize = file.fileSize(); file.close(); // пишем информацию о файле Serial.print("File - "); Serial.print(fileName); Serial.print("\t size - "); Serial.println(myFileSize); // если размер найденного файла больше допустимого проверяем есть ли следующий if (myFileSize >= MaxSizeDataFile) { // извлекаем счетчик String currentCounter = (fileName); currentCounter = currentCounter.substring(4, 8); int fileCount = currentCounter.toInt(); // добавляем 1 fileCount++; // добавляем нули впереди String myStr = String(fileCount); int sizeStr = myStr.length(); while (sizeStr < 4) { myStr = "0" + myStr; sizeStr++; } // собираем имя файла String strFileName = "DATA" + myStr + ".CSV"; // переводим строку в char strFileName.toCharArray(fileName, sizeof(fileName)); Serial.print("Char count - "); Serial.print(currentCounter); Serial.print("\t"); Serial.print("Int count - "); Serial.print(fileCount); Serial.print("\t"); Serial.print("Str count - "); Serial.print(myStr); Serial.println(); } else { // размер файла меньше допустимого пишем в него Serial.println("Write to file"); break; } } else { sd.errorHalt("ERR open file"); } } } // void ControlLogFile() //------------------------------------------------------------------------------ int freeRam() { extern int __heap_start, *__brkval; int v; return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); }
Дежа вю...
А где в коде библиотека для ENC28J60, или памяти не хватает уже на этом этапе? Расковырять библиотеки можно. Можно так-же почитать это http://arduino.cc/en/Reference/PROGMEM и попробовать применить.
Дежа вю...
А где в коде библиотека для ENC28J60, или памяти не хватает уже на этом этапе? Расковырять библиотеки можно. Можно так-же почитать это http://arduino.cc/en/Reference/PROGMEM и попробовать применить.
До ENC28J60 дело не дошло, подключил только SD карту и SD3231 и место в SRAM кончилось.
PROGMEM мне особо не поможет потому как у меня осталась только одна глобальная переменная и та небольшая. Так что вижу только один путь решения для Arduino UNO это убрать из используемых библиотек неиспользуемый функционал :-)
Дежа вю...
А где в коде библиотека для ENC28J60, или памяти не хватает уже на этом этапе? Расковырять библиотеки можно. Можно так-же почитать это http://arduino.cc/en/Reference/PROGMEM и попробовать применить.
До ENC28J60 дело не дошло, подключил только SD карту и SD3231 и место в SRAM кончилось.
PROGMEM мне особо не поможет потому как у меня осталась только одна глобальная переменная и та небольшая. Так что вижу только один путь решения для Arduino UNO это убрать из используемых библиотек неиспользуемый функционал :-)
Все-таки дежа-вю...
http://arduino.ru/forum/programmirovanie/sd-card-initsializiruetsya-no-rabotaet-esli-sketch-menee-24k
А дело не в простых глобальных переменных, а в глобальных объектах (пардон за терминологию)
Вот как минимум - в этих
Попробуйте стандартную библиотеку
#include <SD.h>
А дело не в простых глобальных переменных, а в глобальных объектах (пардон за терминологию)
Вот как минимум - в этих
но вроде как написано что PROGMEM используется для типов переменных:
prog_char - a signed char (1 byte) -127 to 128
prog_uchar - an unsigned char (1 byte) 0 to 255
prog_int16_t - a signed int (2 bytes) -32,767 to 32,768
prog_uint16_t - an unsigned int (2 bytes) 0 to 65,535
prog_int32_t - a signed long (4 bytes) -2,147,483,648 to * 2,147,483,647.
prog_uint32_t - an unsigned long (4 bytes) 0 to 4,294,967,295
Поэтому для объектов он не применим. Или я неправильно понял?
Попробуйте стандартную библиотеку
#include <SD.h>
Пробовал, результат тот же.
И стандартная читает карты только до 4ГБ, сделална на основе SdFat.h более ранней версии.
А дело не в простых глобальных переменных, а в глобальных объектах (пардон за терминологию)
Вот как минимум - в этих
но вроде как написано что PROGMEM используется для типов переменных:
prog_char - a signed char (1 byte) -127 to 128
prog_uchar - an unsigned char (1 byte) 0 to 255
prog_int16_t - a signed int (2 bytes) -32,767 to 32,768
prog_uint16_t - an unsigned int (2 bytes) 0 to 65,535
prog_int32_t - a signed long (4 bytes) -2,147,483,648 to * 2,147,483,647.
prog_uint32_t - an unsigned long (4 bytes) 0 to 4,294,967,295
Поэтому для объектов он не применим. Или я неправильно понял?
Это я предложил, если вы решитесь переделывать библиотеки...