How to optimize and gain FLASH/RAM

Hello everyone I am new to this forum and before starting everything I just want to say that I am french so please note that i can't express myself very well.

Okay so to summarize everything I have a project to do for school but the project relies on memory problems. The code itself is not hard to do, it's just long, but the problem is that we use a Arduino Uno which has not much FLASH memory and RAM. I have the project ready that i tested in different .ini files but if I put them all in one file, I have to put a big part of the code in commentary so that it's not used when compiling the code. I would love if someone can help me and help me gain RAM / FLASH memory. Thank you all.

#include <SoftwareSerial.h>
#include <Wire.h>
#include <RTClib.h>
#include <forcedClimate.h>
#include <ChainableLED.h>
#include <SdFat.h>
#include <EEPROM.h>

#define MODE_STANDARD 1
#define MODE_MAINTENANCE 2
#define MODE_ECO 3
#define MODE_CONFIGURATION 4

#define PIN_BOUTON_VERT 2
#define PIN_BOUTON_ROUGE 3
#define PIN_LUMIN A3
#define PIN_SD 4
#define TAILLE_TABLEAU 15

SdFat SD;
RTC_DS1307 rtc;
ForcedClimate climateSensor = ForcedClimate();
ChainableLED leds(8, 9, 1);

SoftwareSerial SoftSerial(6, 7);

int mode_actu = 0;
int mode_prec;
bool EtatBoutonVert = false;
unsigned long TempsBoutonVert;
bool EtatBoutonRouge = false;
unsigned long TempsBoutonRouge;
unsigned long TempsInactif;
int adresse = 0;

const int ParametresDefault[TAILLE_TABLEAU] =
    {
        10,   // LOG_INTERVAL,
        4096, // FILE_MAX_SIZE,
        30,   // TIMEOUT,
        1,    // LUMIN,
        255,  // LUMIN_LOW,
        768,  // LUMIN_HIGH,
        1,    // TEMP_AIR,
        -10,  // MIN_TEMP_AIR,
        60,   // MAX_TEMP_AIR,
        1,    // HYGR,
        0,    // HYGR_MINT,
        50,   // HYGR_MAXT,
        1,    // PRESSURE
        850,  // PRESSURE_MIN
        1080  // PRESSURE_MAX
};

int ParametresConfig[TAILLE_TABLEAU] =
    {
        10,   // LOG_INTERVAL,
        4096, // FILE_MAX_SIZE,
        30,   // TIMEOUT,
        1,    // LUMIN,
        255,  // LUMIN_LOW,
        768,  // LUMIN_HIGH,
        1,    // TEMP_AIR,
        -10,  // MIN_TEMP_AIR,
        60,   // MAX_TEMP_AIR,
        1,    // HYGR,
        0,    // HYGR_MINT,
        50,   // HYGR_MAXT,
        1,    // PRESSURE
        850,  // PRESSURE_MIN
        1080  // PRESSURE_MAX
};

#define LOG_INTERVAL_INDEX 0
#define FILE_MAX_SIZE_INDEX 1
#define TIMEOUT_INDEX 2
#define LUMIN_INDEX 3
#define LUMIN_LOW_INDEX 4
#define LUMIN_HIGH_INDEX 5
#define TEMP_AIR_INDEX 6
#define MIN_TEMP_AIR_INDEX 7
#define MAX_TEMP_AIR_INDEX 8
#define HYGR_INDEX 9
#define HYGR_MINT_INDEX 10
#define HYGR_MAXT_INDEX 11
#define PRESSURE_INDEX 12
#define PRESSURE_MIN_INDEX 13
#define PRESSURE_MAX_INDEX 14

File32 Fichier;

unsigned long TempsDerniereMesure = 0;
char RevisionFichier = '0';

bool VerificationEEPROM = false;
long LOG_INTERVAL = ParametresConfig[LOG_INTERVAL_INDEX];
String GPS;

void BoutonRougeInterruption(void);
void BoutonVertInterruption(void);

void Mode_standard();
void Mode_Maintenance();
void Mode_economique();
void Mode_config();
void LEDMode();
void Enregistrement_SD();
void ChangerHorloge(int annee, int mois, int jour, int heure, int minute, int seconde);

void GenerationDonnees();
void DonneesGPS();
void connexionSD();
void erreur_acces_horloge();
void erreur_acces_GPS();
void erreur_acces_donnees_capteurs();
void erreur_donnees_incoherentes();
void erreur_carte_SD_pleine();
void erreur_acces_ecriture();
void ModificationConfig();
void Affichage(String Donnees, bool ligne);
void PointVirgule();
void SeparateurHorloge();
void Creation();

