Ошибка 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
Поэтому для объектов он не применим. Или я неправильно понял?
Это я предложил, если вы решитесь переделывать библиотеки...