Arduino IGC logger too much ram and rom used

Hello, I made a code that is not finished yet, but its main purpose is to log GPS data to SD with IGC format. The problem is that I was hopping to add many more functionalities to it, but it’s already taking almost all the memory the Nano has. I wonder where is my mistake, and how can I reduce the memory usage.

//Libraries
#include <SoftwareSerial.h>
#include <TinyGPS++.h>             //http://arduiniana.org/libraries/tinygpsplus/
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <Arduino.h>  //"Arduino.h" for eepromex?
#include <U8x8lib.h>  //text only for OLED
#include <EEPROMex.h>              //https://github.com/thijse/Arduino-EEPROMEx
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

//Initializations
TinyGPSPlus gps;
SoftwareSerial ss(4, 3);           // GPS  RXpin,TXpin
Adafruit_BME280 bme;            // Hey BME
U8X8_SH1106_128X64_NONAME_4W_HW_SPI u8x8(/* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); //MOSI 11 SCK 13 OLED stufff
//

//functions
void Error();
void UpdateGps();
void LogIGC();
//

//Declarations
#define SEALEVELPRESSURE_HPA (1013.25)
#define chipSelect 7 //SD module CS to Pin 7,MOSI-pin 11,MISO-pin 12,CLK - pin 13;
#define ErrorLed A0
#define Button0Pin 8
#define Button1Pin 5
#define Button2Pin 6
#define interval 1000
boolean StartLoging = true;
byte LoggerPeriod = 2;//(1s to 5s);
unsigned long previousMillis = 0;                         //B185209 2302718S 04546811W  A-0056 00 583
String IGCdata = "B1852092302718S04546811WA-005600583";                                           // UTC      Lat     Long     QFEbaro // GpsH
long Lat;
long Long;
int GpsAlt;
int BarAlt;


//
void setup() {


  pinMode(ErrorLed, OUTPUT);
  pinMode(Button0Pin, INPUT_PULLUP);
  pinMode(Button1Pin, INPUT_PULLUP);
  pinMode(Button2Pin, INPUT_PULLUP);
  bme.begin();

  //display stuff not here yet .................

  if (!SD.begin(chipSelect)) {
    while (digitalRead(Button1Pin) == HIGH) {     // press button to ignore SD error
      Error();        //Check SD and indicate status with LED,it should also show SD error on display
    }
  }
  //Tell here SD is fine or has been ignored

  ss.begin(4800);    //GPS receiver serial baudrate
  Serial.begin(115200);  //Serial for debugging
}//end of setup

void loop() {
  UpdateGps();
  if (millis() - previousMillis >= (interval * LoggerPeriod) && StartLoging == true ) {
    LogIGC();
  }
}//end of loop

void LogIGC() {
  previousMillis = millis();
  ///////////////////////////Handle GPS time/////////////////////////////
  IGCdata = "";        //Clears string then starts building a new
  IGCdata += "B";
  if (gps.time.hour() > 9) {
    IGCdata += gps.time.value();
    IGCdata.remove(7, 2);        //removes 00 after seconds. 
  }
  else {
    IGCdata += "0";                   //add the 00 if hour Z is 9, 8, 7...
    IGCdata += gps.time.value();
    IGCdata.remove(7, 2);         //removes 00 after seconds
  }
  ///////////////////////////Handle latitude///////////////////////////////
  Lat = (gps.location.lat() * 100000); //remove decimal point from float
  if (Lat >= 0) {              // if NORTH
    if (Lat < 1000000) {
      IGCdata += "0";
      IGCdata += Lat;
    }
    else {                    // if more than 9 degrees
      IGCdata += Lat;
    }
    IGCdata += "N";
  }
  else {                       // if SOUTH
    if (Lat > -1000000) {
      IGCdata += "0";
      IGCdata += Lat;
      IGCdata.remove(8, 1);    //remove minus for IGC
    }
    else {                     //if less than -9 degrees
      IGCdata += Lat;
      IGCdata.remove(7, 1);     //remove minus for IGC
    }
    IGCdata += "S";
  }
  ///////////////////////////Handle longitude/////////////////////////////
  Long = (gps.location.lng() * 100000); //remove decimal point from float
  if (Long >= 0) {            //if EAST
    if (Long < 1000000) {     //if less than 9 degrees
      IGCdata += "00";
      IGCdata += Long;
    }
    else if (Long >= 1000000 && Long < 10000000) {  //if less than 100 degrees & more than 9
      IGCdata += "0";
      IGCdata += Long;
    }
    else {                   // if more than 99 degrees
      IGCdata += Long;
    }
    IGCdata += "E";
  }
  else {                       //if WEST
    if (Long > -1000000) {     //if more than -10 degrees
      IGCdata += "00";
      IGCdata += Long;
      IGCdata.remove(17, 1);
    }
    else if (Long <= -1000000 && Long > -10000000) {  //if more than -100 degrees & less than -9
      IGCdata += "0";
      IGCdata += Long;
      IGCdata.remove(16, 1);
    }
    else {                   // if less than -99 degrees
      IGCdata += Long;
      IGCdata.remove(15, 1);
    }
    IGCdata += "W";
  }
  ///////////////////////////Handle altimetry////////////////////////////////
  IGCdata += "A";
  BarAlt = (bme.readAltitude(SEALEVELPRESSURE_HPA));
  if (BarAlt < 10000 && BarAlt > 1000 ) {
    IGCdata += "0";
    IGCdata += BarAlt;
  }
  else if (BarAlt < 1000 && BarAlt > 99) {
    IGCdata += "00";
    IGCdata += BarAlt;
  }
  else if (BarAlt < 100 && BarAlt > 9) {
    IGCdata += "000";
    IGCdata += BarAlt;
  }
  else if (BarAlt < 10 && BarAlt > -1) {
    IGCdata += "0000";
    IGCdata += BarAlt;
  }
  else if (BarAlt < 0 && BarAlt > -10 ) {
    IGCdata += "-000";
    IGCdata += BarAlt;
    IGCdata.remove(29, 1);
  }
  else if (BarAlt > -100 && BarAlt < -9) {
    IGCdata += "-00";
    IGCdata += BarAlt;
    IGCdata.remove(28, 1);
  }
  else if (BarAlt > -1000 && BarAlt < -99) {
    IGCdata += "-0";
    IGCdata += BarAlt;
    IGCdata.remove(27, 1);
  }

  GpsAlt = ((gps.altitude.meters() - 0));  // calibrate gps altitude error here
  if (GpsAlt < 10000 && GpsAlt > 1000 ) {
    IGCdata += "0";
    IGCdata += GpsAlt;
  }
  else if (GpsAlt < 1000 && GpsAlt > 99) {
    IGCdata += "00";
    IGCdata += GpsAlt;
  }
  else if (GpsAlt < 100 && GpsAlt > 9) {
    IGCdata += "000";
    IGCdata += GpsAlt;
  }
  else if (GpsAlt < 10 && GpsAlt > -1) {
    IGCdata += "0000";
    IGCdata += GpsAlt;
  }
  else if (GpsAlt < 0 && GpsAlt > -10 ) {
    IGCdata += "-000";
    IGCdata += GpsAlt;
    IGCdata.remove(34, 1);
  }
  else if (GpsAlt > -100 && GpsAlt < -9) {
    IGCdata += "-00";
    IGCdata += GpsAlt;
    IGCdata.remove(33, 1);
  }
  else if (GpsAlt > -1000 && GpsAlt < -99) {   // Lowest place on earth is about - 450m
    IGCdata += "-0";
    IGCdata += GpsAlt;
    IGCdata.remove(32, 1);
  }
  File dataFile = SD.open("log.igc", FILE_WRITE);
  if (dataFile) {
    dataFile.println"";
    dataFile.println(IGCdata);
    dataFile.close();
  }
  // print to the serial port for debbuging
  Serial.println(IGCdata);
}

void UpdateGps() {
  while (ss.available() > 0) {
    gps.encode(ss.read());
  }
}

void Error() {
  digitalWrite(ErrorLed, HIGH);
  delay(80);                      //Here only to be used before code starts
  digitalWrite(ErrorLed, LOW);
  delay(80);
}

Maybe a library is using lots of memory? Or just my String… I don’t know.

Sketch uses 28010 bytes (86%) of program storage space. Maximum is 32256 bytes.
Global variables use 1734 bytes (84%) of dynamic memory, leaving 314 bytes for local variables. Maximum is 2048 bytes.

AFAIR the SD card uses a large buffer array. With the few RAM bytes left it's unlikely that any String handling will succeed. You better use a bigger Arduino, with more memory. And try to avoid the String class on Arduinos.

Get rid of the big-S String. Just print each item to the file directly.

86% memory usage is no big deal, so long as you know you aren't using lots of dynamic memory with Strings.

With the few RAM bytes left it's unlikely that any String handling will succeed.

It didn’t work at first, but then I declared a dumb equivalent string in order to allocate the memory and it succeeded after that.
I can’t use a bigger Arduino otherwise it will be too big for my purpose.
About writing directly to sd that would mean having more smaller strings wouldn’t it? Because I need to manipulate the variables in a way that they are always written with the same number of characters due to the IGC format, thus having to remove “-” and add 00 to the left sometimes.

A Teensy 3.2 is physically smaller than a Nano and it has a lot more memory.

For writing leading zeroes, use something like…

  if(value<100) datafile.print("0");
  if(value<10) datafile.print("0");
  datafile.print(value);

I am trying to switch to an stm32 but after loading the usb bootloader it seems like it stopped working.

IDE gives me this error when trying to upload via usb:

maple_loader v0.1
Resetting to bootloader via DTR pulse

A fatal error has been detected by the Java Runtime Environment:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000007110b5db, pid=12076, tid=7356

JRE version: Java(TM) SE Runtime Environment (9.0+11) (build 9.0.4+11)

Java VM: Java HotSpot(TM) 64-Bit Server VM (9.0.4+11, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)

Problematic frame:

C [jSSC-2.8_x86_64.dll+0xb5db]

No core dump will be written. Minidumps are not enabled by default on client versions of Windows

An error report file with more information is saved as:

C:\Users\Caio\AppData\Local\Arduino15\packages\stm32duino\tools\stm32tools\2018.7.2\win\hs_err_pid12076.log

If you would like to submit a bug report, please visit:

Crash Report

The crash happened outside the Java Virtual Machine in native code.

See problematic frame for where to report the bug.

I did everything correctly...

I gave up on the STM, but found this: https://robotdyn.com/mega-2560-pro-embed-ch340g-atmega2560-16au.html That's a great Mini arduino mega 2560 board. It will do the job I need.