void ClearMoniteurSerie();
void FaireEEPROM(int ParametresConfig[TAILLE_TABLEAU]);
void LireEEPROM(int ParametresConfig[TAILLE_TABLEAU]);

void setup()
{
  Serial.begin(9600);
  SoftSerial.begin(9600);

  ClearMoniteurSerie();

  pinMode(PIN_BOUTON_VERT, INPUT);
  pinMode(PIN_BOUTON_ROUGE, INPUT);

  Wire.begin();
  leds.init();
  climateSensor.begin();

  connexionSD();
  SD.begin();
  Serial.println(F("Connexion à la carte SD réussie."));
  leds.setColorRGB(0, 255, 255, 255);

  while (!rtc.begin())
  {
    Serial.println(F("Module RTC pas trouvé"));
    erreur_acces_horloge();
  }

  rtc.adjust(DateTime((__DATE__), (__TIME__)));

  attachInterrupt(digitalPinToInterrupt(PIN_BOUTON_VERT), BoutonVertInterruption, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_BOUTON_ROUGE), BoutonRougeInterruption, CHANGE);

  LireEEPROM(ParametresConfig);

  for (int i = 0; i < TAILLE_TABLEAU; i++)
  {
    if (ParametresConfig[i] != ParametresDefault[i])
    {
      VerificationEEPROM = true;
      break;
    }
  }

  if (!VerificationEEPROM)
  {
    int adresse = 0;
    for (int i = 0; i < TAILLE_TABLEAU; i++)
    {
      EEPROM.put(adresse + i * sizeof(long), ParametresDefault[i]);
    }
  }

  if (digitalRead(PIN_BOUTON_ROUGE) == LOW)
  {
    mode_actu = MODE_CONFIGURATION;
  }

  else
  {
    mode_actu = MODE_STANDARD;
  }
}

void loop()
{
  switch (mode_actu)
  {
  case MODE_STANDARD:
    Mode_standard();
    break;
  case MODE_MAINTENANCE:
    Mode_Maintenance();
    break;
  case MODE_ECO:
    Mode_economique();
    break;
  case MODE_CONFIGURATION:
    // Mode_config();
    break;
  }
}

void BoutonVertInterruption(void)
{
  if ((digitalRead(PIN_BOUTON_VERT) == LOW) && (!EtatBoutonVert))
  {
    EtatBoutonVert = true;
    TempsBoutonVert = millis();
  }
  else if ((digitalRead(PIN_BOUTON_VERT) == HIGH) && (EtatBoutonVert))
  {
    EtatBoutonVert = false;
    if ((millis() - TempsBoutonVert) >= (5000))
    {
      if (mode_actu == MODE_STANDARD)
      {
        mode_actu = MODE_ECO;
        LEDMode();
      }
      else if (mode_actu == MODE_ECO)
      {
        mode_actu = MODE_STANDARD;
        LEDMode();
      }
    }
  }
}

void BoutonRougeInterruption(void)
{
  if ((digitalRead(PIN_BOUTON_ROUGE) == LOW) && (!EtatBoutonRouge))
  {
    EtatBoutonRouge = true;
    TempsBoutonRouge = millis();
  }

  else if (digitalRead(PIN_BOUTON_ROUGE) == HIGH && (EtatBoutonRouge))
  {
    EtatBoutonRouge = false;
    if ((millis() - TempsBoutonRouge) >= 5000)
    {
      TempsBoutonRouge = millis();
      switch (mode_actu)
      {
      case MODE_CONFIGURATION:
        mode_actu = MODE_STANDARD;
        LEDMode();
        break;
      case MODE_STANDARD:
      case MODE_ECO:
        mode_prec = mode_actu;
        mode_actu = MODE_MAINTENANCE;
        LEDMode();
        break;
      case MODE_MAINTENANCE:
        mode_actu = mode_prec;
        mode_prec = 0;
        switch (mode_actu)
        {
        case MODE_STANDARD:
          LEDMode();
          break;
        case MODE_ECO:
          LEDMode();
          break;
        }
      }
    }
  }
}

void Mode_standard()
{
  LEDMode();
  connexionSD();
  TempsDerniereMesure = millis();
  if ((millis() - TempsDerniereMesure) >= (LOG_INTERVAL * 60 * 1000))
  {
    Creation();
    // Enregistrement_SD();
    TempsDerniereMesure = millis();
    LEDMode();
  }
}

