Problem with code-running out of memory, need help!

I have no prior knowledge of programming/coding and don't know how to make my code efficient so its not glitching. The Sketch uses 23194 bytes (71%) out of 32256 bytes and Global variables use 1624 bytes (79%) of dynamic memory out of 2048 bytes. The error shows; Low memory available, stability problems may occur.
I have air quality sensor, temperature&humidity sensor, gps and LCD screen with SD card reader attached to arduino uno and I would like the sensors to be recorded on the SD card as at the moment it doesn't read all the sensors and I think its because of the low memory issue. The lcd screen is to just read the results for air quality mainly but if it will help increase the memory it can be rid off.
Any help will be appreciated!!! thank you!

CODE:
#include <Wire.h>
#include <LiquidCrystal.h>
#include <dht.h>
#include <SDS011.h>
#include <SD.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

dht DHT;

#define DHT11_PIN 3

int cs = 4; // Set Chip Select to pin ten

float p10, p25;
int error;

SDS011 my_sds;

LiquidCrystal lcd( 8,9,4,5,6,7 ); //interfacing pins
File myFile;
char myFileName[] = "test.txt";

static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

int displaymode;
void setup()
{
Serial.begin(9600);

while (!Serial) { }
Serial.println("Initializing SD card...");
Serial.println();

pinMode(cs, OUTPUT);

pinMode(SS, OUTPUT); // Documentation says you're supposed to do this

// see if the card is present and can be initialized:
if (!SD.begin(cs)) {
Serial.println("SD did not initialize");
while (1) ;
}
Serial.println("SD initialized.");

ss.begin(GPSBaud);

my_sds.begin(2, 6); //RX, TX
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.setCursor(0,0);
lcd.print("LCD Key Shield");
lcd.setCursor(0,1);
lcd.print("Press Key:");
displaymode=1;
}

void loop()
{
int x;
int chk = DHT.read11(DHT11_PIN); // read temp & humidty
error = my_sds.read(&p25, &p10); // reaad air quality
gps.encode(ss.read()); // read gps

Serial.print("DisplayMode = "+String(displaymode));
Serial.print("Temperature = ");
Serial.println(DHT.temperature);
Serial.print("Humidity = ");
Serial.println(DHT.humidity);

Serial.println("P2.5: " + String(p25));
Serial.println("P10: " + String(p10));

Serial.print("Latitude= ");
Serial.print(gps.location.lat(), 6);
Serial.print(" Longitude= ");
Serial.println(gps.location.lng(), 6);

myFile = SD.open(myFileName, FILE_WRITE);
// This next statement checks to see if the file
myFile.println("==================="); // Send Your First Line to that file
myFile.print("Temperature = ");
myFile.println(DHT.temperature);
myFile.print("Humidity = ");
myFile.println(DHT.humidity);

myFile.println("P2.5: " + String(p25));
myFile.println("P10: " + String(p10));

myFile.print("Latitude= ");
myFile.print(gps.location.lat(), 6);
myFile.print(" Longitude= ");
myFile.println(gps.location.lng(), 6);

myFile.flush(); // Save it.

if (displaymode==1) {
lcd.print("Temp: ");
lcd.println(DHT.temperature);
lcd.print("Hum: ");
lcd.println(DHT.humidity);
} else if (displaymode == 2) {
lcd.println("P2.5: " + String(p25));
lcd.println("P10: " + String(p10));
} else if (displaymode == 3) {
lcd.print("Latitude= ");
lcd.print(gps.location.lat(), 6);
lcd.print(" Longitude= ");
lcd.println(gps.location.lng(), 6);
}
delay(2000);

x = analogRead (0);
lcd.setCursor(10,1);
/* if (x < 60) {
displaymode=1; //lcd.print ("Right ");
}
else if (x < 200) {
displaymode=2; //lcd.print ("Up "); //analog voltage 145
}
else if (x < 400){
displaymode=3; //lcd.print ("Down "); //analog voltage 329
}
else if (x < 600){
displaymode=4; //lcd.print ("Left "); //analog voltage 585
}
else if (x < 800){
lcd.print ("Select"); //analog voltage 741
*/
}

You forgot to mention what type of Arduino you are using. Doesn't that seem like a pretty important piece of information? Why would you leave that out?

If this is for an UNO then that's a lot of library to try to go in an UNO. You probably need a Mega for that code. You can try using the F macro on your constant strings (look it up) and stop using the String class. That wastes memory and your use of the + operator to concatenate strings fragments memory and makes your problem that much worse. The String class should be avoided on microcontrollers where memory is limited and there is nothing managing the memory for you. Use char arrays instead.

Please edit your post to add code tags, as described in the "How to use this forum" post.

OP is using an Uno. It is (hidden) in the text :wink:

Thank you for replying! Yes sorry its for Arduino Uno. I have looked up the F macro and started getting rid of the strings and I can already see the global variable bytes going down considerably!
Thank you for your suggestion this seems to be solving my issue :slight_smile:

sterretje:
OP is using an Uno. It is (hidden) in the text :wink:

From the memory available? Maybe. But OP should still be smart enough to share that information and not make me have to get it from that sort of thing. When asking for help, it is never good to cover up information that might help someone to help you.

sterretje:
OP is using an Uno. It is (hidden) in the text :wink:

Also shown in the attached diagram, that shouldn't have to be downloaded to sort it out. However, how often do we ask for a diagram?

Delta_G:
From the memory available? Maybe. But OP should still be smart enough to share that information and not make me have to get it from that sort of thing. When asking for help, it is never good to cover up information that might help someone to help you.

From OP's opening post

I have air quality sensor, temperature&humidity sensor, gps and LCD screen with SD card reader attached to arduino uno

OK I take it back then. It was hidden in there. Answer remains the same.

And .....Reduce the amount of “printed” stuff - all those words have to be stored in memory, you can shorten a lot of them “lat” instead of latitude and so on . ... “SD ok” instead of initialised . You’d prob be ok if you were ruthless here

Check variable types , use those that need the least memory ( eg int instead of float ).

^ instead of up ...

hammy:
And .....Reduce the amount of “printed” stuff - all those words have to be stored in memory, you can shorten a lot of them “lat” instead of latitude and so on .

Not if he uses F macro. Then all those words go in program space which he has plenty of.

Not if he uses F macro. Then all those words go in program space which he has plenty of.

Can you say a bit more about that , “ f macro” in this context ; that’s new to me and sounds useful ?

Edit - just looked that up on the theBaldEngineers site - very useful and simple to use, but well hidden !!

The OP may benefit form this - suggests he Google’s it and moves the print statements as suggested to free off some space .

Thx

Serial.println("hello world");

"hello world" is copied at startup from flash to RAM and will permanently occupy that RAM.

Serial.println(F("hello world"));

"hello world" is copied from flash to RAM when the statement is executed and RAM is available again after that.

hammy:
Can you say a bit more about that , “ f macro” in this context ; that’s new to me and sounds useful

Thx

No, not "f" macro, it's the "F" macro.