Reputation:
I am using a clone of Arduino UNO, Dccduino and I have problem with the memory.Sketch uses 25,114 bytes (77%) of program storage space. Maximum is 32,256 bytes. Global variables use 1,968 bytes (96%) of dynamic memory, leaving 80 bytes for local variables. Maximum is 2,048 bytes. Low memory available, stability problems may occur. Is there any way to reduce the memory about 20% if not I think I have to buy Arduino Mega
Here is the code:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include <GPRS_Shield_Arduino.h>
#include <SoftwareSerial.h>
// Data wire is plugged into port 3 and 2 on the Arduino
#define ONE_WIRE_BUS_1 3 // Many sensors on pin 3
#define ONE_WIRE_BUS_2 2 // Many sensors on pin 2
#define TEMPERATURE_PRECISION 9 // Lower resolution
#define PIN_TX 7
#define PIN_RX 8
#define BAUDRATE 9600
#define PHONE_NUMBER "xxxxxxxxxxxxx"
GPRS gprsTest(PIN_TX, PIN_RX, BAUDRATE); //RX,TX,PWR,BaudRate
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire1(ONE_WIRE_BUS_1);
OneWire oneWire2(ONE_WIRE_BUS_2);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors1(&oneWire1);
DallasTemperature sensors2(&oneWire2);
int numberOfDevices1; // Number of temperature devices found on pin 3
int numberOfDevices2; // Number of temperature devices found on pin 2
DeviceAddress tempDeviceAddress1; // We'll use this variable to store a found device address for bus 3
DeviceAddress tempDeviceAddress2; // We'll use this variable to store a found device address for bus 2
File myFile;
RTC_DS3231 rtc; // Create a RealTimeClock object
void setup(void)
{
// start serial port
#ifndef ESP8266
while (!Serial); // for Leonardo/Micro/Zero
#endif
Serial.begin(9600);
delay(3000);
Serial.println(F("Dallas Temperature IC Control Library Demo"));
Serial.print( F("Initializing SD card..."));
if (!SD.begin(4)) {
Serial.println(F("\ninitialization failed!"));
return;
}
Serial.println(F("initialization done."));
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, lets set the time!");
// following line sets the RTC to the date & time this sketch was compiled
//rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
/* while(!gprsTest.init()) { //gprs init
delay(1000);
Serial.print(F("init error\r\n"));
Serial.println(F("gprs init success"));*/ It takes 20% of dynamic memory so i cant use it
}
Serial.println(F("start to call ..."));// Call when device will start
gprsTest.callUp(PHONE_NUMBER);
Serial.println("start to send message ...");
gprsTest.sendSMS(PHONE_NUMBER, "Hi device is ON"); //define phone number and text
// Start up the library
sensors1.begin();
sensors2.begin();
// Grab a count of devices on the wire
numberOfDevices1 = sensors1.getDeviceCount();
numberOfDevices2 = sensors2.getDeviceCount();
// locate devices on the bus
Serial.print(F("Locating devices..."));
Serial.print(F("Found "));
Serial.print(numberOfDevices1, DEC );
Serial.print(F("+"));
Serial.print(numberOfDevices2, DEC );
Serial.println(F(" devices."));
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors1.isParasitePowerMode()) Serial.println(F("Sensors 1 ON"));
else Serial.println(F("\nSensors 1 OFF"));
if (sensors2.isParasitePowerMode()) Serial.println(F("Sensors 2 ON"));
else Serial.println(F("Sensors 2 OFF"));
// Loop through each device, print out address for pin 3
for (int i = 0; i < numberOfDevices1; i++)
{
// Search the wire for address
if (sensors1.getAddress(tempDeviceAddress1, i))
{
Serial.print(F("Found device "));
Serial.print(i, DEC);
Serial.print(F(" with address: "));
printAddress(tempDeviceAddress1);
Serial.println();
Serial.println(F("\n"));
// set the resolution to TEMPERATURE_PRECISION bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors1.setResolution(tempDeviceAddress1, TEMPERATURE_PRECISION);
} else {
Serial.print(F("Found ghost device for pin 3 at "));
Serial.print(i, DEC);
Serial.print(F(" but could not detect address. Check power and cabling"));
}
}
// Loop through each device, print out address for pin 2
for (int i = 0; i < numberOfDevices2; i++)
{
// Search the wire for address
if (sensors2.getAddress(tempDeviceAddress2, i))
{
Serial.print(F("Found device "));
Serial.print(i + numberOfDevices1, DEC);
Serial.print(F(" with address: "));
printAddress(tempDeviceAddress2);
Serial.println();
Serial.println(F("\n"));
// set the resolution to TEMPERATURE_PRECISION bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors2.setResolution(tempDeviceAddress2, TEMPERATURE_PRECISION);
} else {
Serial.print(F("Found ghost device for pin 2 at "));
Serial.print(i, DEC);
Serial.print(F(" but could not detect address. Check power and cabling"));
}
}
}
void loop(void)
{
// call sensors1.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print(F("Requesting temperatures to pin 3..."));
sensors1.requestTemperatures(); // Send the command to get temperatures for pin 3
Serial.println(F("DONE"));
myFile = SD.open("test1.txt", FILE_WRITE); //open file
// Loop through each device , print out temperature data for pin 3
for (int i = 0; i < numberOfDevices1; i++)
{
// Search the wire for address
if (sensors1.getAddress(tempDeviceAddress1, i))
{
// Output the device ID
Serial.print(F("Temperature for device: "));
Serial.println(i, DEC);
// It responds almost immediately. Let's print out the data
printTemperature1(tempDeviceAddress1);// Use a simple function to print out the data
Serial.print(F("\n"));
}
delay(4000);
//else ghost device! Check your power requirements and cabling
}// End forloop for pin 3
if (numberOfDevices2 != 0) {
Serial.print(F("Requesting temperatures to pin 2..."));
sensors2.requestTemperatures(); // Send the command to get temperatures for pin 2
Serial.println(F("DONE"));
}
// Loop through each device for pin 2, print out temperature data
for (int i = 0; i < numberOfDevices2; i++)
{
// Search the wire for address
if (sensors2.getAddress(tempDeviceAddress2, i))
{
// Output the device ID
Serial.print(F("Temperature for device: "));
Serial.println(i + numberOfDevices1, DEC);
// It responds almost immediately. Let's print out the data
printTemperature2(tempDeviceAddress2);// Use a simple function to print out the data
Serial.print(F("\n"));
}
else Serial.print(F("ghost device! Check your power requirements and cabling"));
delay(4000);
} //End forloop for pin 3
myFile.close(); // Should I close it?
}// End loop()
void printAddress(DeviceAddress deviceAddress) // function to print a device address
{
for (uint8_t i = 0; i < 8; i++)
{
if (deviceAddress[i] < 16) Serial.print(F("0"));
Serial.print(deviceAddress[i], HEX);
}
}
void printTemperature1(DeviceAddress deviceAddress1) // function to print the temperature for a device (pin 3)
{
float tempC = sensors1.getTempC(deviceAddress1);
Serial.print("Temp C: ");
Serial.print(tempC);
if (myFile)
{
Serial.println(F("\nWriting to test.txt..."));
myFile.print(F("C: "));
myFile.print(tempC);
print_time(); // Call print_time() function to print time on file
myFile.print(F("\n"));
Serial.print(F("Done!"));
}
else Serial.print(F("Error opening file 1"));
Serial.println("\n");
}
void printTemperature2(DeviceAddress deviceAddress2) // function to print the temperature for a device (pin 2)
{
float tempC = sensors2.getTempC(deviceAddress2);
Serial.print(F("Temp C: "));
Serial.print(tempC);
if (myFile)
{
Serial.print(F("\nWriting to test.txt..."));
myFile.print(F("C: "));
myFile.print(tempC);
print_time(); // Call print_time() function to print time on file
myFile.print(F("\n"));
Serial.print(F("Done!"));
} else Serial.print(F("Error opening file 2"));
Serial.println("\n");
}
void print_time() { // print time function
DateTime now = rtc.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
myFile.print(now.year(), DEC);
myFile.print('/');
myFile.print(now.month(), DEC);
myFile.print('/');
myFile.print(now.day(), DEC);
myFile.print(now.hour(), DEC);
myFile.print(':');
myFile.print(now.minute(), DEC);
myFile.print(':');
myFile.print(now.second(), DEC);
myFile.println();
}
Upvotes: 1
Views: 4259
Reputation: 71
I'm doing more than that for a system in my barn - SD card, RTC, LCD display, GPRS modem, radio communication with other devices, controlling pumps based on programmed timing by season, rain sensors, float sensors, temp sensors, voltage sensors, etc. Here are some things I've found:
Upvotes: 3
Reputation: 11
I've built several Arduino data loggers in my time, and all of the ones using SD cards have failed because of lack of memory. The SD on its own uses half of the memory available on an ATMega 328. Add to that a couple of libraries for other hardware and you have no memory left at all for your sketch.
I have gone over to 24LC512s. One is normally enough, but you can use up to 4 with different addresses if you want. This is a relatively small amount of memory, but I have found it is always enough. It is too easy to generate megabytes of data which is too large to be analysed. One 24LC512 holds more than enough data for one spreadsheet. The only down side is that you have to use an Arduino to read back the data through the USB.
I use the first two bytes to store the number of records, and the next byte to store the number of bytes per record. (Although in retrospect the latter is not really necessary.) You might think that the first two bytes would “wear out” because they are re-written every time a new entry is made, but this has not happened to me yet. I have had the same Arduino continuously running for 7 years now (uninterrupted apart from a few updates to the sketch), and generating over 1000 records per month, so the first two bytes must have been updated that number of times. I have never had a problem with the first two bytes, and even if I did, it would be cheap enough to replace the 24LC512.
You can even get away with “hot plugging”: I leave the logger running and change over the memory chip for a fresh one so that I can read the data without interrupting the logger. (Read the number of records, then increment it and write the new number and the data.)
Upvotes: 1
Reputation: 26
I think I've seen this code before on another site. From your code I assume you're making a temperature logger and you want to log the data on the SD card. Most of your code is redundant if you use the DS1307RTC.h library and the Time.h library. DS1307RTC is a generic RTC library. With it you don't need OneWire, Wire or SPI and Wire. Software Serial also is unnecessary. However, I suggest you check out my Arduino DataLogger Library on Github: https://github.com/FreelanceJavaDev/DataLogger
I've pretty much maxed out the memory I saved on my Uno down to 22,680 bytes (70%) of program storage space and 1,237 bytes (60%) of SRAM (Dynamic memory). It automatically configures the RTC and SD card. It makes a CSV file for export to excel for each month it's running organized by date.
Upvotes: 1