void Mode_Maintenance()
{
  LEDMode();
  delay(1000);
  Creation();
  LEDMode();
  delay(9000);
}

void Mode_economique()
{
  LEDMode();
  connexionSD();
  TempsDerniereMesure = millis();
  if ((millis() - TempsDerniereMesure) >= (LOG_INTERVAL * 60 * 1000 * 22))
  {
    // Condition GPS 1 fois sur 2
    Serial.println(LOG_INTERVAL * 60 * 1000);
    Creation();
    // Enregistrement_SD();
    TempsDerniereMesure = millis();
    LEDMode();
  }
}

/*
void Mode_config()
{
  LEDMode();
  TempsInactif = millis();
  Serial.println(F("Mode Configuration. Tapez vos commandes de configuration."));

  while ((millis() - TempsInactif) < (30000))
  {

     // Ce if pique un peu les yeux :sob:
     // Nan en vrai tu connais l'index de ce que tu veux modifier, donc mieux vaut faire une
     // fonction ou tu définis cette valeur plutot que de faire un write de toutes les valeurs
     // dans l'EEPROM, surtout qu'elle a un cycle d'ecriture limité, demande moi quand t'arrivera ici si tu veux
     // que je te t'explique ou si tu veux le faire par toi meme

    if (Serial.available() > 0)
    {
      String commande = Serial.readStringUntil('\n');


       * Ici, les startsWith prennent BEAUCOUP de ram ou de flash je sais plus, mais Ă  la place, tu peux les remplacer
       * par des ==, si tu divise le string Ă  l'endroit ou est le '=', t'obtient le membre de gauche et tu le compares,
       * si tu veux je t'explique ou alors si tu veux le faire toi mĂŞme
       * parce que je pense que c'est ici que tu perds le plus (avec le ModificationConfig() en plus évidemment)
       *
       * De plus, tu isole le membre de droite et tu le transformes en int, comme ça pas besoin de faire des substrings qui
       * prennent aussi pas mal de mémoire :)
       *
      if (commande.startsWith("LOG_INTERVAL="))
      {
        ParametresConfig[LOG_INTERVAL_INDEX] = commande.substring(13).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("FILE_MAX_SIZE="))
      {
        ParametresConfig[FILE_MAX_SIZE_INDEX] = commande.substring(14).toInt();
        ModificationConfig();
      }
      else if (commande.equals("RESET"))
      {
        for (int i = 0; i < TAILLE_TABLEAU; i++)
        {
          ParametresConfig[i] = ParametresDefault[i];
        }
        FaireEEPROM(ParametresConfig);
        ModificationConfig();
      }
      else if (commande.equals("VERSION"))
      {
        Serial.println(F("Version du programme : 1.0"));
        Serial.println(F("Numéro de lot : 1"));
      }
      else if (commande.startsWith("TIMEOUT="))
      {
        ParametresConfig[TIMEOUT_INDEX] = commande.substring(8).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("LUMIN="))
      {
        ParametresConfig[LUMIN_INDEX] = commande.substring(6).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("LUMIN_LOW="))
      {
        ParametresConfig[LUMIN_LOW_INDEX] = commande.substring(10).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("LUMIN_HIGH="))
      {
        ParametresConfig[LUMIN_HIGH_INDEX] = commande.substring(11).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("TEMP_AIR="))
      {
        ParametresConfig[TEMP_AIR_INDEX] = commande.substring(9).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("MIN_TEMP_AIR="))
      {
        ParametresConfig[MIN_TEMP_AIR_INDEX] = commande.substring(9).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("MAX_TEMP_AIR="))
      {
        ParametresConfig[MAX_TEMP_AIR_INDEX] = commande.substring(9).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("HYGR="))
      {
        ParametresConfig[HYGR_INDEX] = commande.substring(5).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("HYGR_MINT="))
      {
        ParametresConfig[HYGR_MINT_INDEX] = commande.substring(10).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("HYGR_MAXT="))
      {
        ParametresConfig[HYGR_MAXT_INDEX] = commande.substring(10).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("PRESSURE="))
      {
        ParametresConfig[PRESSURE_INDEX] = commande.substring(5).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("PRESSURE_MIN="))
      {
        ParametresConfig[PRESSURE_MIN_INDEX] = commande.substring(13).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("PRESSURE_MAX="))
      {
        ParametresConfig[PRESSURE_MAX_INDEX] = commande.substring(13).toInt();
        ModificationConfig();
      }
      else if (commande.startsWith("CLOCK="))
      {
        String Horloge = commande.substring(6);
        int annee = Horloge.substring(0, 4).toInt();
        int mois = Horloge.substring(5, 7).toInt();
        int jour = Horloge.substring(8, 10).toInt();
        int heure = Horloge.substring(11, 13).toInt();
        int minute = Horloge.substring(14, 16).toInt();
        int seconde = Horloge.substring(17, 19).toInt();
        ChangerHorloge(annee, mois, jour, heure, minute, seconde);
      }
      else
      {
        Serial.println(F("Commande inexistante."));
      }
      TempsInactif = millis();
    }
  }
  Serial.println(F("Fin de la configuration. Retour au mode standard."));
  mode_actu = MODE_STANDARD;
}
*/

