Memory 如何减少Arduino Uno上的内存使用
我使用的是Arduino UNO、Dccduino的克隆,内存有问题。草图使用了25114字节,占程序存储空间的77%。最大值为32256字节。全局变量使用1968字节占动态内存的96%,而局部变量使用80字节。最大值为2048字节。可用内存不足,可能会出现稳定性问题。 有没有办法将内存减少20%左右?如果没有,我想我必须买Arduino Mega 代码如下:Memory 如何减少Arduino Uno上的内存使用,memory,arduino,rom,Memory,Arduino,Rom,我使用的是Arduino UNO、Dccduino的克隆,内存有问题。草图使用了25114字节,占程序存储空间的77%。最大值为32256字节。全局变量使用1968字节占动态内存的96%,而局部变量使用80字节。最大值为2048字节。可用内存不足,可能会出现稳定性问题。 有没有办法将内存减少20%左右?如果没有,我想我必须买Arduino Mega 代码如下: #include <OneWire.h> #include <DallasTemperature.h> #inc
#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();
}
我想我以前在另一个网站上看过这段代码。 根据您的代码,我假设您正在制作一个温度记录器,并且希望将数据记录在SD卡上。 如果使用DS1307RTC.h库和Time.h库,大多数代码都是冗余的。DS1307RTC是一个通用RTC库。有了它,你不需要一根电线,电线或SPI和电线。软件串行通信也是不必要的。 但是,我建议您在Github上查看我的Arduino数据记录器库:
我几乎已经将我在Uno上保存的内存最大化为22680字节,占程序存储空间的70%,1237字节占SRAM动态内存的60%。它自动配置RTC和SD卡。它生成一个CSV文件,每个月按日期组织导出到excel。我想我以前在另一个网站上见过这段代码。 根据您的代码,我假设您正在制作一个温度记录器,并且希望将数据记录在SD卡上。 如果使用DS1307RTC.h库和Time.h库,大多数代码都是冗余的。DS1307RTC是一个通用RTC库。有了它,你不需要一根电线,电线或SPI和电线。软件串行通信也是不必要的。 但是,我建议您在Github上查看我的Arduino数据记录器库:
我几乎已经将我在Uno上保存的内存最大化为22680字节,占程序存储空间的70%,1237字节占SRAM动态内存的60%。它自动配置RTC和SD卡。它制作了一个CSV文件,每个月按日期组织导出到excel。在我的时间里,我已经建立了几个Arduino数据记录器,所有使用SD卡的都因为内存不足而失败。SD本身使用ATMega 328上可用内存的一半。再加上其他硬件的几个库,你就根本没有内存来绘制草图了 我已经转到24LC512了。通常一个就足够了,但如果需要,最多可以使用4个不同的地址。这是一个相对较小的内存量,但我发现它总是足够的。生成兆字节的数据太容易了,这些数据太大,无法进行分析。一个24LC512存储的数据足以存储一个电子表格。唯一不好的一面是,您必须使用Arduino通过USB读回数据 我使用前两个字节存储记录数,下一个字节存储每条记录的字节数。尽管回顾过去,后者并不是真正必要的。您可能会认为前两个字节会“磨损”,因为它们在每次创建新条目时都会被重新写入,但这还没有发生在我身上。我已经让同一个Arduino连续运行了7年,现在除了对草图进行几次更新外,没有中断,每月生成1000多条记录,因此前两个字节必须被更新了那么多次。我从来没有遇到过前两个字节的问题,即使我有问题,它也足够便宜,可以替换24LC512
你甚至可以通过“热插拔”来逃脱:我让记录器运行,然后将内存芯片换成新的,这样我就可以在不中断记录器的情况下读取数据。读取记录数,然后递增并写入新的记录数和数据。我在我的时间内建立了几个Arduino数据记录器,所有使用SD卡的记录器都因内存不足而失败。SD本身使用ATMega 328上可用内存的一半。再加上其他硬件的几个库,你就根本没有内存来绘制草图了 我已经转到24LC512了。通常一个就足够了,但如果需要,最多可以使用4个不同的地址。这是一个相对较小的内存量,但我发现它总是足够的。生成兆字节的数据太容易了,这些数据太大,无法进行分析。一个24LC512存储的数据足以存储一个电子表格。唯一不好的一面是,您必须使用Arduino通过USB读回数据 我使用前两个字节存储记录数,下一个字节存储每条记录的字节数。尽管回顾过去,后者并不是真正必要的。您可能会认为前两个字节会“磨损”,因为它们在每次创建新条目时都会被重新写入,但这还没有发生在我身上。我已经让同样的Arduino连续运行了7年,现在除了对草图进行一些更新外,没有中断,每月生成1000多条记录,因此 rst两个字节必须已更新该次数。我从来没有遇到过前两个字节的问题,即使我有问题,它也足够便宜,可以替换24LC512
你甚至可以通过“热插拔”来逃脱:我让记录器运行,然后将内存芯片换成新的,这样我就可以在不中断记录器的情况下读取数据。读取记录数,然后增加记录数,然后写入新的数字和数据。我在谷仓中的系统中做的不仅仅是这些——SD卡、RTC、LCD显示屏、GPRS调制解调器、与其他设备的无线电通信、根据季节编程定时控制泵、雨水传感器、浮子传感器、温度传感器、电压传感器、,等等。以下是我发现的一些东西: 所有字符串文字都应替换为F宏调用和/或在flash上工作的本机字符串函数。所以,strcpypstring1,PSTRstring2,strcatpstring1,PSTRstring2类调用。 将对设备的大量访问转换为包含这些调用所需的任何数据结构的函数调用。您的arduino将更加努力地添加和删除堆栈和堆栈帧,但是当功能完成时,数据结构将从堆栈中删除,并且arduino上的机器周期比RAM便宜得多。因此,在单独的函数中将温度读取代码与文件写入分开。返回浮点值,然后将该浮点值发送到SD写入函数。 将所有串行代码隐藏在debug_打印代码中。因此,在调试时,您将使用debug_print调用,它们都将从生产代码中完全消失。 确保只在子例程中调用SD代码,并根据需要在这些子例程中实例化实际的FAT代码,而不是作为一个大的全局变量。 有许多不同的SD库,有些比其他的更便宜。四处逛逛。 在调用其中一个需要RAM的SD调用之前,请使用freeMemory变体来确定内存是否可用。如果您当时没有足够的RAM,您可能希望在EEPROM中实现某种循环缓冲区,以便在RAM可用时存储要写入SD的消息。 如果可能的话,使用布尔值和字节而不是int,并考虑使用标志字段来节省更多的RAM。你的温度总线上真的会有32000台设备吗?你可以在一个字节内得到255。
我在谷仓里做的不仅仅是一个系统——SD卡、RTC、LCD显示屏、GPRS调制解调器、与其他设备的无线电通信、根据季节编程定时控制水泵、雨水传感器、浮子传感器、温度传感器、电压传感器等。我发现了一些东西: 所有字符串文字都应替换为F宏调用和/或在flash上工作的本机字符串函数。所以,strcpypstring1,PSTRstring2,strcatpstring1,PSTRstring2类调用。 将对设备的大量访问转换为包含这些调用所需的任何数据结构的函数调用。您的arduino将更加努力地添加和删除堆栈和堆栈帧,但是当功能完成时,数据结构将从堆栈中删除,并且arduino上的机器周期比RAM便宜得多。因此,在单独的函数中将温度读取代码与文件写入分开。返回浮点值,然后将该浮点值发送到SD写入函数。 将所有串行代码隐藏在debug_打印代码中。因此,在调试时,您将使用debug_print调用,它们都将从生产代码中完全消失。 确保只在子例程中调用SD代码,并根据需要在这些子例程中实例化实际的FAT代码,而不是作为一个大的全局变量。 有许多不同的SD库,有些比其他的更便宜。四处逛逛。 在调用其中一个需要RAM的SD调用之前,请使用freeMemory变体来确定内存是否可用。如果您当时没有足够的RAM,您可能希望在EEPROM中实现某种循环缓冲区,以便在RAM可用时存储要写入SD的消息。 如果可能的话,使用布尔值和字节而不是int,并考虑使用标志字段来节省更多的RAM。你的温度总线上真的会有32000台设备吗?你可以在一个字节内得到255。