/*
void Enregistrement_SD()
{
  DateTime Maintenant = rtc.now();
  String NomFichier;

  NomFichier = String(Maintenant.year() % 100) + String(Maintenant.month()) + String(Maintenant.day()) + "_" + String(RevisionFichier) + ".LOG";
  // snprintf(NomFichier, sizeof(NomFichier), "%02d%02d%02d_%c.LOG", Maintenant.year() % 100, Maintenant.month(), Maintenant.day(), RevisionFichier);

  connexionSD();

  Fichier = SD.open(NomFichier, FILE_WRITE);

  // Verifier si carte SD pleine

  if (Fichier)
  {
    // Mesures des capteurs
    // ...

     *
     * Comme je t'avais dit, mieux vaut faire le print dans le fichier plutot que de faire un enorme string
     * maintenant que tu as la fonction Affichage, t'as juste à appeler la fonction qui genere les données ici
     *

    // Écriture des données dans le fichier
    Fichier.close();

    // Vérifier la taille du fichier
    if ((Fichier.size()) > (ParametresConfig[FILE_MAX_SIZE_INDEX]))
    {
      RevisionFichier++;
    }

    TempsDerniereMesure = millis();
  }
  else
  {
    Serial.println(F("Erreur d'écriture sur la carte SD."));
    erreur_carte_SD_pleine();
    TempsDerniereMesure = millis();
  }
}
*/

void ChangerHorloge(int annee, int mois, int jour, int heure, int minute, int seconde)
{
  DateTime NouvelleHorloge(annee, mois, jour, heure, minute, seconde); // Année, mois, jour, heure, minute, seconde
  rtc.adjust(NouvelleHorloge);
  Serial.println(F("Horloge changée avec succès."));
}

void LEDMode()
{
  switch (mode_actu)
  {
  case MODE_STANDARD:
    leds.setColorRGB(0, 0, 255, 0);
    break;
  case MODE_MAINTENANCE:
    leds.setColorRGB(0, 255, 155, 0);
    break;
  case MODE_ECO:
    leds.setColorRGB(0, 0, 0, 255);
    break;
  case MODE_CONFIGURATION:
    leds.setColorRGB(0, 255, 0, 0);
    break;
  default:
    break;
  }
}

void erreur_acces_horloge()
{                                 // Si erreur d'accès à l'horloge
  leds.setColorRGB(0, 255, 0, 0); // Allume la LED en rouge
  delay(1000);                    // On attend 1 sec
  leds.setColorRGB(0, 0, 0, 255); // Allume la LED en bleu
  delay(1000);                    // On attend 1 sec
}

void erreur_acces_GPS()
{                                   // Si erreur d'accès au GPS
  leds.setColorRGB(0, 255, 0, 0);   // Allume la LED en rouge
  delay(1000);                      // On attend 1 sec
  leds.setColorRGB(0, 255, 255, 0); // Allume la LED en jaune
  delay(1000);                      // On attend 1 sec
}

void erreur_acces_donnees_capteurs()
{                                 // Si erreur d'accès aux données d'un capteur
  leds.setColorRGB(0, 255, 0, 0); // Allume la LED en rouge
  delay(1000);                    // On attend 1 sec
  leds.setColorRGB(0, 0, 255, 0); // Allume la LED en verte
  delay(1000);                    // On attend 1 sec
}

void erreur_donnees_incoherentes()
{                                 // Si données incohérentes
  leds.setColorRGB(0, 255, 0, 0); // Allume la LED en rouge
  delay(1000);                    // On attend 1 sec
  leds.setColorRGB(0, 0, 255, 0); // Allume la LED en vert
  delay(2000);                    // On attend 2 sec
}

void erreur_carte_SD_pleine()
{                                     // Si erreur de carte SD pleine
  leds.setColorRGB(0, 255, 0, 0);     // Allume la LED en rouge
  delay(1000);                        // On attend 1 sec
  leds.setColorRGB(0, 255, 255, 255); // Allume la LED en blanc
  delay(1000);                        // On attend 1 sec
}

void erreur_acces_ecriture()
{                                     // Si erreur d'accès et d'écriture sur la carte SD
  leds.setColorRGB(0, 255, 0, 0);     // On allume la LED en rouge
  delay(1000);                        // On attend 1 sec
  leds.setColorRGB(0, 255, 255, 255); // On allume la LED en blanc
  delay(2000);                        // On attend 2 sec
}

void GenerationDonnees()
{
  climateSensor.takeForcedMeasurement();

  if (ParametresConfig[LUMIN_INDEX])
  {
    int Luminosite = analogRead(PIN_LUMIN);
    Affichage(String(Luminosite) + " ; ", false);
  }
  else
  {
    Affichage("Capteur désactivé ; ", false);
  }

  float Temperature_Air = climateSensor.getTemperatureCelcius();
  if (ParametresConfig[TEMP_AIR_INDEX])
  {
    if (Temperature_Air >= ParametresConfig[MIN_TEMP_AIR_INDEX] && Temperature_Air <= ParametresConfig[MAX_TEMP_AIR_INDEX])
    {
      Affichage(String(Temperature_Air) + " ; ", false);
    }
    else
    {
      erreur_donnees_incoherentes();
      Affichage("Hors intervalle ; ", false);
    }
  }
  else
  {
    Affichage("Capteur désactivé ; ", false);
  }

  if (ParametresConfig[HYGR_INDEX])
  {
    float Hygrometrie = climateSensor.getRelativeHumidity();
    if (Temperature_Air >= ParametresConfig[MIN_TEMP_AIR_INDEX] && Temperature_Air <= ParametresConfig[MAX_TEMP_AIR_INDEX])
    {
      Affichage(String(Hygrometrie) + " ; ", false);
    }
    else
    {
      erreur_donnees_incoherentes();
      Affichage("Hors intervalle ; ", false);
    }
  }
  else
  {
    Affichage("Capteur désactivé ; ", false);
  }

  if (ParametresConfig[PRESSURE_INDEX])
  {
    float Pression = climateSensor.getPressure();
    if (Pression >= ParametresConfig[PRESSURE_MIN_INDEX] && Pression <= ParametresConfig[PRESSURE_MAX_INDEX])
    {
      Affichage(String(Pression), true);
    }
    else
    {
      erreur_donnees_incoherentes();
      Affichage("Hors intervalle", true);
    }
  }
  else
  {
    Affichage("Capteur désactivé", true);
  }
}

void connexionSD()
{
  while (!SD.begin(PIN_SD))
  {
    Serial.println(F("Connexion Ă  la carte SD impossible, veuillez verifier la connexion."));
    erreur_acces_ecriture();
  }
}

void ModificationConfig()
{
  /*
   *  Comme dit au dessus, Changer ça :'(
   * Tu sais quel paramètre tu changes dans le mode config donc ne modifie que cette valeur
   * Par contre pour le setup tu peux le laisser :)
   */
  Serial.println(F("Modification effectuée avec succès."));
  FaireEEPROM(ParametresConfig);
}

void ClearMoniteurSerie()
{
  for (int i = 0; i < 30; i++)
  {
    Serial.println();
  }
}

void FaireEEPROM(int ParametresConfig[TAILLE_TABLEAU])
{
  adresse = 0;
  for (int i = 0; i < TAILLE_TABLEAU; i++)
  {
    EEPROM.put(adresse + i * sizeof(long), ParametresConfig[i]);
  }
}

void LireEEPROM(int ParametresConfig[TAILLE_TABLEAU])
{
  adresse = 0;
  for (int i = 0; i < TAILLE_TABLEAU; i++)
  {
    EEPROM.get(adresse + i * sizeof(long), ParametresConfig[i]);
  }
}

void DonneesGPS()
{
  if (SoftSerial.available())
  {
    GPS = "";
    unsigned long StartGPS = millis();
    do
    {
      GPS = SoftSerial.readStringUntil('\n');
      if ((millis() - StartGPS) > 5000)
      {
        erreur_acces_GPS();
        Affichage("GPS Timeout", false);
        PointVirgule();
        StartGPS = millis();
        break;
      }
    } while (!GPS.startsWith(F("$GPGGA")));
    Affichage(GPS, false);
    PointVirgule();
  }
}

void Affichage(String Donnees, bool ligne)
{
  if (mode_actu == MODE_MAINTENANCE)
  {
    if (ligne)
    {
      Serial.println(Donnees);
    }
    else
    {
      Serial.print(Donnees);
    }
  }
  else
  {
    Fichier.print(Donnees);
  }
}

void PointVirgule()
{
  Affichage(" ; ", false);
}

void SeparateurHorloge()
{
  Affichage(":", false);
}

void Creation()
{
  DateTime Maintenant = rtc.now();
  Affichage(Maintenant.hour() > 9 ? String(Maintenant.hour()) : '0' + String(Maintenant.hour()), false);
  SeparateurHorloge();
  Affichage(Maintenant.minute() > 9 ? String(Maintenant.minute()) : '0' + String(Maintenant.minute()), false);
  SeparateurHorloge();
  Affichage(Maintenant.second() > 9 ? String(Maintenant.second()) : '0' + String(Maintenant.second()), false);
  PointVirgule();
  delay(1000);
  DonneesGPS();
  GenerationDonnees();
}

If you put all your code into one file and compile it, what does the IDE report back as the memory usage?

kI will take a guess: I am not much at code but I have found out using strings kills the arcuino code compactness. Eliminate as much as possible and be sure to define the length of arrays etc. You used the "F" macro which helps a lot. You can define every number that does not change saving RAM which you have done is some cases. I hope this helps:

kJe vais deviner : je ne suis pas très doué en code mais j'ai découvert que l'utilisation de chaînes tue la compacité du code arcuino. Éliminez autant que possible et assurez-vous de définir la longueur des tableaux, etc. Vous avez utilisé la macro "F" qui aide beaucoup. Vous pouvez définir tous les nombres qui ne changent pas en économisant de la RAM, ce que vous avez fait dans certains cas. J'espère que ça aide:

It says 98% FLASH and 82% RAM but the problem is that if i put everything together it seems to do a stack overflow because the GPS or the sensors dont seem to give any more values

You are using the SD library, which I believe wants 512 bytes just for the SD card buffer. That's 25% of your available RAM gone straight away.

With so little overhead left, avoid using the String class as already suggested. I just learnt via @david_2018 in another recent discussion that RTCLib also uses the String class.

You can also put your 2 arrays ParametresDefault & ParametresConfig into flash using PROGMEM to trade RAM for FLASH.

I've no experience of File32, but how does that compare to using File? I assume, maybe wrongly, that File32 is associated with the FAT32 filesystem. Do you save any memory (FLASH or RAM) by switching to File rather than File32?

To answer you, yes File32 is Fat32, and no changing it to File does not make me gain more Flash or RAM, and i just tested right now also to put it on my windows 10 pc, and it just went from 98% flash to 92% and the RAM didn't change, idk why i just pasted the code i had on my home pc and i gained more than 6% FLASH, except for my project i have to present it live and so i have to use my laptop which is windows 11

...do not call that from an interrupt handler. That is a sure fire way to corrupt the state of your application.

With Flash, if the value is less than or equal to 100% you are fine. Over that you are not.

You will very likely gain some Flash and a bit of SRAM by moving the button handling code out of interrupt service routines. In general, handling buttons with interrupts is not appropriate.

i agree, but it is asked within the project x) so i can't change this

And also i gained 6% flash switching from Adafruit SdFat library directly to the author SdFat latest library which was the version 2.2.2 and adafruit was 2.2.

Are you sure the statement just before the if belongs there?

Yes

When using String (capital S), do not concatenate using '+'; use '+=' or concat(). Using '+' results in additional String objects being created temporarily.

When passing String objects to a function, use a reference. That way you don't pass the complete object on the stack but only the reference.

Both will result in more stable behaviour at run time.

Maybe I did misunderstsnd you but there will be no difference in a project with multiple ino files or the same project in one big ino file. The Arduino builder will combine all ino files into one big cpp file that is passed to the compiler.

Okay thanks i will try that

One way to save some memory usage to to never use an int where a byte will handle the value just fine.

How will the if() statement ever be true? You take note of the time and then the very next instruction subtracts that time from the current time? That will result in 0 milliseconds having elapsed between those two statements.

1 Like

Oh yes sorry, it should be in the void setup I don’t know why it’s there, but yes normally it’s in void setup

You might need to consider to buy a arduino with more ram/flash. For 25 euro or so you can easily double both.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.