Problema scrittura su SD card

Buonasera a tutti,
premetto che ho già provato a dare un occhio in giro per internet e non ho trovato alcuna soluzione al problema che sto riscontrando da stamani.

Ho un software che deve eseguire più di una volta accessi sulla scheda SD, da varie parti del programma, per salvare parametri e stringhe su diverse directory.

Il problema è che tutto funziona perfettamente, tutte le directory vengono create, e dentro vengono creati correttamente i file di testo in cui vengono salvati i parametri in formato stringa.

Il problema sorge quando cerco di effettuare la scrittura di una stringa dentro ad un solo file, appena la MCU esegue il comando myFile.write(parametro); crasha tutto e il processore rimane completamente bloccato, non esegue più niente di ciò che è scritto nelle parti di programma successive.
Come se avesse problemi ad avere accesso alla SD e a scrivere il parametro in quel file di testo in quella determinata directory.

Sono con le spalle al muro, ho cambiato SD, ho formattato più volte, ho fatto centinaia e centinaia di prove.

Stamattina ha funzionato perfettamente durante diversi test, poi ho continuato il mio programma e oggi pomeriggio, provando ad effettuare ulteriori test sul mio prototipo, è sorto il problema.

Il resto del codice sono sicuro che sia perfetto, il compilatore non segnala alcun errore, il modo in cui la scrittura del file che provoca il problema è identico al modo in cui effettuo accessi alla SD da altre parti di programma, che però funzionano perfettamente.

Inoltre, nello stesso programma, qualche giorno fa ho avuto un problema stranissimo:
stavo facendo leggere una ventina di parametri dalla scheda SD in formato stringa.
Questi parametri venivano convertiti in un valore di tipo intero tramite la funzione sscanf.
Nessuno di questi file da leggere dava errori, tutti i parametri erano corretti (le variabili contenenti i parametri sono variabili globali), SOLO una di queste variabili globali si resettava da sola... come se la variabile fosse locale.
La cosa strana è che ho fatto stampare la variabile su uno schemo LCD (non ho seriali disponibili sul mio prototipo) e nel momento esatto in cui il parametro veniva letto, convertito, salvato nella propria variabile globale e stampato su display il valore era corretto, una volta uscito dalla funzione in cui facevo tutto questo, la stessa variabile che prima aveva valore, adesso valeva 0...
NON ho assolutamente idea di quale sia stato il problema, vi dico solo che cambiando il nome della variabile globale ho risolto il problema....

Posso chiedere a voi oppure ho bisogno di un esorcista??? :rofl: :rofl:
Ringrazio tutti in anticipo!

[AGGIORNAMENTO]:
Dopo una serie di tentativi, ho potuto osservare che la scrittura su quel file "dannato" viene eseguita con successo solo una volta, le restanti scritture bloccano tutto il sistema.

[NOTA]:
Ho fatto altre ricerche su internet e pare che un ragazzo abbia avuto lo stesso problema utilizzando il comando SD.open() sulla piattaforma Arduino Diecimila.
Tra le risposte ne ho trovata una che credo sia la più plausibile, ovvero la SRAM completamente piena, o comunque abbastanza da non poter dedicare 512 byte allo stream di uscita.
Ora io non penso di aver riempito la SRAM di un ATSAM3X8E (Arduino Due) dato che ha un totale di 96k di SRAM, non 1K come il Diecimila.

Suggerimenti? :thinking:

Foto del circuito realizzato e sorgente (minimo) del programma (mi raccomando tra i tag CODE) ...
... altrimenti difficilmente qualcuno potrà aiutarti.

Guglielmo

P.S.: se ben usata e ben collegata, la SD non da alcun problema ... pensa solo all'infinità di GPSrecorder, fatti con il classico ATmega328P, che ci sono in giro e che aprono/chiudono/scrivono in continuazione ... :wink:

Buonasera, prima di tutto ti ringrazio per la risposta!

L'hardware che sto utilizzando è un prototipo custom basato sulla MCU ATSAM3X8E, l' ho già pubblicato in passato per un problema su Rx e Tx, poi risolto.

Comunque l'hardware è stato collaudato per molto tempo, tutto funziona in maniera perfetta, anche perchè qualora ci fossero problemi sull'hardware, il software non dovrebbe essere mai in grado di poter scrivere o leggere. Inoltre con altri software ha funzionato, quindi escluderei un problema sull'hardware.

Il codice che posto qua sotto non è l'intero software di controllo, ma solo le due parti che interessano la scheda SD.

questa è la parte di codice che funziona:

void SDconfiguration(){
  const uint8_t SDdelay = 250;
  const uint16_t display_delay = 1000;

  delay(SDdelay);

  if(!digitalRead(cardDetectPin) == LOW){
    error = SD_NOT_PRESENT;
    errorHandler();
    delay(SDdelay);
  }else{
    if(!digitalRead(writeProtectPin) == LOW){
      error = SD_PROTECTED;
      errorHandler();
      delay(SDdelay);
    }else if(!SD.begin(CS)){
      error = SD_NOT_BEGINNED;
      errorHandler();
      delay(SDdelay);
    }
  }
  
  delay(SDdelay);
  
  
  if(digitalRead(cardDetectPin) == LOW){
    if(digitalRead(writeProtectPin) == LOW){
      if(SD.begin(CS)){

/* -------------------------------------------------- SD DIRECTORIES CHECK: */

/* -------------------------------------------------- DIRECTORY CONFIG DOESN'T EXISTS: */
        if(!SD.exists("CONFIG")){
          
          SD.mkdir("CONFIG");
          
          myData = SD.open(DISPLAY_DELAY_PATH, FILE_WRITE);
          myData.write(DEFAULT_DISPLAY_DELAY);
          myData.close();
          

          myData = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
          myData.write(DEFAULT_IR_SENSIVITY);
          IR_SENSIVITY = 500;
          myData.close();


          myData = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_WRITE);
          myData.write(DEFAULT_EV_PRE_PUMP_TIME);
          EV_PRE_PUMP_TIME = 3000;
          myData.close();


          myData = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
          myData.write(DEFAULT_EV_POST_PUMP_TIMER);
          EV_POST_PUMP_TIMER = 5000;
          myData.close();


          myData = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_WRITE);
          myData.write(DEFAULT_MAX_MIN_VACUUM_TIMER);
          MAX_MIN_VACUUM_TIMER = 60000;
          myData.close();

          
          myData = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
          myData.write(DEFAULT_RELATIVE_ZERO_TIMER);
          RELATIVE_ZERO_TIMER = 5000;
          myData.close();

          
          myData = SD.open(ALARM_DELAY_PATH, FILE_WRITE);
          myData.write(DEFAULT_ALARM_DELAY);
          ALARM_DELAY = 1000;
          myData.close();

          
          myData = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_WRITE);
          myData.write(DEFAULT_VACUUM_READ_START_DELAY);
          VACUUM_READ_START_DELAY = 3000;
          myData.close();

          
          myData = SD.open(FILTER_COEFFICIENT_PATH, FILE_WRITE);
          myData.write(DEFAULT_FILTER_COEFFICIENT);
          FILTER_COEFFICIENT = 5;
          myData.close();


          myData = SD.open(PUMP_START_MODE_PATH, FILE_WRITE);
          myData.write(DEFAULT_PUMP_START_MODE);
          PUMP_START_MODE = 1;
          myData.close();

          
          myData = SD.open(PUMP_START_TIME_PATH, FILE_WRITE);
          myData.write(DEFAULT_PUMP_START_TIME);
          myData.close();

          
          myData = SD.open(PUMP_STOP_TIME_PATH, FILE_WRITE);
          myData.write(DEFAULT_PUMP_STOP_TIME);
          myData.close();

          myData = SD.open(DEVICE_NAME_PATH, FILE_WRITE);
          myData.print(DEFAULT_DEVICE_NAME);
          myData.close();

          
/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT MODULE_NUMBER.txt FILE DOESN'T: */
        }else{
          LCD_display.clear();
          LCD_display.setCursor(2, 0);
          LCD_display.print("[SD CONFIG]");
          

/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT IR_SENSOR_SENSIVITY.txt FILE DOESN'T: */
          if(SD.exists(IR_SENSIVITY_PATH)){
            myData = SD.open(IR_SENSIVITY_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
                myData.write(DEFAULT_IR_SENSIVITY);

                myData.close();
              }else{
                const uint8_t MaxChar = 5;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                sscanf(CharArray, "%d", &IR_SENSIVITY);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("IRSS: ");
                LCD_display.print(IR_SENSIVITY);
                delay(display_delay);

                if(IR_SENSIVITY < 0 || IR_SENSIVITY > 1023){
                  IR_SENSIVITY = 500;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(IR_SENSIVITY_PATH);
                  myData = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
                  myData.write(DEFAULT_IR_SENSIVITY);
                  myData.close();
                    
                  error = INCONSISTENT_IR_SENSIVITY_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = IR_SENSIVITY_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
            myData.write(DEFAULT_IR_SENSIVITY);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT EV_PRE_PUMP_TIMER.txt FILE DOESN'T: */
          if(SD.exists(EV_PRE_PUMP_TIME_PATH)){
            myData = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_WRITE);
                myData.write(DEFAULT_EV_PRE_PUMP_TIME);

                myData.close();
              }else{
                const uint8_t MaxChar = 5;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &EV_PRE_PUMP_TIME);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("EVPE: ");
                LCD_display.print(EV_PRE_PUMP_TIME);
                delay(display_delay);

                if(EV_PRE_PUMP_TIME < 0 || EV_PRE_PUMP_TIME > 5000){
                  EV_PRE_PUMP_TIME = 3000;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(EV_PRE_PUMP_TIME_PATH);
                  myData = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_WRITE);
                  myData.write(DEFAULT_EV_PRE_PUMP_TIME);
                  myData.close();
                    
                  error = INCONSISTENT_EV_PRE_PUMP_TIME_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = EV_PRE_PUMP_TIME_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_WRITE);
            myData.write(DEFAULT_EV_PRE_PUMP_TIME);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT EV_POST_PUMP_TIMER.txt FILE DOESN'T: */
          if(SD.exists(EV_POST_PUMP_TIMER_PATH)){
            myData = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
                myData.write(DEFAULT_EV_POST_PUMP_TIMER);

                myData.close();
              }else{
                const uint8_t MaxChar = 6;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &EV_POST_PUMP_TIMER);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("EVPT: ");
                LCD_display.print(EV_POST_PUMP_TIMER);
                delay(display_delay);

                if(EV_POST_PUMP_TIMER < 0 || EV_POST_PUMP_TIMER > 10000){
                  EV_POST_PUMP_TIMER = 5000;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(EV_POST_PUMP_TIMER_PATH);
                  myData = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
                  myData.write(DEFAULT_EV_POST_PUMP_TIMER);
                  myData.close();
                    
                  error = INCONSISTENT_EV_POST_PUMP_TIMER_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = EV_POST_PUMP_TIMER_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
            myData.write(DEFAULT_EV_POST_PUMP_TIMER);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT MAX&MIN_VACUUM_TIMER.txt FILE DOESN'T: */
          if(SD.exists(MAX_MIN_VACUUM_TIMER_PATH)){
            myData = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_WRITE);
                myData.write(DEFAULT_MAX_MIN_VACUUM_TIMER);

                myData.close();
              }else{
                const uint8_t MaxChar = 7;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }

                sscanf(CharArray, "%d", &MAX_MIN_VACUUM_TIMER);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("MMVT: ");
                LCD_display.print(MAX_MIN_VACUUM_TIMER);
                delay(display_delay);

                if(MAX_MIN_VACUUM_TIMER < 30000 || MAX_MIN_VACUUM_TIMER > 180000){
                  MAX_MIN_VACUUM_TIMER = 60000;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(MAX_MIN_VACUUM_TIMER_PATH);
                  myData = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_WRITE);
                  myData.write(DEFAULT_MAX_MIN_VACUUM_TIMER);
                  myData.close();
                    
                  error = INCONSISTENT_MAX_MIN_VACUUM_TIMER_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = MAX_MIN_VACUUM_TIMER_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_WRITE);
            myData.write(DEFAULT_MAX_MIN_VACUUM_TIMER);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT RELATIVE_ZERO_TIMER.txt FILE DOESN'T: */
          if(SD.exists(RELATIVE_ZERO_TIMER_PATH)){
            myData = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
                myData.write(DEFAULT_RELATIVE_ZERO_TIMER);

                myData.close();
              }else{
                const uint8_t MaxChar = 6;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }

                sscanf(CharArray, "%d", &RELATIVE_ZERO_TIMER);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("RZTR: ");
                LCD_display.print(RELATIVE_ZERO_TIMER);
                delay(display_delay);

                if(RELATIVE_ZERO_TIMER < 2000 || RELATIVE_ZERO_TIMER > 10000){
                  RELATIVE_ZERO_TIMER = 5000;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(RELATIVE_ZERO_TIMER_PATH);
                  myData = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
                  myData.write(DEFAULT_RELATIVE_ZERO_TIMER);
                  myData.close();
                    
                  error = INCONSISTENT_RELATIVE_ZERO_TIMER_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = RELATIVE_ZERO_TIMER_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
            myData.write(DEFAULT_RELATIVE_ZERO_TIMER);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT ALARM_DELAY.txt FILE DOESN'T: */
          if(SD.exists(ALARM_DELAY_PATH)){
            myData = SD.open(ALARM_DELAY_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(ALARM_DELAY_PATH, FILE_WRITE);
                myData.write(DEFAULT_ALARM_DELAY);

                myData.close();
              }else{
                const uint8_t MaxChar = 5;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while((myData.available())){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &ALARM_DELAY);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("AMRS: ");
                LCD_display.print(ALARM_DELAY);
                delay(display_delay);

                if(ALARM_DELAY < 500 || ALARM_DELAY > 3000){
                  ALARM_DELAY = 1000;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(ALARM_DELAY_PATH);
                  myData = SD.open(ALARM_DELAY_PATH, FILE_WRITE);
                  myData.write(DEFAULT_ALARM_DELAY);
                  myData.close();
                    
                  error = INCONSISTENT_ALARM_DELAY_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = ALARM_DELAY_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(ALARM_DELAY_PATH, FILE_WRITE);
            myData.write(DEFAULT_ALARM_DELAY);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT VACUUM_READ_START_DELAY.txt FILE DOESN'T: */
          if(SD.exists(VACUUM_READ_START_DELAY_PATH)){
            myData = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_WRITE);
                myData.write(DEFAULT_VACUUM_READ_START_DELAY);

                myData.close();
              }else{
                const uint8_t MaxChar = 5;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &VACUUM_READ_START_DELAY);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("VRSD: ");
                LCD_display.print(VACUUM_READ_START_DELAY);
                delay(display_delay);

                if(VACUUM_READ_START_DELAY < 0 || VACUUM_READ_START_DELAY > 5000){
                  VACUUM_READ_START_DELAY = 3000;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(VACUUM_READ_START_DELAY_PATH);
                  myData = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_WRITE);
                  myData.write(DEFAULT_VACUUM_READ_START_DELAY);
                  myData.close();
                    
                  error = INCONSISTENT_VACUUM_READ_START_DELAY_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = VACUUM_READ_START_DELAY_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_WRITE);
            myData.write(DEFAULT_VACUUM_READ_START_DELAY);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT FILTER_COEFFICIENT.txt FILE DOESN'T: */
          if(SD.exists(FILTER_COEFFICIENT_PATH)){
            myData = SD.open(FILTER_COEFFICIENT_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(FILTER_COEFFICIENT_PATH, FILE_WRITE);
                myData.write(DEFAULT_FILTER_COEFFICIENT);

                myData.close();
              }else{
                const uint8_t MaxChar = 3;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &FILTER_COEFFICIENT);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("FRCT: ");
                LCD_display.print(FILTER_COEFFICIENT);
                delay(display_delay);

                if(FILTER_COEFFICIENT < 0 || FILTER_COEFFICIENT > 10){
                  FILTER_COEFFICIENT = 5;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(FILTER_COEFFICIENT_PATH);
                  myData = SD.open(FILTER_COEFFICIENT_PATH, FILE_WRITE);
                  myData.write(DEFAULT_FILTER_COEFFICIENT);
                  myData.close();
                    
                  error = INCONSISTENT_FILTER_COEFFICIENT_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = FILTER_COEFFICIENT_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(FILTER_COEFFICIENT_PATH, FILE_WRITE);
            myData.write(DEFAULT_FILTER_COEFFICIENT);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT PUMP_START_MODE.txt FILE DOESN'T: */
          if(SD.exists(PUMP_START_MODE_PATH)){
            myData = SD.open(PUMP_START_MODE_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(PUMP_START_MODE_PATH, FILE_WRITE);
                myData.write(DEFAULT_PUMP_START_MODE);

                myData.close();
              }else{
                char startMode;
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    startMode = incomingChar;
                  }
                }
                
                PUMP_START_MODE = startMode - '0';
                
                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("PSTM: ");
                LCD_display.print(PUMP_START_MODE);
                delay(display_delay);

                if(PUMP_START_MODE < 1 || PUMP_START_MODE > 2){
                  PUMP_START_MODE = 1;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(PUMP_START_MODE_PATH);
                  myData = SD.open(PUMP_START_MODE_PATH, FILE_WRITE);
                  myData.write(DEFAULT_PUMP_START_MODE);
                  myData.close();
                    
                  error = INCONSISTENT_PUMP_START_MODE_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = PUMP_START_MODE_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(PUMP_START_MODE_PATH, FILE_WRITE);
            myData.write(DEFAULT_PUMP_START_MODE);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT PUMP_START_TIME.txt FILE DOESN'T: */
          if(SD.exists(PUMP_START_TIME_PATH)){
            myData = SD.open(PUMP_START_TIME_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(PUMP_START_TIME_PATH, FILE_WRITE);
                myData.write(DEFAULT_PUMP_START_TIME);

                myData.close();
              }else{
                const uint8_t MaxChar = 3;
                char HoursArray[MaxChar];
                char MinutesArray[MaxChar];
                uint8_t ArrayIndex = 0;
                bool hourIsDone = false;
                bool incorrectTime = false;
                
                while(myData.available()){
                  char incomingChar = myData.read();

                  if(incomingChar == ':'){
                    hourIsDone = true;
                    ArrayIndex = 0;
                  }
                  
                  if(!hourIsDone){
                    if(isDigit(incomingChar)){
                      HoursArray[ArrayIndex] = incomingChar;
                      HoursArray[++ArrayIndex] = 0;
                    }
                  }else{
                    if(isDigit(incomingChar)){
                      MinutesArray[ArrayIndex] = incomingChar;
                      MinutesArray[++ArrayIndex] = 0;
                    }
                  }
                }
                
                sscanf(HoursArray, "%d", &PUMP_START_HOURS);
                sscanf(MinutesArray, "%d", &PUMP_START_MINUTES);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("PSTT: ");
                printTwoDigits(PUMP_START_HOURS);
                LCD_display.print(':');
                printTwoDigits(PUMP_START_MINUTES);
                delay(display_delay);

                if(PUMP_START_HOURS < 0 || PUMP_START_HOURS > 23){
                  PUMP_START_HOURS = 07;
                  incorrectTime = true;
                }
                if(PUMP_START_MINUTES < 0 || PUMP_START_MINUTES > 59){
                  PUMP_START_MINUTES = 00;
                  incorrectTime = true;
                }

                if(incorrectTime){
                  myData.close();
                  SD.remove(PUMP_START_TIME_PATH);
                  myData = SD.open(PUMP_START_TIME_PATH, FILE_WRITE);
                  myData.write(DEFAULT_PUMP_START_TIME);
                  myData.close();
                    
                  error = INCONSISTENT_PUMP_START_TIME_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = PUMP_START_TIME_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(PUMP_START_TIME_PATH, FILE_WRITE);
            myData.write(DEFAULT_PUMP_START_TIME);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT PUMP_STOP_TIME.txt FILE DOESN'T: */
          if(SD.exists(PUMP_STOP_TIME_PATH)){
            myData = SD.open(PUMP_STOP_TIME_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(PUMP_STOP_TIME_PATH, FILE_WRITE);
                myData.write(DEFAULT_PUMP_STOP_TIME);

                myData.close();
              }else{
                const uint8_t MaxChar = 3;
                char HoursArray[MaxChar];
                char MinutesArray[MaxChar];
                bool hourIsDone = false;
                bool incorrectTime = false;
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();

                  if(incomingChar == ':'){
                    hourIsDone = true;
                    ArrayIndex = 0;
                  }
                  
                  if(!hourIsDone){
                    if(isDigit(incomingChar)){
                      HoursArray[ArrayIndex] = incomingChar;
                      HoursArray[++ArrayIndex] = 0;
                    }
                  }else{
                    if(isDigit(incomingChar)){
                      MinutesArray[ArrayIndex] = incomingChar;
                      MinutesArray[++ArrayIndex] = 0;
                    }
                  }
                }
                
                sscanf(HoursArray, "%d", &PUMP_STOP_HOURS);
                sscanf(MinutesArray, "%d", &PUMP_STOP_MINUTES);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("PSPT: ");
                printTwoDigits(PUMP_STOP_HOURS);
                LCD_display.print(':');
                printTwoDigits(PUMP_STOP_MINUTES);
                delay(display_delay);

                if(PUMP_STOP_HOURS < 0 || PUMP_STOP_HOURS > 23){
                  PUMP_STOP_HOURS = 19;
                  incorrectTime = true;
                }
                if(PUMP_STOP_MINUTES < 0 || PUMP_STOP_MINUTES > 59){
                  PUMP_STOP_MINUTES = 00;
                  incorrectTime = true;
                }
                
                if(incorrectTime){
                  myData.close();
                  SD.remove(PUMP_STOP_TIME_PATH);
                  myData = SD.open(PUMP_STOP_TIME_PATH, FILE_WRITE);
                  myData.write(DEFAULT_PUMP_STOP_TIME);
                  myData.close();
                    
                  error = INCONSISTENT_PUMP_STOP_TIME_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = PUMP_STOP_TIME_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(PUMP_STOP_TIME_PATH, FILE_WRITE);
            myData.write(DEFAULT_PUMP_STOP_TIME);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT VACUUM_CURVATURE_VALUES.txt FILE DOESN'T: */
          if(SD.exists(VACUUM_CURVATURE_VALUES_PATH)){
            myData = SD.open(VACUUM_CURVATURE_VALUES_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(VACUUM_CURVATURE_VALUES_PATH, FILE_WRITE);
                myData.write(DEFAULT_VACUUM_CURVATURE_VALUES);

                myData.close();
              }else{

                const uint8_t curvatureValuesLength = 17;
                char curvatureValues[curvatureValuesLength];
                uint8_t curvatureValuesIndex = 0;

                while(myData.available()){
                  char incomingChar = myData.read();
                  if(isDigit(incomingChar) && (curvatureValuesIndex < curvatureValuesLength)){
                    curvatureValues[curvatureValuesIndex] = incomingChar;
                    curvatureValuesIndex++;
                  }
                }

                char curvatureSingleValue[3];
                for(uint8_t i = 0; i < curvatureValuesLength; i++){
                  curvatureSingleValue[0] = curvatureValues[i];
                  curvatureSingleValue[1] = curvatureValues[i + 1];

                  switch(i){
                    case 0:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE1);
                      break;
                      
                    case 2:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE2);
                      break;
  
                    case 4:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE3);
                      break;
  
                    case 6:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE4);
                      break;
  
                    case 8:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE5);
                      break;
  
                    case 10:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE6);
                      break;
  
                    case 12:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE7);
                      break;
  
                    case 14:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE8);
                      break;
                  }
                }
                
                LCD_display.setCursor(0, 1);
                LCD_display.print("               ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("C1: ");
                printTwoDigits(CURVATURE_VALUE1);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C2: ");
                printTwoDigits(CURVATURE_VALUE2);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C3: ");
                printTwoDigits(CURVATURE_VALUE3);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C4: ");
                printTwoDigits(CURVATURE_VALUE4);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C5: ");
                printTwoDigits(CURVATURE_VALUE5);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C6: ");
                printTwoDigits(CURVATURE_VALUE6);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C7: ");
                printTwoDigits(CURVATURE_VALUE7);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C8: ");
                printTwoDigits(CURVATURE_VALUE8);
                delay(display_delay);
              }
            }else{
              error = VACUUM_CURVATURE_VALUES_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(VACUUM_CURVATURE_VALUES_PATH, FILE_WRITE);
            myData.write(DEFAULT_VACUUM_CURVATURE_VALUES);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT DEVIC_ENAME.txt FILE DOESN'T: */
          if(SD.exists(DEVICE_NAME_PATH)){
            myData = SD.open(DEVICE_NAME_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(DEVICE_NAME_PATH, FILE_WRITE);
                myData.write(DEFAULT_DEVICE_NAME);

                myData.close();
              }else{
                for(uint8_t i = 0; i < DEVICE_NAME_MAX; i++){
                  DEVICE_NAME[i] = '\0';
                }
                
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                  DEVICE_NAME[ArrayIndex] = incomingChar;
                  DEVICE_NAME[++ArrayIndex] = 0;
                }

                LCD_display.setCursor(0, 1);
                LCD_display.print("BT:             ");
                LCD_display.setCursor(3, 1);
                LCD_display.print(DEVICE_NAME);
                delay(display_delay);
              }
            }else{
              error = DEVICE_NAME_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(DEVICE_NAME_PATH, FILE_WRITE);
            myData.write(DEFAULT_DEVICE_NAME);
            myData.close();
          }


        }


/* -------------------------------------------------- DIRECTORY "EVENTS" DOESN'T EXISTS: */
        if(!SD.exists("EVENTS")){
          SD.mkdir("EVENTS");


/* -------------------------------------------------- DIRECTORY "EVENTS" EXISTS BUT EVENTS.txt FILE DOESN'T: */
        }else{
          if(!SD.exists(EVENTS_PATH)){
            myData = SD.open(EVENTS_PATH, FILE_WRITE);
            myData.close();
          }
        }

        if(SD.exists("PAR")){
          myData = SD.open(PARAMETERS_MIN_VACUUM_1_PATH);
          if(myData){
            if(!myData.available()){
              error = VACUUM_1_MIN_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myData.available()){
                char incomingChar = myData.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &minVacuum1);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("mV1: ");
              LCD_display.print(minVacuum1);
              delay(display_delay);
            }
          }else{
            error = PARAMETERS_MIN_VACUUM_1_PATH_FAILURE;
            errorHandler();
          }
          myData.close();


          myData = SD.open(PARAMETERS_MIN_VACUUM_2_PATH);
          if(myData){
            if(!myData.available()){
              error = VACUUM_2_MIN_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myData.available()){
                char incomingChar = myData.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &minVacuum2);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("mV2: ");
              LCD_display.print(minVacuum2);
              delay(display_delay);
            }
          }else{
            error = PARAMETERS_MIN_VACUUM_2_PATH_FAILURE;
            errorHandler();
          }
          myData.close();


          myData = SD.open(PARAMETERS_MAX_VACUUM_1_PATH);
          if(myData){
            if(!myData.available()){
              error = VACUUM_1_MAX_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myData.available()){
                char incomingChar = myData.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &maxVacuum1);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("MV1: ");
              LCD_display.print(maxVacuum1);
              delay(display_delay);
            }
          }else{
            error = PARAMETERS_MAX_VACUUM_1_PATH_FAILURE;
            errorHandler();
          }
          myData.close();


          myData = SD.open(PARAMETERS_MAX_VACUUM_2_PATH);
          if(myData){
            if(!myData.available()){
              error = VACUUM_2_MAX_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myData.available()){
                char incomingChar = myData.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &maxVacuum2);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("MV2: ");
              LCD_display.print(maxVacuum2);
              delay(display_delay);
            }
          }else{
            error = PARAMETERS_MAX_VACUUM_2_PATH_FAILURE;
            errorHandler();
          }
          myData.close();


          myData = SD.open(PARAMETERS_RELATIVE_ZERO_1_PATH);
          if(myData){
            if(!myData.available()){
              error = RELATIVE_ZERO_1_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myData.available()){
                char incomingChar = myData.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &relativeZero1);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("RZ1: ");
              LCD_display.print(relativeZero1);
              delay(display_delay);
            }
          }else{
            error = PARAMETERS_RELATIVE_ZERO_1_PATH_FAILURE;
            errorHandler();
          }
          myData.close();


          myData = SD.open(PARAMETERS_RELATIVE_ZERO_2_PATH);
          if(myData){
            if(!myData.available()){
              error = RELATIVE_ZERO_2_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myData.available()){
                char incomingChar = myData.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &relativeZero2);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("RZ2: ");
              LCD_display.print(relativeZero2);
              delay(display_delay);
            }
          }else{
            error = PARAMETERS_RELATIVE_ZERO_2_PATH_FAILURE;
            errorHandler();
          }
          myData.close();
        }
        error = NO_ERRORS;
      }else{
        error = SD_NOT_BEGINNED;
        errorHandler();
        return;
      }
    }else{
      error = SD_PROTECTED;
      errorHandler();
      return;
    }
  }else{
    error = SD_NOT_PRESENT;
    errorHandler();
    return;
  }

  LCD_display.clear();
  LCD_display.setCursor(2, 0);
  LCD_display.print("[SYSTEM  OK]");

}

All'inizio ho effettuato un doppio controllo sullo stato della SD poichè ho notato che con uno singolo il software non funziona esattamente come deve, rimanendo bloccato su un singolo controllo.
Invece con il doppio controllo, il programma mi segnala su un display LCD 16x2 in tempo reale qual'è il problema:

  • se la SD non è presente mi segnala la scritta "SD not present";
  • se la SD è protetta mi segnala la scritta "SD protected";
  • se la SD non è stata correttamente inizializzata mi segnala la scritta "SD not beginned".

La gestione degli errori l'ho riportata tutta in un'apposita funzione chiamata errorHandler, che funge da vero e proprio gestore degli errori per tutto il programma.

Questa, invece, è la parte di codice che blocca l'intera esecuzione:

void saveOnSD(char msgToSave[40]){
  myData = SD.open(EVENTS_PATH, FILE_WRITE);
  
  for(uint8_t dateOnSD = 0; dateOnSD < 6; dateOnSD++){
    char numToChar[3];
    
    for(uint8_t i = 0; i < 3; i++){
      numToChar[i] = 0;
    }
    
    switch(dateOnSD){
      case 0:
        sprintf(numToChar, "%d", RealTimeClock.getDay());
        if(RealTimeClock.getDay() < 10){
          myData.write('0');
          myData.write(numToChar);
        }else
          myData.write(numToChar);
        break;

      case 1:
        sprintf(numToChar, "%d", RealTimeClock.getMonth());
        if(RealTimeClock.getMonth() < 10){
          myData.write('0');
          myData.write(numToChar);
        }else
          myData.write(numToChar);
        break;

      case 2:
        sprintf(numToChar, "%d", RealTimeClock.getYear() - 2000);
        if(RealTimeClock.getYear() < 10){
          myData.write('0');
          myData.write(numToChar);
        }else
          myData.write(numToChar);
        break;

      case 3:
        sprintf(numToChar, "%d", RealTimeClock.getHours());
        if(RealTimeClock.getHours() < 10){
          myData.write('0');
          myData.write(numToChar);
        }else
          myData.write(numToChar);
        break;

      case 4:
        sprintf(numToChar, "%d", RealTimeClock.getMinutes());
        if(RealTimeClock.getMinutes() < 10){
          myData.write('0');
          myData.write(numToChar);
        }else
          myData.write(numToChar);
        break;

      case 5:
        sprintf(numToChar, "%d", RealTimeClock.getSeconds());
        if(RealTimeClock.getSeconds() < 10){
          myData.write('0');
          myData.write(numToChar);
        }else
          myData.write(numToChar);
        break;
    }

    if(dateOnSD < 2){
      myData.write('/');
    }else if(dateOnSD == 2){
      myData.write("   -   ");
    }else if (dateOnSD > 2 && dateOnSD < 5){
      myData.write(':');
    }
  }

  if(error != NO_ERRORS){
    char errorNumber[3];
    for(uint8_t i = 0; i < 3; i++){
      errorNumber[i] = 0;
    }
    sprintf(errorNumber, "%d", error);
    myData.write("  ->  ");
    myData.write(msgToSave);
    myData.write("    Err: ");
    myData.write(errorNumber);
  }else{
    myData.write("  ->  ");
    myData.write(msgToSave);
  }
  myData.write("\r\n");
  myData.close();
  
}

Sicuramente potevo usare approcci migliori sia per i controlli per la presenza della SD, sia per la lettura, sia per la scrittura dei dati.

Per ora mi basta che funzioni anche con questo approccio, tanto ci torno in un secondo momento per ottimizzare il codice e finalizzarlo.

Il problema è che nella prima funzione che ho allegato la SD si comporta in maniera corretta, funziona tutto, scrive e legge ogni dato.

Nella seconda funzione si blocca completamente la MCU.
Ieri notte, dopo centinaia di tentativi, ho potuto osservare che il blocco avveniva durante l'esecuzione del comando myFile.write(...).
All'inizio pensavo fosse il comando myFile = SD.open(...), che si è poi rivelato non colpevole del blocco.

Per ora è tutto quanto, ora mi rimetto all' opera.
Grazie per ora.

Tu indenti in maniera differente da me

Quindi mi trovo un po' in difficoltà a seguirti sul furbofono (C)(R)
Anche perché hai un'alta complessità ciclomatica (troppi if incatastati uno sull'altro)

Però secondo me ti manca un myfile.close()
Perché tu lo fai nel caso il valore letto sia fuori dai limiti

Ma nel caso else?

Comunque ci sono troppe variabili maiuscole e troppo codice ripetuto/simile

Buonasera, ti ringrazio per la risposta.

Ammetto che alcuni if sono stati scritti in maniera un po' confusionaria, vedo subito di rimediare.
Alcuni if purtroppo sono indispensabili così come sono, il programma è assai più esteso rispetto alle due funzioni che ho scritto nel post sopra, ci sono tante variabili e tanti fattori in gioco che mi trovo costretto ad affrontare tramite switch vari e if nidificati.

Per quanto riguarda il nome delle variabili, mi è successa una cosa stranissima, nel post sopra allegato, nella prima funzione (SDconfiguration per intenderci), ad un certo punto compaiono delle operazioni con la variabile EV_PRE_PUMP_TIME.
Originariamente la variabile si chiamava EV_PRE_PUMP_TIMER, però non funzionava, la variabile che è globale, andava persa nella terminazione della funzione SDconfiguration.
In sostanza assegnavo un valore pari a 3000 che facevo visualizzare su display mentre la stessa variabile, che prima aveva valore 3000, nel loop aveva valore 0.
Ho risolto solamente cambiandone il nome, dopo tale modifica (assurda direi) la variabile veniva memorizzata correttamente restituendo il valore assegnato da tutte le funzioni...
Di tutte le variabili recepite con lo stesso metodo dalla SD, solo quella "perdeva" valore, le altre invece mantenevano il valore in modo perfetto.

Nel caso else, cioè se: if(myFile) non va a buon fine, imposto l'enumerazione all'errore opportuno e chiamo la funzione errorHandler che esegue, per ora, un while(true) per cui non è un problema a chiudere lo stream.

Inoltre ieri sera ho effettuato un test inserendo la chiusura di un eventuale stream rimasto aperto con la scheda SD prima di riaprirne uno nuovo ma niente da fare, si freeza proprio tutto il sistema.

PS: "Furbofono" mi è piaciuta :rofl: :rofl:, termine perfettamente azzeccato.

Nel caso else di "questo" if

Io non ho visto chiusure

Tanto tanto tempo fa
In una galassia lontana lontana...
Avevo scritto "la mia seconda volta in C++"

Che potrebbe aiutare a ridurre tutta la complessità ciclomatica che ha il tuo programma
Magari anche solo come ispirazione...

Riposto qua il codice inerente alla variabile IR_SENSIVITY:

if(SD.exists(IR_SENSIVITY_PATH)){
            myData = SD.open(IR_SENSIVITY_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){ 
                myData.close();
              
                myData = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
                myData.write(DEFAULT_IR_SENSIVITY);

                myData.close();
              }else{
                const uint8_t MaxChar = 5;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                sscanf(CharArray, "%d", &IR_SENSIVITY);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("IRSS: ");
                LCD_display.print(IR_SENSIVITY);
                delay(display_delay);

                if(IR_SENSIVITY < 0 || IR_SENSIVITY > 1023){
                  IR_SENSIVITY = 500;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(IR_SENSIVITY_PATH);
                  myData = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
                  myData.write(DEFAULT_IR_SENSIVITY);
                  myData.close();
                    
                  error = INCONSISTENT_IR_SENSIVITY_VALUE;
                  errorHandler();
                }
              }
            }else{ // se il file esiste ma l'apertura di questo ha fallito, chiamo il gestore degli errori.
                   // il gestore degli errori al suo interno ha uno switch con i case inerenti al valore
                   // dell'enumerato error e, per ora, esegue la funzione while(true) quindi si blocca li.
              error = IR_SENSIVITY_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
            myData.write(DEFAULT_IR_SENSIVITY);
            myData.close();
          }

Come descritto dal commento, se l'apertura del file non va a buon fine, chiamo la funzione errorHandler() e il codice viene bloccato all' istruzione while(true) contenuta nella funzione.
L'unico modo che ho per uscire da quel loop infinito è disalimentare il circuito, però a questo punto lo stream con la scheda SD dovrebbe terminarsi giusto??

Comunque la cosa strana è nel primo pomeriggio di ieri ero riuscito a farlo funzionare correttamente e non ho apportato modifiche così sostanziali al codice, anzi non ricordo nemmeno di aver modificato alcuna riga di codice nella funzione saveOnSD().

Ho addirittura provato a sostituire scheda logica (ne ho 5 identiche), pensando che la precedente fosse in qualche modo difettosa, ma non ho ottenuto cambiamenti.

Riguardo invece al mistero del cambio nome alla variabile EV_PRE_PUMP_TIMER viene in mente qualcosa?? :thinking:

Avevo letto qualcosa di simile qua: SD write problems
ma non penso sia il mio caso perchè non uso la classe String, che so causare mooolti problemi con la memoria heap, inoltre sto utilizzando una piattaforma analoga a quella di Arduino Due, che ha 96K di memoria SRAM, quindi boh.

[AGGIORNAMENTO]:
Ho provato, in disperazione, a creare un programmino semplicissimo che scrive sulla SD, con gli stessi nomi identici a quello a cui sto lavorando...funziona, davvero non capisco come mai non funzioni nel programma a cui sto lavorando.

[AGGIORNAMENTO 2]:
Ho provato ad effettuare una scrittura anche senza chiamare la funzione saveOnSD, direttamente scrivendo il codice alla fine del setup. Si blocca tutto comunque...

Una volta scritta la SD non ne vuole più sapere, guai a provare a riscriverla perchè blocca completamente il sistema.

La mia domanda ora è: in quale condizione è possibile che una scrittura su SD blocchi completamente la MCU?

Ho provato anche a creare una directory, quella la crea senza problemi, si blocca solo in scrittura.

Ma lo hai ripostato uguale?

E io uguale scrivo

E fin qui ok
Se il valore NON è nei limiti chiudi il file

E se invece È nei limiti?
Dove lo chiudi?

Torno comunque a dire che quel codice è troppo contorto per poter essere ben mantenuto

Questo puoi semplificarlo. La %d accetta il fill di 0, con %02d avrai sempre 2 cifre filato da 0 quando serve. 3 quindi hai 03, 10 rimane 10

Buongiorno,
hai ragione, mi ero dimenticato di chiudere lo stream in caso in cui ogni valore sia nei limiti, ho fatto una prova inserendo la chiusura dello stream per ogni volta che eseguo l'operazione come per la variabile IR_SENSIVITY ma niente, ho inserito la chiusura dello stream anche dentro all'if citato sopra (e negli altri identici) ma il problema rimane lo stesso, si freeza tutto appena legge myFile.write(...).

Poi la cosa strana è che lo fa solo una volta, in sostanza il mio prototipo esegue un software che deve acquisire dei parametri, una volta acquisiti questi parametri nella prima accensione, il circuito deve essere riavviato. Da questo punto in poi non deve mai più essere scollegato perchè ad ogni avvio confronta i parametri che legge con quelli del primo avvio (il primo avvio serve per salvare una condizione di default).

Per capire se è il primo avvio o no, ho fatto un controllo sulla SD, se trova una directory particolare che contiene i parametri di primo avvio allora parte l'avvio "normale", altrimenti esegue il primo avvio.
Funziona come una specie di press control per intenderci, però include delle funzioni di salva motore e dei controlli continui ad ogni avvio sui parametri acquisiti rispetto ai parametri di primo avvio.

Al primo avvio funziona tutto perfettamente, come lo riavvio scollegandolo e ricollegandolo alla corrente (con i parametri di default già presi) non accetta più la scrittura su SD.

Ciao nid! Grazie per il consiglio.
Ho modificato subito il codice come hai detto tu e il risultato è quello che volevo, ma con meno righe di codice.
Grazie mille ancora!!

Beh

Se non va ancora metti qui il programma completo che ci vediamo dentro

La SD è saldata sulla board o è un modulo volante collegato con cavetti? ... perché ti ricordo anche il problema del bus SPI ... è un bus a, relativamente, alta velocità (parliamo di MHz) e NON ama cavetti particolarmente lunghi ... :roll_eyes:

Guglielmo

Buongiorno,

la SD è saldata sulla board, ho usato un lettore della 3M.
Qua sotto ti allego le foto della mia board.

MCU img1

MCU img2

MCU img3

Per quanto riguarda le schematiche, rimando al link di un mio post di mesi fa, in cui si vedono bene.

Comunque tengo a ribadire che la cosa strana è che con altri software funziona, e soprattutto che nel software in questione funziona solo una volta. Addirittura qualche giorno fa sono riuscito a farlo funzionare correttamente in tutte le sue parti, poi non so cosa ho modificato per farlo smettere di funzionare, ho provato a cercare e cercare a nottate intere, ho provato anche a sostituire la MCU (ne ho 5) e ho cambiato scheda SD (ho provato con una 8GB e una 2GB formattate più volte in FAT16 e FAT32), ho provato a riscrivere quelle parti di codice che sembravano essere colpevoli del "malfunzionamento" ma niente da fare.

Ho scritto questo codice:

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include <SPI.h>
#include <SD.h>

#define LCD_COLS 16
#define LCD_ROWS 2
hd44780_I2Cexp LCD_display;

const uint8_t CS = 8;
const uint8_t cardDetectPin = 26;
const uint8_t writeProtectPin = 27;

File myFile;
const char EVENTS_PATH[] = "/EVENTS/EVENTS.txt";

void setup() {
  pinMode(cardDetectPin, INPUT);
  pinMode(writeProtectPin, INPUT);

  int status = LCD_display.begin(LCD_COLS, LCD_ROWS);
  if(status)
    hd44780::fatalError(status);
  const uint16_t startDisplayDelay = 500;
  delay(startDisplayDelay);

  const uint8_t SDdelay = 250;
  bool SDOK = false;

  while(!SDOK){
    if(digitalRead(cardDetectPin) == LOW){
      if(digitalRead(writeProtectPin) == LOW){
        if(SD.begin(CS)){
          SDOK = true;
        }else{
          LCD_display.setCursor(0, 0);
          LCD_display.print("SD NOT BEGINNED");
          while(!SD.begin(CS));
          LCD_display.setCursor(0, 0);
          LCD_display.print("               ");
          delay(SDdelay);
        }
      }else{
        LCD_display.setCursor(0, 0);
        LCD_display.print("SD PROTECTED");
        while(digitalRead(writeProtectPin) == HIGH);
        LCD_display.setCursor(0, 0);
        LCD_display.print("            ");
        delay(SDdelay);
      }
    }else{
      LCD_display.setCursor(0, 0);
      LCD_display.print("SD NOT PRESENT");
      while(digitalRead(cardDetectPin) == HIGH);
      LCD_display.setCursor(0, 0);
      LCD_display.print("              ");
      delay(SDdelay);
    }
  }

  myFile = SD.open(EVENTS_PATH, FILE_WRITE);
  myFile.write("prova scrittura su SD\r\n");
  myFile.close();

  LCD_display.clear();
  LCD_display.setCursor(0, 0);
  LCD_display.print("OP. RIUSCITA!");
}

void loop() {

}

Questo funziona perfettamente, quindi per certo il problema non è hardware.

Spero in qualche miracolosa soluzione.
Grazie per ora!

Buongiorno,
Metto qui sotto l'intero codice, per ora ci sono delle variabili che non sono utilizzate perchè ancora non è completo, devo affinare e ottimizzare il tutto appena funziona correttamente anche scritto in modo "grezzo".


/*  DISPLAY PARAMETERS:
 *  LCD_COLS: NUMBER OF COLUMNS OF DISPLAY
 *  LCD_ROWS: NUMBER OF ROWS OF DISPLAY+
 *  DISPLAY_DELAY: DELAY TO WAIT TO INITIALIZE DISPLAY CORRECTLY
*/

#define DISPLAY_ADDRESS 0x27
#define LCD_COLS 16
#define LCD_ROWS 2
#define LCD_REFRESH_DELAY 50    // delay without which the display does not print the characters correctly.
#define DISPLAY_DELAY 500


/* -------------------------------------------------- SERIAL COMMUNICATIONS PARAMETERS:
 *  SERIAL_BAUDRATE: SERIAL & BLUETOOTH BAUDRATE.
 *  SERIAL_PROG_MODE_BAUDRATE: SERIAL & BLUETOOTH BAUDRATE IN PROGRAMMING MODE.
 *  SERIAL_DELAY: DELAY TO WAIT TO INITIALIZE COMMUNICATIONS CORRECTLY
*/
#define SERIAL_BAUDRATE 9600
#define SERIAL_AT_MODE_BAUDRATE 38400
#define SERIAL_DELAY 500


/* SERIAL PORTS DEFINITIONS
 * SERIAL_PORT_1 -> Serial1
 * SERIAL_PORT_2 -> serial2
 */
 
#define SERIAL_PORT_1      // SELECTED Serial1
//#define SERIAL_PORT_2    // NOT SELECTED Serial2

#ifdef SERIAL_PORT_1
  #define SERIAL_PORT Serial1
#endif

#ifdef SERIAL_PORT_2
  #define SERIAL_PORT Serial2
#endif


/* -------------------------------------------------- SOFTWARE DEPENDENCIES: */
#include <Arduino.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include <SPI.h>
#include <SD.h>
#include <RTCDue.h>
#include <Timer.h>

/* -------------------------------------------------- BLUETOOTH PIN DECLARATION: */
const uint8_t BT_EN = 36;
const uint8_t BT_power = 47;
const uint8_t BT_state = A3;


/* -------------------------------------------------- SD PIN DECLARATION: */
const uint8_t CS = 8;
const uint8_t cardDetectPin = 26;
const uint8_t writeProtectPin = 27;


/* -------------------------------------------------- OUTPUT PINS DECLARATION: */
const uint8_t RL1 = 49;
const uint8_t RL2 = 50;
const uint8_t buzzer = 48;
const uint8_t redLamp = 42;
const uint8_t orangeLamp = 43;
const uint8_t EV = 51;
const uint8_t safetyRL = 13;

/* -------------------------------------------------- ANALOGIC PINS DECLARATION: */
/* -------------------------------------------------- POWER CHECK VARIABLES: */
const uint8_t shutdownPin = A0;
uint16_t powerCheck;
uint8_t shutdownThreshold = 40;


/* -------------------------------------------------- VACUUM SENSORS PINS DECLARATIONS: */
const uint8_t vacuum1pin = A1;
const uint8_t vacuum2pin = A2;


/* -------------------------------------------------- IR SENSOR PIN DECLARATION: */
const uint8_t IRsensor = 22;


/* -------------------------------------------------- VACUUM SENSORS VARIABLES DECLARATIONS: */
uint16_t vacuum1, oldVacuum1;
uint16_t vacuum2, oldVacuum2;

uint16_t maxVacuum1;
uint16_t maxVacuum2;

uint16_t minVacuum1;
uint16_t minVacuum2;

uint16_t relativeZero1 = 0, oldRelativeZero1;
uint16_t relativeZero2 = 0, oldRelativeZero2;

/* -------------------------------------------------- RTC TIME COMPARISON VARIABLES: */
uint16_t oldYear = 0;
uint8_t oldMonth = 0, oldDay = 0, oldHours = 25, oldMinutes = 60, oldSeconds = 60;

/* -------------------------------------------------- HD44780_I2Cexp OBJECT DECLARATION: */
hd44780_I2Cexp LCD_display;


/* -------------------------------------------------- LCD CUSTOM CHARACTERS: */
byte bluetoothSignal[] = {
  B00100,
  B10110,
  B01101,
  B00110,
  B00110,
  B01101,
  B10110,
  B00100
};

byte bluetoothBar[] = {
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
};


/* -------------------------------------------------- LCD DISPLAY STATE VARIABLES: */
const uint16_t LCDdisplayTime = 10000;
bool LCDdisplayState = false;
bool displayPressureFlag = false;

/* -------------------------------------------------- INTERNAL RTC OBJECT DECLARATION: */
RTCDue RealTimeClock(RC);


/* -------------------------------------------------- SD OBJECT DECLARATION: */
File myFile;
const char DISPLAY_DELAY_PATH[] = "/CONFIG/DYDE.txt";
const char IR_SENSIVITY_PATH[] = "/CONFIG/IRSS.txt";
const char EV_PRE_PUMP_TIME_PATH[] = "/CONFIG/EVPE.txt";
const char EV_POST_PUMP_TIMER_PATH[] = "/CONFIG/EVPT.txt";
const char MAX_MIN_VACUUM_TIMER_PATH[] = "/CONFIG/MMVT.txt";
const char RELATIVE_ZERO_TIMER_PATH[] = "/CONFIG/RZTR.txt";
const char ALARM_DELAY_PATH[] = "/CONFIG/AMRS.txt";
const char VACUUM_READ_START_DELAY_PATH[] = "/CONFIG/VRSD.txt";
const char FILTER_COEFFICIENT_PATH[] = "/CONFIG/FRCT.txt";
const char PUMP_START_MODE_PATH[] = "/CONFIG/PSTM.txt";
const char PUMP_START_TIME_PATH[] = "/CONFIG/PSTT.txt";
const char PUMP_STOP_TIME_PATH[] = "/CONFIG/PSPT.txt";
const char VACUUM_CURVATURE_VALUES_PATH[] = "/CONFIG/VCVS.txt";
const char DEVICE_NAME_PATH[] = "/CONFIG/DENE.txt";


const char EVENTS_PATH[] = "/EVENTS/EVENTS.txt";


const char PARAMETERS_MIN_VACUUM_1_PATH[] = "/PAR/MNV1.txt";
const char PARAMETERS_MIN_VACUUM_2_PATH[] = "/PAR/MNV2.txt";
const char PARAMETERS_MAX_VACUUM_1_PATH[] = "/PAR/MXV1.txt";
const char PARAMETERS_MAX_VACUUM_2_PATH[] = "/PAR/MXV2.txt";
const char PARAMETERS_RELATIVE_ZERO_1_PATH[] = "/PAR/RZV1.txt";
const char PARAMETERS_RELATIVE_ZERO_2_PATH[] = "/PAR/RZV2.txt";


const char DEFAULT_DISPLAY_DELAY[] = "500";
const char DEFAULT_IR_SENSIVITY[] = "500";
const char DEFAULT_EV_PRE_PUMP_TIME[] = "3000";           // time to wait between the valve opening and pump start.
const char DEFAULT_EV_POST_PUMP_TIMER[] = "5000";         // time to wait between the pump start and valv closing.
const char DEFAULT_MAX_MIN_VACUUM_TIMER[] = "60000";      // time to wait to calculate maximal and minimal vacuum of pump
const char DEFAULT_RELATIVE_ZERO_TIMER[] = "5000";        // time to wait to calculate the relative zero vacuum value.
const char DEFAULT_ALARM_DELAY[] = "1000";   // time to wait before system enter alarm mode.
const char DEFAULT_VACUUM_READ_START_DELAY[] = "3000";    // time to wait to start reading vacuum value
const char DEFAULT_FILTER_COEFFICIENT = '5';              // coefficient that indicates the level of vacuum under minimum
const char DEFAULT_PUMP_START_MODE = '1';                 // 1 = manual, 2 = timer
const char DEFAULT_PUMP_START_TIME[] = "07:00";
const char DEFAULT_PUMP_STOP_TIME[] = "19:00";
const char DEFAULT_VACUUM_CURVATURE_VALUES[] = "30;24;18;14;10;06;04;02";
const char DEFAULT_DEVICE_NAME[] = "Modulo_000";


unsigned int IR_SENSIVITY;
unsigned int EV_PRE_PUMP_TIME;
unsigned int EV_POST_PUMP_TIMER;
unsigned int MAX_MIN_VACUUM_TIMER;
unsigned int RELATIVE_ZERO_TIMER;
unsigned int ALARM_DELAY;
unsigned int VACUUM_READ_START_DELAY;
unsigned int FILTER_COEFFICIENT;
unsigned int PUMP_START_MODE;

unsigned int PUMP_START_HOURS;
unsigned int PUMP_START_MINUTES;

unsigned int PUMP_STOP_HOURS;
unsigned int PUMP_STOP_MINUTES;

uint8_t CURVATURE_VALUE_VACUUM1;
uint8_t CURVATURE_VALUE_VACUUM2;

uint8_t CURVATURE_VALUE1;
uint8_t CURVATURE_VALUE2;
uint8_t CURVATURE_VALUE3;
uint8_t CURVATURE_VALUE4;
uint8_t CURVATURE_VALUE5;
uint8_t CURVATURE_VALUE6;
uint8_t CURVATURE_VALUE7;
uint8_t CURVATURE_VALUE8;

const uint8_t DEVICE_NAME_MAX = 13;
char DEVICE_NAME[DEVICE_NAME_MAX];


/* -------------------------------------------------- TIMER OBJECT & DECLARATIONS: */
timer LCDdisplayTimer = timer();


/* -------------------------------------------------- ERROR TYPES DECLARATIONS: */
enum errorType {
/* -------------------------------------------------- SD ERRORS: */
  NO_ERRORS,

/* ----------------------------------- HARDWARE ERRORS: */
  SD_NOT_PRESENT,                                    // 1
  SD_PROTECTED,                                      // 2
  SD_NOT_BEGINNED,                                   // 3

/* ----------------------------------- INCONSISTENT PATHS ERRORS: */
  DISPLAY_DELAY_PATH_FAILURE,                        // 4
  IR_SENSIVITY_PATH_FAILURE,                         // 5
  EV_PRE_PUMP_TIME_PATH_FAILURE,                     // 6
  EV_POST_PUMP_TIMER_PATH_FAILURE,                   // 7
  MAX_MIN_VACUUM_TIMER_PATH_FAILURE,                 // 8
  RELATIVE_ZERO_TIMER_PATH_FAILURE,                  // 9
  ALARM_DELAY_PATH_FAILURE,                          // 10
  VACUUM_READ_START_DELAY_PATH_FAILURE,              // 11
  FILTER_COEFFICIENT_PATH_FAILURE,                   // 12
  PUMP_START_MODE_PATH_FAILURE,                      // 13
  PUMP_START_TIME_PATH_FAILURE,                      // 14
  PUMP_STOP_TIME_PATH_FAILURE,                       // 15
  VACUUM_CURVATURE_VALUES_PATH_FAILURE,              // 16
  DEVICE_NAME_PATH_FAILURE,                          // 17
  
/* ----------------------------------- INCONSISTENT VALUES ERRORS: */
  INCONSISTENT_DISPLAY_DELAY_VALUE,                  // 18
  INCONSISTENT_IR_SENSIVITY_VALUE,                   // 19
  INCONSISTENT_EV_PRE_PUMP_TIME_VALUE,               // 20
  INCONSISTENT_EV_POST_PUMP_TIMER_VALUE,             // 21
  INCONSISTENT_MAX_MIN_VACUUM_TIMER_VALUE,           // 22
  INCONSISTENT_RELATIVE_ZERO_TIMER_VALUE,            // 23
  INCONSISTENT_ALARM_DELAY_VALUE,                    // 24
  INCONSISTENT_VACUUM_READ_START_DELAY_VALUE,        // 25
  INCONSISTENT_FILTER_COEFFICIENT_VALUE,             // 26
  INCONSISTENT_PUMP_START_MODE_VALUE,                // 27
  INCONSISTENT_PUMP_START_TIME_VALUE,                // 28
  INCONSISTENT_PUMP_STOP_TIME_VALUE,                 // 29
  INCONSISTENT_CURVATURE_VALUES,                     // 30


  PARAMETERS_MIN_VACUUM_1_PATH_FAILURE,              // 31
  PARAMETERS_MIN_VACUUM_2_PATH_FAILURE,              // 32
  PARAMETERS_MAX_VACUUM_1_PATH_FAILURE,              // 33
  PARAMETERS_MAX_VACUUM_2_PATH_FAILURE,              // 34
  PARAMETERS_RELATIVE_ZERO_1_PATH_FAILURE,           // 35
  PARAMETERS_RELATIVE_ZERO_2_PATH_FAILURE,           // 36
  

  VACUUM_1_MIN_NOT_FOUND,                            // 37
  VACUUM_2_MIN_NOT_FOUND,                            // 38
  VACUUM_1_MAX_NOT_FOUND,                            // 39
  VACUUM_2_MAX_NOT_FOUND,                            // 40
  RELATIVE_ZERO_1_NOT_FOUND,                         // 41
  RELATIVE_ZERO_2_NOT_FOUND,                         // 42


/* -------------------------------------------------- RTC ERRORS: */
  RTC_ERROR,                                         // 43


/* -------------------------------------------------- POWER SOURCE ERRORS: */
  POWER_ERROR,                                       // 44


/* -------------------------------------------------- DISPLAY ERRORS: */
  DISPLAY_ERROR,                                     // 45


/* -------------------------------------------------- OUTPUTS ERRORS: */
  RELAY_ERROR,


/* -------------------------------------------------- INPUTS ERRORS: */
  VACUUM1_LOW_ERROR,
  VACUUM2_LOW_ERROR,
  VACUUM_1_2_LOW_ERROR,
  VACUUM1_HIGH_ERROR,
  VACUUM2_HIGH_ERROR,
  VACUUM_1_2_HIGH_ERROR,
  FLOW_ERROR,

  BT_NOT_RESPONSE
};

enum errorType error;


/* -------------------------------------------------- PUMP START MODE TYPES DECLARATIONS: */
enum pumpStartModeList {
  manual = 1,
  automatic
};

enum pumpStartModeList pumpStartMode;

bool pumpState = false;


/* -------------------------------------------------- GLOBAL TIMERS: */
timer LCDrefresh = timer();
timer alarmResponsivenessTimer = timer();


/* -------------------------------------------------- GLOBAL FLAGS: */
bool alarmFlag = false;

void setup() {
/* -------------------------------------------------- TIMING VARIABLES & STATE VARIABLES DEFINITIONS: */
  const unsigned int presentationTime = 2000;

  
/* -------------------------------------------------- INPUTS: */
  pinMode(IRsensor, INPUT);
  pinMode(BT_state, INPUT);
  pinMode(cardDetectPin, INPUT);
  pinMode(writeProtectPin, INPUT);

/* -------------------------------------------------- OUTPUTS: */
  pinMode(BT_EN, OUTPUT);
  pinMode(BT_power, OUTPUT);
  pinMode(RL1, OUTPUT);
  pinMode(RL2, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(redLamp, OUTPUT);
  pinMode(orangeLamp, OUTPUT);
  pinMode(EV, OUTPUT);
  pinMode(safetyRL, OUTPUT);


  digitalWrite(BT_power, HIGH);
  digitalWrite(BT_EN, LOW);
  digitalWrite(RL1, LOW);
  digitalWrite(RL2, LOW);
  digitalWrite(buzzer, LOW),
  digitalWrite(redLamp, LOW),
  digitalWrite(orangeLamp, LOW),
  digitalWrite(EV, LOW);
  digitalWrite(safetyRL, LOW);

  SERIAL_PORT.begin(SERIAL_BAUDRATE);
  delay(SERIAL_DELAY);


/* -------------------------------------------------- DISPLAY INITIALIZATION: */
  int status = LCD_display.begin(LCD_COLS, LCD_ROWS);
  if(status)
    hd44780::fatalError(status);
  const uint16_t startDisplayDelay = 500;
  delay(startDisplayDelay);


/* -------------------------------------------------- DISPLAY INITIALIZATION: */
  LCD_display.createChar(0, bluetoothSignal);
  LCD_display.createChar(1, bluetoothBar);

  
  LCD_display.on();
  LCDdisplayState = true;
  LCD_display.clear();


/* -------------------------------------------------- INTERNAL RTC INITIALIZATION: */
  RealTimeClock.begin();


/* -------------------------------------------------- SD CONFIGURATION: */
  SDconfiguration();


/* -------------------------------------------------- FIRST START + BLUETOOTH CONFIG: */

  if(!SD.exists("PAR")){
    bluetoothConfig();
    
    getDateTime();

    LCD_display.setCursor(0, 0);
    LCD_display.print("DATE: ");

    LCD_display.setCursor(6, 0);
    printTwoDigits(RealTimeClock.getDay());
    
    LCD_display.setCursor(8, 0);
    LCD_display.print('/');
    
    LCD_display.setCursor(9, 0);
    printTwoDigits(RealTimeClock.getMonth());
    
    LCD_display.setCursor(11, 0);
    LCD_display.print('/');
    
    LCD_display.setCursor(12, 0);
    printTwoDigits(RealTimeClock.getYear());

    LCD_display.setCursor(0, 1);
    LCD_display.print("TIME: ");
    
    LCD_display.setCursor(6, 1);
    printTwoDigits(RealTimeClock.getHours());
    
    LCD_display.setCursor(8, 1);
    LCD_display.print(':');

    LCD_display.setCursor(9, 1);
    printTwoDigits(RealTimeClock.getMinutes());
    
    LCD_display.setCursor(11, 1);
    LCD_display.print(':');
    
    LCD_display.setCursor(12, 1);
    printTwoDigits(RealTimeClock.getSeconds());
    
    delay(5000);
  
    firstStart();
  }else{
      
    getDateTime();

    LCD_display.setCursor(0, 0);
    LCD_display.print("DATE: ");

    LCD_display.setCursor(6, 0);
    printTwoDigits(RealTimeClock.getDay());
    
    LCD_display.setCursor(8, 0);
    LCD_display.print('/');
    
    LCD_display.setCursor(9, 0);
    printTwoDigits(RealTimeClock.getMonth());
    
    LCD_display.setCursor(11, 0);
    LCD_display.print('/');
    
    LCD_display.setCursor(12, 0);
    printTwoDigits(RealTimeClock.getYear());

    LCD_display.setCursor(0, 1);
    LCD_display.print("TIME: ");
    
    LCD_display.setCursor(6, 1);
    printTwoDigits(RealTimeClock.getHours());
    
    LCD_display.setCursor(8, 1);
    LCD_display.print(':');

    LCD_display.setCursor(9, 1);
    printTwoDigits(RealTimeClock.getMinutes());
    
    LCD_display.setCursor(11, 1);
    LCD_display.print(':');
    
    LCD_display.setCursor(12, 1);
    printTwoDigits(RealTimeClock.getSeconds());

    delay(5000);

    normalStart();
  }
  
  error = NO_ERRORS;
  //char FIRST_START_COMPLETE[] = "[DEVICE STARTED]";
  //saveOnSD(FIRST_START_COMPLETE);
  
  LCD_display.setCursor(0, 1);
  LCD_display.print("status: OK");


  LCDdisplayTimer.setTimer(LCDdisplayTime);
  LCD_display.clear();

  LCD_display.setCursor(2, 0);
  LCD_display.print(':');
  LCD_display.setCursor(5, 0);
  LCD_display.print(':');
  
  LCD_display.setCursor(0, 1);
  LCD_display.print("STATUS: ");
  if(error == NO_ERRORS){
    LCD_display.print("OK");
  }else{
    errorHandler();
  }

  while(SERIAL_PORT.available()){
    SERIAL_PORT.read();
  }
}


/* -------------------------------------------------- MAIN LOOP: */
void loop() {
/* -------------------------------------------------- SD CHECK: */
  if(!digitalRead(cardDetectPin) == LOW){
    error = SD_NOT_PRESENT;
    errorHandler();
  }else{
    if(!digitalRead(writeProtectPin) == LOW){
      error = SD_PROTECTED;
      errorHandler();
    }else if(!SD.begin(CS)){
      error = SD_NOT_BEGINNED;
      errorHandler();
    }
  }

  vacuum1 = map(analogRead(vacuum1pin), 0, 1023, 255, 0);
  vacuum2 = map(analogRead(vacuum2pin), 0, 1023, 255, 0);
  
  if(!alarmFlag && (vacuum1 > 220 || vacuum2 > 220)){
    alarmResponsivenessTimer.setTimer(ALARM_DELAY);
    alarmFlag = true;
    LCD_display.setCursor(14, 1);
    LCD_display.print('!');
  }

  if((alarmFlag == true) && (alarmResponsivenessTimer.timerFIRED())){
    if(vacuum1 > 220 && vacuum2 > 220){
      error = VACUUM_1_2_HIGH_ERROR;
      errorHandler();
    }else{
      if(vacuum1 > 220 && vacuum2 < 220){
        error = VACUUM1_HIGH_ERROR;
        errorHandler();
      }
      if(vacuum1 < 220 && vacuum2 > 220){
        error = VACUUM2_HIGH_ERROR;
        errorHandler();
      }
    }
    LCD_display.setCursor(14, 1);
    LCD_display.print(' ');
    alarmFlag = false;
  }
  
  powerCheck = map(analogRead(shutdownPin), 0, 1023, 0, 255);
  
  /*
  if(LCDrefresh.timerFIRED()){
    LCD_display.setCursor(0, 1);
    LCD_display.print("    ");
    LCD_display.setCursor(0, 1);
    LCD_display.print(powerCheck);
    LCDrefresh.setTimer(100);
  }
  */
  
  if(powerCheck < shutdownThreshold){
    error = POWER_ERROR;
    errorHandler();
  }
  
  
  if(LCDdisplayTimer.timerFIRED()){
    LCD_display.off();
    LCDdisplayState = false;
  }

  if(digitalRead(IRsensor) == LOW){
    LCD_display.on();
    LCDdisplayState = true;
    LCDdisplayTimer.setTimer(LCDdisplayTime);
  }
  
  if(digitalRead(BT_state) == HIGH){
    LCD_display.setCursor(14, 0);
    LCD_display.write(0);
  }else{
    LCD_display.setCursor(14, 0);
    LCD_display.print(' ');
  }
  if(!displayPressureFlag){
    if(RealTimeClock.getHours() != oldHours){
      LCD_display.setCursor(0, 0);
      printTwoDigits(RealTimeClock.getHours());
      oldHours = RealTimeClock.getHours();
    }
    if(RealTimeClock.getMinutes() != oldMinutes){
      LCD_display.setCursor(3, 0);
      printTwoDigits(RealTimeClock.getMinutes());
      oldMinutes = RealTimeClock.getMinutes();
    }
  if(RealTimeClock.getSeconds() != oldSeconds){
      LCD_display.setCursor(6, 0);
      printTwoDigits(RealTimeClock.getSeconds());
      oldSeconds = RealTimeClock.getSeconds();
    }
  }

  /* --------------------------------------------------  WAITING PREAMBLE TO GET COMMAND: */
  if(SERIAL_PORT.available()){
    char BTinput = SERIAL_PORT.read();
    if(BTinput == '@'){
      bluetoothCOM();
    }
  }


  if(displayPressureFlag == true){
    
    LCD_display.setCursor(0, 0);
    LCD_display.print("V1:");
    LCD_display.setCursor(3, 0);
    LCD_display.print(minVacuum1);
    LCD_display.setCursor(11, 0);
    LCD_display.print(maxVacuum1);
    
    LCD_display.setCursor(0, 1);
    LCD_display.print("V2:"); 
    LCD_display.setCursor(3, 1);
    LCD_display.print(minVacuum2);
    LCD_display.setCursor(11, 1);
    LCD_display.print(maxVacuum2);
    
    timer displayPressureTimer = timer();
    displayPressureTimer.setTimer(10000);

    if(!displayPressureTimer.timerFIRED()){
      if(LCDrefresh.timerFIRED()){
        if(oldVacuum1 != vacuum1){
          LCD_display.setCursor(7, 0);
          LCD_display.print("   ");
          LCD_display.setCursor(7, 0);
          LCD_display.print(vacuum1);
          oldVacuum1 = vacuum1;
        }
        if(oldVacuum2 != vacuum2){
          LCD_display.setCursor(7, 1);
          LCD_display.print("   ");
          LCD_display.setCursor(7, 1);
          LCD_display.print(vacuum2);
          oldVacuum2 = vacuum2;
        }
      }
      LCDrefresh.setTimer(250);
    }else{
      displayPressureFlag = false;
      
      LCD_display.setCursor(0, 1);
      LCD_display.print("status: OK");


      LCDdisplayTimer.setTimer(LCDdisplayTime);
      LCD_display.clear();

      LCD_display.setCursor(2, 0);
      LCD_display.print(':');
      LCD_display.setCursor(5, 0);
      LCD_display.print(':');
  
      LCD_display.setCursor(0, 1);
      LCD_display.print("STATUS: ");
    }
  }
}


void normalStart(){
  LCD_display.clear();
  LCD_display.setCursor(5, 0);
  LCD_display.print("[START]");

  timer EVtimerPrePump = timer();
  timer RL1timer = timer();
  EVtimerPrePump.setTimer(EV_PRE_PUMP_TIME);
  RL1timer.setTimer(EV_PRE_PUMP_TIME - 1000);    // RL1 must go HIGH before RL2 
  
  digitalWrite(EV, HIGH);

  while(!RL1timer.timerFIRED()){
    
  }
  digitalWrite(RL1, HIGH);

  while(!EVtimerPrePump.timerFIRED()){
    
  }
  digitalWrite(RL2, HIGH);
  
  timer EVtimerPostPump = timer();
  EVtimerPostPump.setTimer(EV_POST_PUMP_TIMER);
  timer redAlarmOnStartTimer = timer();
  redAlarmOnStartTimer.setTimer(VACUUM_READ_START_DELAY);

  //////////////////////////////// DA RIVEDERE CON CURVATURA ///////////////////////////////
  while(!EVtimerPostPump.timerFIRED()){
    while(!redAlarmOnStartTimer.timerFIRED()){
      
    }
    vacuum1 = map(analogRead(vacuum1pin), 0, 1023, 255, 0);
    vacuum2 = map(analogRead(vacuum2pin), 0, 1023, 255, 0);
  }
  
  digitalWrite(EV, LOW);


  vacuum1 = map(analogRead(vacuum1pin), 0, 1023, 255, 0);
  vacuum2 = map(analogRead(vacuum2pin), 0, 1023, 255, 0);


  if(minVacuum1 <= relativeZero1 && minVacuum2 > relativeZero2){
    error = VACUUM1_LOW_ERROR;
    errorHandler();
  }else if(minVacuum1 > relativeZero1 && minVacuum2 <= relativeZero2){
    error = VACUUM2_LOW_ERROR;
    errorHandler();
  }else if(minVacuum1 <= relativeZero1 && minVacuum2 <= relativeZero2){
    error = VACUUM_1_2_LOW_ERROR;
    errorHandler();
  }

  pumpState = true;
}

void pumpStop(){
  timer pumpStopTimer = timer();
  pumpStopTimer.setTimer(1000);
  
  digitalWrite(RL2, LOW);

  while(!pumpStopTimer.timerFIRED()){
    
  }

  digitalWrite(RL1, LOW);
  
  pumpState = false;
}


/* --------------------------------------------------  BLUETOOTH GET COMMAND: */
void bluetoothCOM(){
  LCD_display.on();
  LCDdisplayState = true;
  LCDdisplayTimer.setTimer(LCDdisplayTime);
  
  const uint8_t BTcommandLength = 15;
  char BTcommand[10];
  uint8_t BTcommandIndex = 0;

  while((SERIAL_PORT.available()) && (BTcommandIndex < (BTcommandLength - 1))){
    char incomingChar = SERIAL_PORT.read();
    if((incomingChar != '\n') && (incomingChar != '\r') && (incomingChar != '\0')){
      BTcommand[BTcommandIndex] = incomingChar;
      BTcommand[++BTcommandIndex] = 0;
    }else{
      break;
    }
  }

  /*
  LCD_display.setCursor(0, 1);
  LCD_display.print("          ");
  LCD_display.setCursor(0, 1);
  LCD_display.print(BTcommand);
  */

  if(strcmp(BTcommand, "pON\r\n")){
    displayPressureFlag = true;
    LCD_display.clear();
  }
  else if((strcmp(BTcommand, "START\r\n")) && (pumpState == false))    // && (PUMP_START_MODE == 1)
    normalStart();

  else if((strcmp(BTcommand, "STOP\r\n")) && (pumpState == true))    // && (PUMP_START_MODE == 1)
    pumpStop();

  while(SERIAL_PORT.available()){
    SERIAL_PORT.read();
  }
}

/* -------------------------------------------------- FIRST START */
void firstStart(){
  LCD_display.clear();
  LCD_display.setCursor(1, 0);
  LCD_display.print("[FIRST START]");

  timer EVtimerPrePump = timer();
  EVtimerPrePump.setTimer(EV_PRE_PUMP_TIME);
  digitalWrite(EV, HIGH);

  LCD_display.setCursor(0, 1);
  LCD_display.print("EV ON   PUMP OFF");

  while(!EVtimerPrePump.timerFIRED()){
    
  }

  digitalWrite(RL1, HIGH);

  timer relativeZeroTimer = timer();
  relativeZeroTimer.setTimer(RELATIVE_ZERO_TIMER);

  
  //timer LCDrefresh = timer();
  //LCDrefresh.setTimer(250);

  /*
  LCD_display.clear();
  LCD_display.setCursor(0, 0);
  LCD_display.print("[RELATIVE ZERO]");
  
  LCD_display.setCursor(0, 1);
  LCD_display.print("RZ1: ");
  LCD_display.setCursor(8, 1);
  LCD_display.print("RZ2: ");
  */
  

  while(!relativeZeroTimer.timerFIRED()){
    vacuum1 = map(analogRead(vacuum1pin), 0, 1023, 255, 0);
    vacuum2 = map(analogRead(vacuum2pin), 0, 1023, 255, 0);

    if(vacuum1 > maxVacuum1){
      relativeZero1 = vacuum1;
    }
    if(vacuum2 > maxVacuum2){
      relativeZero2 = vacuum2;
    }

    /*
    if(LCDrefresh.timerFIRED()){
      if(relativeZero1 != oldRelativeZero1){
        LCD_display.setCursor(5, 1);
        LCD_display.print("   ");
        LCD_display.setCursor(5, 1);
        LCD_display.print(relativeZero1);
        oldRelativeZero1 = relativeZero1;
      }
      if(relativeZero2 != oldRelativeZero2){
        LCD_display.setCursor(13, 1);
        LCD_display.print("   ");
        LCD_display.setCursor(13, 1);
        LCD_display.print(relativeZero2);
        oldRelativeZero2 = relativeZero2;
      }
      LCDrefresh.setTimer(250);
    }
    */
    
  }
  
  digitalWrite(RL2, HIGH);
  timer EVtimerPostPump = timer();
  EVtimerPostPump.setTimer(EV_POST_PUMP_TIMER);

  LCD_display.setCursor(0, 1);
  LCD_display.print("EV ON   PUMP ON ");

  while(!EVtimerPostPump.timerFIRED()){
    
  }

  digitalWrite(EV, LOW);
  LCD_display.setCursor(0, 1);
  LCD_display.print("EV OFF  PUMP ON ");


  timer vacuumStabilizationTimer = timer();
  uint16_t stabilizationtimer = 10000;
  vacuumStabilizationTimer.setTimer(stabilizationtimer);

  while(!vacuumStabilizationTimer.timerFIRED()){
    
  }
  /*
  LCD_display.clear();
  LCD_display.setCursor(3, 0);
  LCD_display.print("[PRESSURES]");
  
  LCD_display.setCursor(0, 1);
  LCD_display.print("V1:");
  LCD_display.setCursor(10, 1);
  LCD_display.print("V2:"); 
  */
  timer maxMinVacuumTimer = timer();
  maxMinVacuumTimer.setTimer(MAX_MIN_VACUUM_TIMER);

  minVacuum1 = 255;
  minVacuum2 = 255;

  maxVacuum1 = 0;
  maxVacuum2 = 0;


  //LCDrefresh.setTimer(250);

  while(!maxMinVacuumTimer.timerFIRED()){
    vacuum1 = map(analogRead(vacuum1pin), 0, 1023, 255, 0);
    vacuum2 = map(analogRead(vacuum2pin), 0, 1023, 255, 0);

    if(vacuum1 > maxVacuum1){
      maxVacuum1 = vacuum1;
    }
    if(vacuum2 > maxVacuum2){
      maxVacuum2 = vacuum2;
    }
    if(vacuum1 < minVacuum1){
      minVacuum1 = vacuum1;
    }
    if(vacuum2 < minVacuum2){
      minVacuum2 = vacuum2;
    }

    /*
    if(LCDrefresh.timerFIRED()){
      if(oldVacuum1 != vacuum1){
        LCD_display.setCursor(3, 1);
        LCD_display.print("   ");
        LCD_display.setCursor(3, 1);
        LCD_display.print(vacuum1);
        oldVacuum1 = vacuum1;
      }
      if(oldVacuum2 != vacuum2){
        LCD_display.setCursor(13, 1);
        LCD_display.print("   ");
        LCD_display.setCursor(13, 1);
        LCD_display.print(vacuum2);
        oldVacuum2 = vacuum2;
      }
      LCDrefresh.setTimer(250);
    }
    */
  }

  if(minVacuum1 <= relativeZero1 && minVacuum2 > relativeZero2){
    error = VACUUM1_LOW_ERROR;
    errorHandler();
  }else if(minVacuum1 > relativeZero1 && minVacuum2 <= relativeZero2){
    error = VACUUM2_LOW_ERROR;
    errorHandler();
  }else if(minVacuum1 <= relativeZero1 && minVacuum2 <= relativeZero2){
    error = VACUUM_1_2_LOW_ERROR;
    errorHandler();
  }

  LCD_display.clear();
  
  LCD_display.setCursor(0, 0);
  LCD_display.print("mV1:");
  LCD_display.print(minVacuum1);
  
  LCD_display.setCursor(0, 1);
  LCD_display.print("mV2:");
  LCD_display.print(minVacuum2);

  LCD_display.setCursor(9, 0);
  LCD_display.print("MV1:");
  LCD_display.print(maxVacuum1);
  
  LCD_display.setCursor(9, 1);
  LCD_display.print("MV2:");
  LCD_display.print(maxVacuum2);
  

  digitalWrite(RL2, LOW);
  delay(1000);
  digitalWrite(RL1, LOW);
  
  delay(1000);

  SD.mkdir("PAR");

  uint8_t paramsDone = 0;
  uint8_t paramsNumber = 6;
  while(paramsDone < paramsNumber){
    char numToChar[4];
    for(uint8_t i = 0; i < 4; i++){
      numToChar[i] = 0;
    }

    switch(paramsDone){
      case 0:
        sprintf(numToChar, "%d", minVacuum1);
        myFile = SD.open(PARAMETERS_MIN_VACUUM_1_PATH, FILE_WRITE);
        myFile.write(numToChar);
        myFile.close();
        break;

      case 1:
        sprintf(numToChar, "%d", minVacuum2);
        myFile = SD.open(PARAMETERS_MIN_VACUUM_2_PATH, FILE_WRITE);
        myFile.write(numToChar);
        myFile.close();
        break;

      case 2:
        sprintf(numToChar, "%d", maxVacuum1);
        myFile = SD.open(PARAMETERS_MAX_VACUUM_1_PATH, FILE_WRITE);
        myFile.write(numToChar);
        myFile.close();
        break;

      case 3:
        sprintf(numToChar, "%d", maxVacuum2);
        myFile = SD.open(PARAMETERS_MAX_VACUUM_2_PATH, FILE_WRITE);
        myFile.write(numToChar);
        myFile.close();
        break;

      case 4:
        sprintf(numToChar, "%d", relativeZero1);
        myFile = SD.open(PARAMETERS_RELATIVE_ZERO_1_PATH, FILE_WRITE);
        myFile.write(numToChar);
        myFile.close();
        break;

      case 5:
        sprintf(numToChar, "%d", relativeZero2);
        myFile = SD.open(PARAMETERS_RELATIVE_ZERO_2_PATH, FILE_WRITE);
        myFile.write(numToChar);
        myFile.close();
        break;
    }

    paramsDone++;
  }

  char FIRST_START_COMPLETE[] = "[FIRST START]";
  
  saveOnSD(FIRST_START_COMPLETE);

  delay(5000);

  LCD_display.clear();
  LCD_display.setCursor(0, 0);
  LCD_display.print("[PARAMETERS OK]");

  
  while(true){
    LCD_display.setCursor(1, 1);
    LCD_display.print("restart system");
    delay(2000);
    LCD_display.setCursor(1, 1);
    LCD_display.print("              ");
    delay(2000);
  }
  
}

/* -------------------------------------------------- SD CONFIGURATION: */
void SDconfiguration(){

  myFile.close();
  
  const uint16_t SDdelay = 250;
  uint16_t display_delay = 1000;
  bool SDOK = false;

  while(!SDOK){
    if(digitalRead(cardDetectPin) == LOW){
      if(digitalRead(writeProtectPin) == LOW){
        if(SD.begin(8)){
          SDOK = true;
        }else{
          error = SD_NOT_BEGINNED;
          errorHandler();
          delay(SDdelay);
        }
      }else{
        error = SD_PROTECTED;
        errorHandler();
        delay(SDdelay);
      }
    }else{
      error = SD_NOT_PRESENT;
      errorHandler();
      delay(SDdelay);
    }
  }
  
  
  if(digitalRead(cardDetectPin) == LOW){
    if(digitalRead(writeProtectPin) == LOW){
      if(SD.begin(8)){

/* -------------------------------------------------- SD DIRECTORIES CHECK: */

/* -------------------------------------------------- DIRECTORY CONFIG DOESN'T EXISTS: */
        if(!SD.exists("CONFIG")){
          
          SD.mkdir("CONFIG");
          
          myFile = SD.open(DISPLAY_DELAY_PATH, FILE_WRITE);
          myFile.write(DEFAULT_DISPLAY_DELAY);
          myFile.close();
          

          myFile = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
          myFile.write(DEFAULT_IR_SENSIVITY);
          IR_SENSIVITY = 500;
          myFile.close();


          myFile = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_WRITE);
          myFile.write(DEFAULT_EV_PRE_PUMP_TIME);
          EV_PRE_PUMP_TIME = 3000;
          myFile.close();


          myFile = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
          myFile.write(DEFAULT_EV_POST_PUMP_TIMER);
          EV_POST_PUMP_TIMER = 5000;
          myFile.close();


          myFile = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_WRITE);
          myFile.write(DEFAULT_MAX_MIN_VACUUM_TIMER);
          MAX_MIN_VACUUM_TIMER = 60000;
          myFile.close();

          
          myFile = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
          myFile.write(DEFAULT_RELATIVE_ZERO_TIMER);
          RELATIVE_ZERO_TIMER = 5000;
          myFile.close();

          
          myFile = SD.open(ALARM_DELAY_PATH, FILE_WRITE);
          myFile.write(DEFAULT_ALARM_DELAY);
          ALARM_DELAY = 1000;
          myFile.close();

          
          myFile = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_WRITE);
          myFile.write(DEFAULT_VACUUM_READ_START_DELAY);
          VACUUM_READ_START_DELAY = 3000;
          myFile.close();

          
          myFile = SD.open(FILTER_COEFFICIENT_PATH, FILE_WRITE);
          myFile.write(DEFAULT_FILTER_COEFFICIENT);
          FILTER_COEFFICIENT = 5;
          myFile.close();


          myFile = SD.open(PUMP_START_MODE_PATH, FILE_WRITE);
          myFile.write(DEFAULT_PUMP_START_MODE);
          PUMP_START_MODE = 1;
          myFile.close();

          
          myFile = SD.open(PUMP_START_TIME_PATH, FILE_WRITE);
          myFile.write(DEFAULT_PUMP_START_TIME);
          myFile.close();

          
          myFile = SD.open(PUMP_STOP_TIME_PATH, FILE_WRITE);
          myFile.write(DEFAULT_PUMP_STOP_TIME);
          myFile.close();

          myFile = SD.open(DEVICE_NAME_PATH, FILE_WRITE);
          myFile.print(DEFAULT_DEVICE_NAME);
          myFile.close();

          
/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT MODULE_NUMBER.txt FILE DOESN'T: */
        }else{
          LCD_display.clear();
          LCD_display.setCursor(2, 0);
          LCD_display.print("[SD CONFIG]");
          /*
          if(SD.exists(DISPLAY_DELAY_PATH)){
            myFile = SD.open(DISPLAY_DELAY_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
                
                myFile = SD.open(DISPLAY_DELAY_PATH, FILE_WRITE);
                myFile.write(DEFAULT_DISPLAY_DELAY);
                
                myFile.close();
              }
            }
          }else{
            myFile = SD.open(DISPLAY_DELAY_PATH, FILE_WRITE);
            myFile.write(DEFAULT_DISPLAY_DELAY);
            myFile.close();
          }
          */

/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT IR_SENSOR_SENSIVITY.txt FILE DOESN'T: */
          if(SD.exists(IR_SENSIVITY_PATH)){
            myFile = SD.open(IR_SENSIVITY_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
                myFile.write(DEFAULT_IR_SENSIVITY);

                myFile.close();
              }else{
                const uint8_t MaxChar = 5;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                sscanf(CharArray, "%d", &IR_SENSIVITY);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("IRSS: ");
                LCD_display.print(IR_SENSIVITY);
                delay(display_delay);

                if(IR_SENSIVITY < 0 || IR_SENSIVITY > 1023){
                  IR_SENSIVITY = 500;    // reset to default value if readed value is inconsistent
                  myFile.close();
                  SD.remove(IR_SENSIVITY_PATH);
                  myFile = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_IR_SENSIVITY);
                  myFile.close();
                    
                  error = INCONSISTENT_IR_SENSIVITY_VALUE;
                  errorHandler();
                }
                myFile.close();
              }
            }else{
              myFile.close();
              error = IR_SENSIVITY_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(IR_SENSIVITY_PATH, FILE_WRITE);
            myFile.write(DEFAULT_IR_SENSIVITY);
            myFile.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT EV_PRE_PUMP_TIMER.txt FILE DOESN'T: */
          if(SD.exists(EV_PRE_PUMP_TIME_PATH)){
            myFile = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_WRITE);
                myFile.write(DEFAULT_EV_PRE_PUMP_TIME);

                myFile.close();
              }else{
                const uint8_t MaxChar = 5;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &EV_PRE_PUMP_TIME);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("EVPE: ");
                LCD_display.print(EV_PRE_PUMP_TIME);
                delay(display_delay);

                if(EV_PRE_PUMP_TIME < 0 || EV_PRE_PUMP_TIME > 5000){
                  EV_PRE_PUMP_TIME = 3000;    // reset to default value if readed value is inconsistent
                  myFile.close();
                  SD.remove(EV_PRE_PUMP_TIME_PATH);
                  myFile = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_EV_PRE_PUMP_TIME);
                  myFile.close();
                    
                  error = INCONSISTENT_EV_PRE_PUMP_TIME_VALUE;
                  errorHandler();
                }
                myFile.close();
              }
            }else{
              myFile.close();
              error = EV_PRE_PUMP_TIME_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(EV_PRE_PUMP_TIME_PATH, FILE_WRITE);
            myFile.write(DEFAULT_EV_PRE_PUMP_TIME);
            myFile.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT EV_POST_PUMP_TIMER.txt FILE DOESN'T: */
          if(SD.exists(EV_POST_PUMP_TIMER_PATH)){
            myFile = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
                myFile.write(DEFAULT_EV_POST_PUMP_TIMER);

                myFile.close();
              }else{
                const uint8_t MaxChar = 6;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &EV_POST_PUMP_TIMER);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("EVPT: ");
                LCD_display.print(EV_POST_PUMP_TIMER);
                delay(display_delay);

                if(EV_POST_PUMP_TIMER < 0 || EV_POST_PUMP_TIMER > 10000){
                  EV_POST_PUMP_TIMER = 5000;    // reset to default value if readed value is inconsistent
                  myFile.close();
                  SD.remove(EV_POST_PUMP_TIMER_PATH);
                  myFile = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_EV_POST_PUMP_TIMER);
                  myFile.close();
                    
                  error = INCONSISTENT_EV_POST_PUMP_TIMER_VALUE;
                  errorHandler();
                }
                myFile.close();
              }
            }else{
              myFile.close();
              error = EV_POST_PUMP_TIMER_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
            myFile.write(DEFAULT_EV_POST_PUMP_TIMER);
            myFile.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT MAX&MIN_VACUUM_TIMER.txt FILE DOESN'T: */
          if(SD.exists(MAX_MIN_VACUUM_TIMER_PATH)){
            myFile = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_WRITE);
                myFile.write(DEFAULT_MAX_MIN_VACUUM_TIMER);

                myFile.close();
              }else{
                const uint8_t MaxChar = 7;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }

                sscanf(CharArray, "%d", &MAX_MIN_VACUUM_TIMER);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("MMVT: ");
                LCD_display.print(MAX_MIN_VACUUM_TIMER);
                delay(display_delay);

                if(MAX_MIN_VACUUM_TIMER < 30000 || MAX_MIN_VACUUM_TIMER > 180000){
                  MAX_MIN_VACUUM_TIMER = 60000;    // reset to default value if readed value is inconsistent
                  myFile.close();
                  SD.remove(MAX_MIN_VACUUM_TIMER_PATH);
                  myFile = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_MAX_MIN_VACUUM_TIMER);
                  myFile.close();
                    
                  error = INCONSISTENT_MAX_MIN_VACUUM_TIMER_VALUE;
                  errorHandler();
                }
                myFile.close();
              }
            }else{
              myFile.close();
              error = MAX_MIN_VACUUM_TIMER_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(MAX_MIN_VACUUM_TIMER_PATH, FILE_WRITE);
            myFile.write(DEFAULT_MAX_MIN_VACUUM_TIMER);
            myFile.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT RELATIVE_ZERO_TIMER.txt FILE DOESN'T: */
          if(SD.exists(RELATIVE_ZERO_TIMER_PATH)){
            myFile = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
                myFile.write(DEFAULT_RELATIVE_ZERO_TIMER);

                myFile.close();
              }else{
                const uint8_t MaxChar = 6;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }

                sscanf(CharArray, "%d", &RELATIVE_ZERO_TIMER);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("RZTR: ");
                LCD_display.print(RELATIVE_ZERO_TIMER);
                delay(display_delay);

                if(RELATIVE_ZERO_TIMER < 2000 || RELATIVE_ZERO_TIMER > 10000){
                  RELATIVE_ZERO_TIMER = 5000;    // reset to default value if readed value is inconsistent
                  myFile.close();
                  SD.remove(RELATIVE_ZERO_TIMER_PATH);
                  myFile = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_RELATIVE_ZERO_TIMER);
                  myFile.close();
                    
                  error = INCONSISTENT_RELATIVE_ZERO_TIMER_VALUE;
                  errorHandler();
                }
                myFile.close();
              }
            }else{
              myFile.close();
              error = RELATIVE_ZERO_TIMER_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
            myFile.write(DEFAULT_RELATIVE_ZERO_TIMER);
            myFile.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT ALARM_DELAY.txt FILE DOESN'T: */
          if(SD.exists(ALARM_DELAY_PATH)){
            myFile = SD.open(ALARM_DELAY_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(ALARM_DELAY_PATH, FILE_WRITE);
                myFile.write(DEFAULT_ALARM_DELAY);

                myFile.close();
              }else{
                const uint8_t MaxChar = 5;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while((myFile.available())){
                  char incomingChar = myFile.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &ALARM_DELAY);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("AMRS: ");
                LCD_display.print(ALARM_DELAY);
                delay(display_delay);

                if(ALARM_DELAY < 500 || ALARM_DELAY > 3000){
                  ALARM_DELAY = 1000;    // reset to default value if readed value is inconsistent
                  myFile.close();
                  SD.remove(ALARM_DELAY_PATH);
                  myFile = SD.open(ALARM_DELAY_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_ALARM_DELAY);
                  myFile.close();
                    
                  error = INCONSISTENT_ALARM_DELAY_VALUE;
                  errorHandler();
                }
                myFile.close();
              }
            }else{
              myFile.close();
              error = ALARM_DELAY_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(ALARM_DELAY_PATH, FILE_WRITE);
            myFile.write(DEFAULT_ALARM_DELAY);
            myFile.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT VACUUM_READ_START_DELAY.txt FILE DOESN'T: */
          if(SD.exists(VACUUM_READ_START_DELAY_PATH)){
            myFile = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_WRITE);
                myFile.write(DEFAULT_VACUUM_READ_START_DELAY);

                myFile.close();
              }else{
                const uint8_t MaxChar = 5;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &VACUUM_READ_START_DELAY);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("VRSD: ");
                LCD_display.print(VACUUM_READ_START_DELAY);
                delay(display_delay);

                if(VACUUM_READ_START_DELAY < 0 || VACUUM_READ_START_DELAY > 5000){
                  VACUUM_READ_START_DELAY = 3000;    // reset to default value if readed value is inconsistent
                  myFile.close();
                  SD.remove(VACUUM_READ_START_DELAY_PATH);
                  myFile = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_VACUUM_READ_START_DELAY);
                  myFile.close();
                    
                  error = INCONSISTENT_VACUUM_READ_START_DELAY_VALUE;
                  errorHandler();
                }
                myFile.close();
              }
            }else{
              myFile.close();
              error = VACUUM_READ_START_DELAY_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(VACUUM_READ_START_DELAY_PATH, FILE_WRITE);
            myFile.write(DEFAULT_VACUUM_READ_START_DELAY);
            myFile.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT FILTER_COEFFICIENT.txt FILE DOESN'T: */
          if(SD.exists(FILTER_COEFFICIENT_PATH)){
            myFile = SD.open(FILTER_COEFFICIENT_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(FILTER_COEFFICIENT_PATH, FILE_WRITE);
                myFile.write(DEFAULT_FILTER_COEFFICIENT);

                myFile.close();
              }else{
                const uint8_t MaxChar = 3;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex] = 0;
                  }
                }
                
                sscanf(CharArray, "%d", &FILTER_COEFFICIENT);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("FRCT: ");
                LCD_display.print(FILTER_COEFFICIENT);
                delay(display_delay);

                if(FILTER_COEFFICIENT < 0 || FILTER_COEFFICIENT > 10){
                  FILTER_COEFFICIENT = 5;    // reset to default value if readed value is inconsistent
                  myFile.close();
                  SD.remove(FILTER_COEFFICIENT_PATH);
                  myFile = SD.open(FILTER_COEFFICIENT_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_FILTER_COEFFICIENT);
                  myFile.close();
                    
                  error = INCONSISTENT_FILTER_COEFFICIENT_VALUE;
                  errorHandler();
                }
                myFile.close();
              }
            }else{
              myFile.close();
              error = FILTER_COEFFICIENT_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(FILTER_COEFFICIENT_PATH, FILE_WRITE);
            myFile.write(DEFAULT_FILTER_COEFFICIENT);
            myFile.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT PUMP_START_MODE.txt FILE DOESN'T: */
          if(SD.exists(PUMP_START_MODE_PATH)){
            myFile = SD.open(PUMP_START_MODE_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(PUMP_START_MODE_PATH, FILE_WRITE);
                myFile.write(DEFAULT_PUMP_START_MODE);

                myFile.close();
              }else{
                char startMode;
                while(myFile.available()){
                  char incomingChar = myFile.read();
                
                  if(isDigit(incomingChar)){
                    startMode = incomingChar;
                  }
                }
                
                PUMP_START_MODE = startMode - '0';
                
                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("PSTM: ");
                LCD_display.print(PUMP_START_MODE);
                delay(display_delay);

                if(PUMP_START_MODE < 1 || PUMP_START_MODE > 2){
                  PUMP_START_MODE = 1;    // reset to default value if readed value is inconsistent
                  myFile.close();
                  SD.remove(PUMP_START_MODE_PATH);
                  myFile = SD.open(PUMP_START_MODE_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_PUMP_START_MODE);
                  myFile.close();
                    
                  error = INCONSISTENT_PUMP_START_MODE_VALUE;
                  errorHandler();
                }
                myFile.close();
              }
            }else{
              myFile.close();
              error = PUMP_START_MODE_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(PUMP_START_MODE_PATH, FILE_WRITE);
            myFile.write(DEFAULT_PUMP_START_MODE);
            myFile.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT PUMP_START_TIME.txt FILE DOESN'T: */
          if(SD.exists(PUMP_START_TIME_PATH)){
            myFile = SD.open(PUMP_START_TIME_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(PUMP_START_TIME_PATH, FILE_WRITE);
                myFile.write(DEFAULT_PUMP_START_TIME);

                myFile.close();
              }else{
                const uint8_t MaxChar = 3;
                char HoursArray[MaxChar];
                char MinutesArray[MaxChar];
                uint8_t ArrayIndex = 0;
                bool hourIsDone = false;
                bool incorrectTime = false;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();

                  if(incomingChar == ':'){
                    hourIsDone = true;
                    ArrayIndex = 0;
                  }
                  
                  if(!hourIsDone){
                    if(isDigit(incomingChar)){
                      HoursArray[ArrayIndex] = incomingChar;
                      HoursArray[++ArrayIndex] = 0;
                    }
                  }else{
                    if(isDigit(incomingChar)){
                      MinutesArray[ArrayIndex] = incomingChar;
                      MinutesArray[++ArrayIndex] = 0;
                    }
                  }
                }
                
                sscanf(HoursArray, "%d", &PUMP_START_HOURS);
                sscanf(MinutesArray, "%d", &PUMP_START_MINUTES);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("PSTT: ");
                printTwoDigits(PUMP_START_HOURS);
                LCD_display.print(':');
                printTwoDigits(PUMP_START_MINUTES);
                delay(display_delay);

                if(PUMP_START_HOURS < 0 || PUMP_START_HOURS > 23){
                  PUMP_START_HOURS = 07;
                  incorrectTime = true;
                }
                if(PUMP_START_MINUTES < 0 || PUMP_START_MINUTES > 59){
                  PUMP_START_MINUTES = 00;
                  incorrectTime = true;
                }

                if(incorrectTime){
                  myFile.close();
                  SD.remove(PUMP_START_TIME_PATH);
                  myFile = SD.open(PUMP_START_TIME_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_PUMP_START_TIME);
                  myFile.close();
                    
                  error = INCONSISTENT_PUMP_START_TIME_VALUE;
                  errorHandler();
                }
              }
            }else{
              myFile.close();
              error = PUMP_START_TIME_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(PUMP_START_TIME_PATH, FILE_WRITE);
            myFile.write(DEFAULT_PUMP_START_TIME);
            myFile.close();
          }
          myFile.close();


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT PUMP_STOP_TIME.txt FILE DOESN'T: */
          if(SD.exists(PUMP_STOP_TIME_PATH)){
            myFile = SD.open(PUMP_STOP_TIME_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(PUMP_STOP_TIME_PATH, FILE_WRITE);
                myFile.write(DEFAULT_PUMP_STOP_TIME);

                myFile.close();
              }else{
                const uint8_t MaxChar = 3;
                char HoursArray[MaxChar];
                char MinutesArray[MaxChar];
                bool hourIsDone = false;
                bool incorrectTime = false;
                uint8_t ArrayIndex = 0;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();

                  if(incomingChar == ':'){
                    hourIsDone = true;
                    ArrayIndex = 0;
                  }
                  
                  if(!hourIsDone){
                    if(isDigit(incomingChar)){
                      HoursArray[ArrayIndex] = incomingChar;
                      HoursArray[++ArrayIndex] = 0;
                    }
                  }else{
                    if(isDigit(incomingChar)){
                      MinutesArray[ArrayIndex] = incomingChar;
                      MinutesArray[++ArrayIndex] = 0;
                    }
                  }
                }
                
                sscanf(HoursArray, "%d", &PUMP_STOP_HOURS);
                sscanf(MinutesArray, "%d", &PUMP_STOP_MINUTES);

                LCD_display.setCursor(0, 1);
                LCD_display.print("                ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("PSPT: ");
                printTwoDigits(PUMP_STOP_HOURS);
                LCD_display.print(':');
                printTwoDigits(PUMP_STOP_MINUTES);
                delay(display_delay);

                if(PUMP_STOP_HOURS < 0 || PUMP_STOP_HOURS > 23){
                  PUMP_STOP_HOURS = 19;
                  incorrectTime = true;
                }
                if(PUMP_STOP_MINUTES < 0 || PUMP_STOP_MINUTES > 59){
                  PUMP_STOP_MINUTES = 00;
                  incorrectTime = true;
                }
                
                if(incorrectTime){
                  myFile.close();
                  SD.remove(PUMP_STOP_TIME_PATH);
                  myFile = SD.open(PUMP_STOP_TIME_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_PUMP_STOP_TIME);
                  myFile.close();
                    
                  error = INCONSISTENT_PUMP_STOP_TIME_VALUE;
                  errorHandler();
                }
              }
            }else{
              myFile.close();
              error = PUMP_STOP_TIME_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(PUMP_STOP_TIME_PATH, FILE_WRITE);
            myFile.write(DEFAULT_PUMP_STOP_TIME);
            myFile.close();
          }
          myFile.close();


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT VACUUM_CURVATURE_VALUES.txt FILE DOESN'T: */
          if(SD.exists(VACUUM_CURVATURE_VALUES_PATH)){
            myFile = SD.open(VACUUM_CURVATURE_VALUES_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(VACUUM_CURVATURE_VALUES_PATH, FILE_WRITE);
                myFile.write(DEFAULT_VACUUM_CURVATURE_VALUES);

                myFile.close();
              }else{

                const uint8_t curvatureValuesLength = 17;
                char curvatureValues[curvatureValuesLength];
                uint8_t curvatureValuesIndex = 0;

                while(myFile.available()){
                  char incomingChar = myFile.read();
                  if(isDigit(incomingChar) && (curvatureValuesIndex < curvatureValuesLength)){
                    curvatureValues[curvatureValuesIndex] = incomingChar;
                    curvatureValuesIndex++;
                  }
                }

                char curvatureSingleValue[3];
                for(uint8_t i = 0; i < curvatureValuesLength; i++){
                  curvatureSingleValue[0] = curvatureValues[i];
                  curvatureSingleValue[1] = curvatureValues[i + 1];

                  switch(i){
                    case 0:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE1);
                      break;
                      
                    case 2:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE2);
                      break;
  
                    case 4:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE3);
                      break;
  
                    case 6:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE4);
                      break;
  
                    case 8:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE5);
                      break;
  
                    case 10:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE6);
                      break;
  
                    case 12:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE7);
                      break;
  
                    case 14:
                      sscanf(curvatureSingleValue, "%d", &CURVATURE_VALUE8);
                      break;
                  }
                }
                
                LCD_display.setCursor(0, 1);
                LCD_display.print("               ");
                LCD_display.setCursor(0, 1);
                LCD_display.print("C1: ");
                printTwoDigits(CURVATURE_VALUE1);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C2: ");
                printTwoDigits(CURVATURE_VALUE2);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C3: ");
                printTwoDigits(CURVATURE_VALUE3);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C4: ");
                printTwoDigits(CURVATURE_VALUE4);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C5: ");
                printTwoDigits(CURVATURE_VALUE5);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C6: ");
                printTwoDigits(CURVATURE_VALUE6);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C7: ");
                printTwoDigits(CURVATURE_VALUE7);
                delay(display_delay);

                LCD_display.setCursor(0, 1);
                LCD_display.print("C8: ");
                printTwoDigits(CURVATURE_VALUE8);
                delay(display_delay);

                /*
                if(PUMP_STOP_HOURS < 0 || PUMP_STOP_HOURS > 23){
                  PUMP_STOP_HOURS = 19;
                  incorrectTime = true;
                }
                if(PUMP_STOP_MINUTES < 0 || PUMP_STOP_MINUTES > 59){
                  PUMP_STOP_MINUTES = 00;
                  incorrectTime = true;
                }
                
                if(incorrectTime){
                  myFile.close();
                  SD.remove(PUMP_STOP_TIME_PATH);
                  myFile = SD.open(PUMP_STOP_TIME_PATH, FILE_WRITE);
                  myFile.write(DEFAULT_PUMP_STOP_TIME);
                  myFile.close();
                    
                  error = INCONSISTENT_PUMP_STOP_TIME_VALUE;
                  errorHandler();
                }
                */
              }
            }else{
              myFile.close();
              error = VACUUM_CURVATURE_VALUES_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(VACUUM_CURVATURE_VALUES_PATH, FILE_WRITE);
            myFile.write(DEFAULT_VACUUM_CURVATURE_VALUES);
            myFile.close();
          }
          myFile.close();


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT DEVIC_ENAME.txt FILE DOESN'T: */
          if(SD.exists(DEVICE_NAME_PATH)){
            myFile = SD.open(DEVICE_NAME_PATH, FILE_READ);
            if(myFile){
              if(!myFile.available()){
                myFile.close();
              
                myFile = SD.open(DEVICE_NAME_PATH, FILE_WRITE);
                myFile.write(DEFAULT_DEVICE_NAME);

                myFile.close();
              }else{
                for(uint8_t i = 0; i < DEVICE_NAME_MAX; i++){
                  DEVICE_NAME[i] = '\0';
                }
                
                uint8_t ArrayIndex = 0;
                
                while(myFile.available()){
                  char incomingChar = myFile.read();
                  DEVICE_NAME[ArrayIndex] = incomingChar;
                  DEVICE_NAME[++ArrayIndex] = 0;
                }

                LCD_display.setCursor(0, 1);
                LCD_display.print("BT:             ");
                LCD_display.setCursor(3, 1);
                LCD_display.print(DEVICE_NAME);
                delay(display_delay);
              }
            }else{
              myFile.close();
              error = DEVICE_NAME_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myFile = SD.open(DEVICE_NAME_PATH, FILE_WRITE);
            myFile.write(DEFAULT_DEVICE_NAME);
            myFile.close();
          }
          myFile.close();


        }


/* -------------------------------------------------- DIRECTORY "EVENTS" DOESN'T EXISTS: */
        if(!SD.exists("EVENTS")){
          SD.mkdir("EVENTS");


/* -------------------------------------------------- DIRECTORY "EVENTS" EXISTS BUT EVENTS.txt FILE DOESN'T: */
        }else{
          if(!SD.exists(EVENTS_PATH)){
            myFile = SD.open(EVENTS_PATH, FILE_WRITE);
            myFile.close();
          }
        }

        if(SD.exists("PAR")){
          myFile = SD.open(PARAMETERS_MIN_VACUUM_1_PATH);
          if(myFile){
            if(!myFile.available()){
              error = VACUUM_1_MIN_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myFile.available()){
                char incomingChar = myFile.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &minVacuum1);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("mV1: ");
              LCD_display.print(minVacuum1);
              delay(display_delay);
            }
          }else{
            myFile.close();
            error = PARAMETERS_MIN_VACUUM_1_PATH_FAILURE;
            errorHandler();
          }
          myFile.close();


          myFile = SD.open(PARAMETERS_MIN_VACUUM_2_PATH);
          if(myFile){
            if(!myFile.available()){
              error = VACUUM_2_MIN_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myFile.available()){
                char incomingChar = myFile.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &minVacuum2);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("mV2: ");
              LCD_display.print(minVacuum2);
              delay(display_delay);
            }
          }else{
            myFile.close();
            error = PARAMETERS_MIN_VACUUM_2_PATH_FAILURE;
            errorHandler();
          }
          myFile.close();


          myFile = SD.open(PARAMETERS_MAX_VACUUM_1_PATH);
          if(myFile){
            if(!myFile.available()){
              error = VACUUM_1_MAX_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myFile.available()){
                char incomingChar = myFile.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &maxVacuum1);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("MV1: ");
              LCD_display.print(maxVacuum1);
              delay(display_delay);
            }
          }else{
            myFile.close();
            error = PARAMETERS_MAX_VACUUM_1_PATH_FAILURE;
            errorHandler();
          }
          myFile.close();


          myFile = SD.open(PARAMETERS_MAX_VACUUM_2_PATH);
          if(myFile){
            if(!myFile.available()){
              error = VACUUM_2_MAX_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myFile.available()){
                char incomingChar = myFile.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &maxVacuum2);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("MV2: ");
              LCD_display.print(maxVacuum2);
              delay(display_delay);
            }
          }else{
            myFile.close();
            error = PARAMETERS_MAX_VACUUM_2_PATH_FAILURE;
            errorHandler();
          }
          myFile.close();


          myFile = SD.open(PARAMETERS_RELATIVE_ZERO_1_PATH);
          if(myFile){
            if(!myFile.available()){
              error = RELATIVE_ZERO_1_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myFile.available()){
                char incomingChar = myFile.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &relativeZero1);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("RZ1: ");
              LCD_display.print(relativeZero1);
              delay(display_delay);
            }
          }else{
            error = PARAMETERS_RELATIVE_ZERO_1_PATH_FAILURE;
            errorHandler();
          }
          myFile.close();


          myFile = SD.open(PARAMETERS_RELATIVE_ZERO_2_PATH);
          if(myFile){
            if(!myFile.available()){
              error = RELATIVE_ZERO_2_NOT_FOUND;
              errorHandler();
            }else{
              const uint8_t MaxChar = 4;
              char CharArray[MaxChar];
              uint8_t ArrayIndex = 0;
                
              while(myFile.available()){
                char incomingChar = myFile.read();
                
                if(isDigit(incomingChar)){
                  CharArray[ArrayIndex] = incomingChar;
                  CharArray[++ArrayIndex] = 0;
                }
              }
                
              sscanf(CharArray, "%d", &relativeZero2);

              LCD_display.setCursor(0, 1);
              LCD_display.print("                ");
              LCD_display.setCursor(0, 1);
              LCD_display.print("RZ2: ");
              LCD_display.print(relativeZero2);
              delay(display_delay);
            }
          }else{
            myFile.close();
            error = PARAMETERS_RELATIVE_ZERO_2_PATH_FAILURE;
            errorHandler();
          }
          myFile.close();
        }
        error = NO_ERRORS;
      }else{
        error = SD_NOT_BEGINNED;
        errorHandler();
        return;
      }
    }else{
      error = SD_PROTECTED;
      errorHandler();
      return;
    }
  }else{
    error = SD_NOT_PRESENT;
    errorHandler();
    return;
  }

  LCD_display.clear();
  LCD_display.setCursor(2, 0);
  LCD_display.print("[SYSTEM  OK]");
  myFile.close();

}


/* -------------------------------------------------- BLUETOOTH CONFIGURATION: */
void bluetoothConfig(){
  
  LCD_display.clear();
  LCD_display.setCursor(2, 0);
  LCD_display.print("[BT CONFIG]");

  const uint16_t BTbootStrapDelay = 1000;
  const uint16_t BTresetDelay = 3000;

  uint8_t stringsSize = 40;
  char stringArray[stringsSize];
  char ATresponse[stringsSize];

  for(uint8_t i = 0; i < stringsSize; i++){
    stringArray[i] = 0;
  }
  for(uint8_t i = 0; i < stringsSize; i++){
    ATresponse[i] = 0;
  }
  
  char ATquery[3] = "AT";
  char ATsetName[9] = "AT+NAME=";
  char ATsetRole[10] = "AT+ROLE=1";
  char ATsetUART[18] = "AT+UART=9600,0,0,";
  char ATendCommunication[] = "\r\n";


  timer ATwatchdogTimer = timer();
  uint16_t watchdogTime = 5000;
  bool ATsuccess = false;

  
/* -------------------------------------------------- SERIAL INITIALIZATION: */
  SERIAL_PORT.begin(SERIAL_AT_MODE_BAUDRATE);
  delay(SERIAL_DELAY);

  digitalWrite(BT_power, LOW);
  delay(BTresetDelay);
  digitalWrite(BT_EN, HIGH);
  delay(BTbootStrapDelay);
  digitalWrite(BT_power, HIGH);

  LCD_display.setCursor(2, 0);
  LCD_display.print("[BT RESTART]");
  
  for(uint8_t i = 0; i < 16; i++){
    LCD_display.setCursor(i, 1);
    LCD_display.write(1);
    delay(625);
  }

  LCD_display.clear();
  LCD_display.setCursor(3, 0);
  LCD_display.print("[AT  MODE]");
  LCD_display.setCursor(1, 1);
  LCD_display.print("PROGRAMMING...");

/* -------------------------------------------------- BLUETOOTH START COMMUNICATION: */
  strcat(stringArray, ATquery);
  strcat(stringArray, ATendCommunication);
  SERIAL_PORT.write(stringArray);
  delay(5000);

  ATwatchdogTimer.setTimer(watchdogTime);
  uint8_t ATresponseIndex = 0;
  while(!ATwatchdogTimer.timerFIRED()){
    while(SERIAL_PORT.available()){
      char serialInput = SERIAL_PORT.read();
      if(isPrintable(serialInput)){
        ATresponse[ATresponseIndex] = serialInput;
        ATresponse[++ATresponseIndex] = 0;
      }
    }
    if(strlen(ATresponse) > 0){
      ATsuccess = true;
    }

    /*
    if(strcmp(ATresponse, "OK") == 0){
      ATsuccess = true;
    }
    */
  }
  if(!ATsuccess){
    error = BT_NOT_RESPONSE;
    errorHandler();
  }
  ATsuccess = false;

  for(uint8_t i = 0; i < stringsSize; i++){
    stringArray[i] = 0;
  }
  for(uint8_t i = 0; i < stringsSize; i++){
    ATresponse[i] = 0;
  }

/* -------------------------------------------------- BLUETOOTH SET NAME: */
  strcat(stringArray, ATsetName);
  strcat(stringArray, DEVICE_NAME);
  strcat(stringArray, ATendCommunication);
  SERIAL_PORT.write(stringArray);

  for(uint8_t i = 0; i < stringsSize; i++){
    stringArray[i] = 0;
  }

/* -------------------------------------------------- BLUETOOTH SET ROLE: */
  strcat(stringArray, ATsetRole);
  strcat(stringArray, ATendCommunication);
  SERIAL_PORT.write(stringArray);

  for(uint8_t i = 0; i < stringsSize; i++){
    stringArray[i] = 0;
  }

/* -------------------------------------------------- BLUETOOTH SET UART: */
  strcat(stringArray, ATsetUART);
  strcat(stringArray, ATendCommunication);
  SERIAL_PORT.write(stringArray);

  for(uint8_t i = 0; i < stringsSize; i++){
    stringArray[i] = 0;
  }

  LCD_display.setCursor(0, 1);
  LCD_display.print("BT config OK...");
  delay(3000);
  LCD_display.clear();
  
  digitalWrite(BT_power, LOW);
  digitalWrite(BT_EN, LOW);
  
  LCD_display.setCursor(2, 0);
  LCD_display.print("[BT RESTART]");
  
  for(uint8_t i = 0; i < 16; i++){
    LCD_display.setCursor(i, 1);
    LCD_display.write(1);
    delay(625);
  }

  LCD_display.clear();
  LCD_display.setCursor(4, 0);
  LCD_display.print("[BT OK]");
  
  digitalWrite(BT_power, HIGH);
  delay(3000);
  SERIAL_PORT.begin(SERIAL_BAUDRATE);

  LCD_display.clear();
}


/* -------------------------------------------------- RTC SET TIME: */
void getDateTime(){
  bool dateIsOK = false;
  while(!dateIsOK){

    while(SERIAL_PORT.available()){
      SERIAL_PORT.read();
    }
    uint8_t variablesDone = 0;
    
    const uint8_t dateTimeLength = 14;
    char dateTime[dateTimeLength];

    for(uint8_t i = 0; i < dateTimeLength; i++){
      dateTime[i] = 0;
    }
    uint8_t dateTimeIndex = 0;
    char incomingChar = 0;
    bool receivedPreamble = false;

    LCD_display.setCursor(0, 1);
    LCD_display.print("waiting conn...");

    LCD_display.setCursor(0, 1);
    while(SERIAL_PORT.available()){
      char serRead = SERIAL_PORT.read();
      LCD_display.print(serRead);
    }


/* -------------------------------------------------- WAITING DATE PREAMBLE: $: */
    while(!receivedPreamble){
      if(SERIAL_PORT.available()){
        incomingChar = SERIAL_PORT.read();
        if(incomingChar == '$')
          receivedPreamble = true;
      }

      if(digitalRead(BT_state) == HIGH){
        LCD_display.setCursor(14, 0);
        LCD_display.write(0);
      }else{
        LCD_display.setCursor(14, 0);
        LCD_display.print(' ');
      }
    }

    LCD_display.clear();
    delay(LCD_REFRESH_DELAY);


/* -------------------------------------------------- PREAMBLE RECEIVED, WAITING DATETIME: */
    while((receivedPreamble) && (dateTimeIndex < dateTimeLength)){
      incomingChar = SERIAL_PORT.read();
      if((incomingChar != '\n') && (incomingChar != '\r') && (incomingChar != '\0')){
        dateTime[dateTimeIndex] = incomingChar;
        dateTime[++dateTimeIndex] = 0;
      }
    }
  

    LCD_display.setCursor(1, 0);
    LCD_display.print("Setting Date...");
  
    char dateTimeCharArray[2];
    for(uint8_t i = 0; i < dateTimeLength; i+=2){
      dateTimeCharArray[0] = dateTime[i];
      dateTimeCharArray[1] = dateTime[i + 1];

      int dateTimeToInt;
      sscanf(dateTimeCharArray, "%d", &dateTimeToInt);

/* -------------------------------------------------- RTC SET TIME & ERROR HANDLER FUNCTION CALL: */
      switch(i){
        case 0:
          if(dateTimeToInt >= 1 && dateTimeToInt <= 31){
            RealTimeClock.setDay(dateTimeToInt);
            variablesDone++;
          }else{
            error = RTC_ERROR;
            errorHandler();
          }
          break;

        case 2:
          if(dateTimeToInt >= 1 && dateTimeToInt <= 12){
            RealTimeClock.setMonth(dateTimeToInt);
            variablesDone++;
          }else{
            error = RTC_ERROR;
            errorHandler();
          }
          break;

        case 4:
          if(dateTimeToInt >= 22 && dateTimeToInt <= 99){
            RealTimeClock.setYear(dateTimeToInt);
            variablesDone++;
          }else{
            error = RTC_ERROR;
            errorHandler();
          }
          break;

        case 6:
          if(dateTimeToInt >= 0 && dateTimeToInt <= 23){
            RealTimeClock.setHours(dateTimeToInt);
            variablesDone++;
          }else{
            error = RTC_ERROR;
            errorHandler();
          }
          break;

        case 8:
          if(dateTimeToInt >= 0 && dateTimeToInt <= 59){
            RealTimeClock.setMinutes(dateTimeToInt);
            variablesDone++;
          }else{
            error = RTC_ERROR;
            errorHandler();
          }
          break;
        
        case 10:
          if(dateTimeToInt >= 0 && dateTimeToInt <= 59){
            RealTimeClock.setSeconds(dateTimeToInt);
            variablesDone++;
          }else{
            error = RTC_ERROR;
            errorHandler();
          }
          break;
      }
    }
    if(variablesDone >= 6){
      dateIsOK = true;
    }
    LCD_display.clear();
  }
}

/* -------------------------------------------------- (EVENTS) SAVE ON SD: */
void saveOnSD(char msgToSave[40]){
  myFile = SD.open(EVENTS_PATH, FILE_WRITE);
  
  for(uint8_t dateOnSD = 0; dateOnSD < 6; dateOnSD++){
    char numToChar[3];
    
    for(uint8_t i = 0; i < 3; i++){
      numToChar[i] = 0;
    }
    
    switch(dateOnSD){
      case 0:
        sprintf(numToChar, "%02d", RealTimeClock.getDay());
        myFile.write(numToChar);
        break;

      case 1:
        sprintf(numToChar, "%02d", RealTimeClock.getMonth());
        myFile.write(numToChar);
        break;

      case 2:
        sprintf(numToChar, "%02d", RealTimeClock.getYear() - 2000);
        myFile.write(numToChar);
        break;

      case 3:
        sprintf(numToChar, "%02d", RealTimeClock.getHours());
        myFile.write(numToChar);
        break;

      case 4:
        sprintf(numToChar, "%02d", RealTimeClock.getMinutes());
        myFile.write(numToChar);
        break;

      case 5:
        sprintf(numToChar, "%02d", RealTimeClock.getSeconds());
        myFile.write(numToChar);
        break;
    }

    if(dateOnSD < 2){
      myFile.write('/');
    }else if(dateOnSD == 2){
      myFile.write("   -   ");
    }else if (dateOnSD > 2 && dateOnSD < 5){
      myFile.write(':');
    }
  }

  if(error != NO_ERRORS){
    char errorNumber[3];
    for(uint8_t i = 0; i < 3; i++){
      errorNumber[i] = 0;
    }
    sprintf(errorNumber, "%d", error);
    myFile.write("  ->  ");
    myFile.write(msgToSave);
    myFile.write("    Err: ");
    myFile.write(errorNumber);
  }else{
    myFile.write("  ->  ");
    myFile.write(msgToSave);
  }
  myFile.write("\r\n");
  myFile.close();
  
}


/* -------------------------------------------------- ERROR HANDLER: */
void errorHandler(){
  digitalWrite(RL1, LOW);
  digitalWrite(RL2, LOW);
  digitalWrite(buzzer, LOW),
  digitalWrite(redLamp, LOW),
  digitalWrite(orangeLamp, LOW),
  digitalWrite(EV, LOW);
  digitalWrite(safetyRL, LOW);

  LCD_display.on();

  const uint8_t SDstringLength = 40;
  char SDstring[SDstringLength];

  for(uint8_t i = 0; i < SDstringLength; i++){
    SDstring[i] = 0;
  }

  
  LCD_display.clear();
  LCD_display.setCursor(4, 0);
  LCD_display.print("[ERROR!]");

  switch(error){
/* -------------------------------------------------- SD NOT PRESENT ERROR HANDLING: */
    case SD_NOT_PRESENT:
      LCD_display.setCursor(2, 1);
      LCD_display.print("SD not found");
      while(digitalRead(cardDetectPin) == HIGH){}
      return;


/* -------------------------------------------------- SD PROTECTED ERROR HANDLING: */
    case SD_PROTECTED:
      LCD_display.setCursor(2, 1);
      LCD_display.print("SD protected");
      while(digitalRead(writeProtectPin) == HIGH){ }
      return;

/* -------------------------------------------------- SD NOT BEGINNED ERROR HANDLING: */
    case SD_NOT_BEGINNED:
      LCD_display.setCursor(0, 1);
      LCD_display.print("SD not beginned");
      while(!SD.begin(CS)){}
      return;


/* -------------------------------------------------- DISPLAY PATH ERROR HANDLING: */
    case DISPLAY_DELAY_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("DYDE path fail");
      //saveOnSD("DISPLAY DELAY PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- IR SENSIVITY PATH ERROR HANDLING: */
    case IR_SENSIVITY_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("IRSS path fail");
      //saveOnSD("IR SENSOR PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- EV PRE PUMP TIMER PATH ERROR HANDLING: */
    case EV_PRE_PUMP_TIME_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("EVPE path fail");
      //saveOnSD("EV PRE PUMP TIMER PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- EV POST PUMP TIMER PATH ERROR HANDLING: */
    case EV_POST_PUMP_TIMER_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("EVPT path fail");
      //saveOnSD("EV POST PUMP PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- MAX & MIN VACUUM TIMER PATH ERROR HANDLING: */
    case MAX_MIN_VACUUM_TIMER_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("MMVT path fail");
      //saveOnSD("MIN/MAX VACUUM TIMER PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- RELATIVE ZERO TIMER PATH ERROR HANDLING: */
    case RELATIVE_ZERO_TIMER_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("EVPT path fail");
      //saveOnSD("RELATIVE ZERO TIMER PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- RED ALARM RESPONSIVENESS PATH ERROR HANDLING: */
    case ALARM_DELAY_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("RDRS path fail");
      //saveOnSD("RED ARLARM RESPONSIVENESS PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- VACUUM READ START DELAY PATH ERROR HANDLING: */
    case VACUUM_READ_START_DELAY_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("VRSD path fail");
      //saveOnSD("VACUUM READ START DELAY PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- FILTER COEFFICIENT PATH ERROR HANDLING: */
    case FILTER_COEFFICIENT_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("FRCT path fail");
      //saveOnSD("FILTER COEFFICIENT PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- PUMP START MODE PATH ERROR HANDLING: */
    case PUMP_START_MODE_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("PSTM path fail");
      //saveOnSD("PUMP START MODE PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- PUMP START TIME PATH ERROR HANDLING: */
    case PUMP_START_TIME_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("PSTT path fail");
      //saveOnSD("PUMP START TIME PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- PUMP STOP TIME PATH ERROR HANDLING: */
    case PUMP_STOP_TIME_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("PSPT path fail");
      //saveOnSD("PUMP STOP TIME PATH FAILURE");
      while(true);
      break;
      

/* -------------------------------------------------- PUMP STOP TIME PATH ERROR HANDLING: */
    case VACUUM_CURVATURE_VALUES_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("VCVS path fail");
      //saveOnSD("VACUUM CURVATURE VALUES PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- DEVICE NAME PATH ERROR HANDLING: */
    case DEVICE_NAME_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("DENA path fail");
      //saveOnSD("DEVICE NAME PATH FAILURE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT DISPLAY DELAY VALUE ERROR HANDLING: */
    case INCONSISTENT_DISPLAY_DELAY_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("DYDE bad value");
      //saveOnSD("DISPLAY DELAY VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT IR SENSIVITY VALUE ERROR HANDLING: */
    case INCONSISTENT_IR_SENSIVITY_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("IRSS bad value");
      //saveOnSD("IR SENSIVITY VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT EV PRE PUMP TIMER ERROR HANDLING: */
    case INCONSISTENT_EV_PRE_PUMP_TIME_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("EVPE bad value");
      //saveOnSD("EV PRE PUMP TIMER VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT EV POST PUMP TIMER ERROR HANDLING: */
    case INCONSISTENT_EV_POST_PUMP_TIMER_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("EVPT bad value");
      //saveOnSD("EV POST PUMP TIMER VALUE OUT OF RANGE");
      while(true);
      break;
      

/* -------------------------------------------------- INCONSISTENT MAX & MIN VACUUM TIMER ERROR HANDLING: */
    case INCONSISTENT_MAX_MIN_VACUUM_TIMER_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("MMVT bad value");
      //saveOnSD("MAX/MIN VACUUM TIMER VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT RELATIVE ZERO TIMER ERROR HANDLING: */
    case INCONSISTENT_RELATIVE_ZERO_TIMER_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("RZTR bad value");
      //saveOnSD("RELATIVE ZERO TIMER VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT RED ALARM RESPONSIVENESS ERROR HANDLING: */
    case INCONSISTENT_ALARM_DELAY_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("RDRS bad value");
      //saveOnSD("RED ALARM RESPONSIVENESS VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT VACUUM READ START DELAY ERROR HANDLING: */
    case INCONSISTENT_VACUUM_READ_START_DELAY_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("VRSD bad value");
      //saveOnSD("VACUUM READ START DELAY VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT FILTER COEFFICIENT ERROR HANDLING: */
    case INCONSISTENT_FILTER_COEFFICIENT_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("FRCT bad value");
      //saveOnSD("FILTER COEFFICIENT VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT PUMP START MODE ERROR HANDLING: */
    case INCONSISTENT_PUMP_START_MODE_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("PSTM bad value");
      //saveOnSD("PUMP START MODE VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT PUMP START TIME ERROR HANDLING: */
    case INCONSISTENT_PUMP_START_TIME_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("PSTT bad value");
      //saveOnSD("PUMP START TIME VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- INCONSISTENT PUMP STOP TIME ERROR HANDLING: */
    case INCONSISTENT_PUMP_STOP_TIME_VALUE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("PSPT bad value");
      //saveOnSD("PUMP STOP TIME VALUE OUT OF RANGE");
      while(true);
      break;


/* -------------------------------------------------- MIN VACUUM 1 VALUE PATH ERROR HANDLING: */
    case PARAMETERS_MIN_VACUUM_1_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("mV1 PATH ERROR");
      //saveOnSD("VACUUM 1 MIN PATH NO SUCH FILE OR DIRECTORY");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;
      

/* -------------------------------------------------- MIN VACUUM 2 VALUE PATH ERROR HANDLING: */
  case PARAMETERS_MIN_VACUUM_2_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("mV2 PATH ERROR");
      //saveOnSD("VACUUM 2 MIN PATH NO SUCH FILE OR DIRECTORY");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;
      

/* -------------------------------------------------- MAX VACUUM 1 VALUE PATH ERROR HANDLING: */
  case PARAMETERS_MAX_VACUUM_1_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("MV1 PATH ERROR");
      //saveOnSD("VACUUM 1 MAX PATH NO SUCH FILE OR DIRECTORY");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- MAX VACUUM 2 VALUE PATH ERROR HANDLING: */
  case PARAMETERS_MAX_VACUUM_2_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("MV2 PATH ERROR");
      //saveOnSD("VACUUM 2 MAX PATH NO SUCH FILE OR DIRECTORY");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- RELATIVE ZERO 1 VALUE PATH ERROR HANDLING: */
  case PARAMETERS_RELATIVE_ZERO_1_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("RZ1 PATH ERROR");
      //saveOnSD("RELATIVE ZERO 1 VALUE PATH NO SUCH FILE OR DIRECTORY");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- RELATIVE ZERO 2 VALUE PATH ERROR HANDLING: */
  case PARAMETERS_RELATIVE_ZERO_2_PATH_FAILURE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("RZ2 PATH ERROR");
      //saveOnSD("RELATIVE ZERO 2 VALUE PATH NO SUCH FILE OR DIRECTORY");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- VACUUM 1 MIN VALUE NOT FOUND ERROR HANDLING: */
  case VACUUM_1_MIN_NOT_FOUND:
      LCD_display.setCursor(0, 1);
      LCD_display.print("mV1 NOT FOUND");
      //saveOnSD("MIN VACUUM 1 VALUE NOT FOUND");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- VACUUM 2 MIN VALUE NOT FOUND ERROR HANDLING: */
  case VACUUM_2_MIN_NOT_FOUND:
      LCD_display.setCursor(0, 1);
      LCD_display.print("mV2 NOT FOUND");
      //saveOnSD("MIN VACUUM 2 VALUE NOT FOUND");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- VACUUM 1 MAX VALUE NOT FOUND ERROR HANDLING: */
  case VACUUM_1_MAX_NOT_FOUND:
      LCD_display.setCursor(0, 1);
      LCD_display.print("MV1 NOT FOUND");
      //saveOnSD("MAX VACUUM 1 VALUE NOT FOUND");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- VACUUM 2 MAX VALUE NOT FOUND ERROR HANDLING: */
  case VACUUM_2_MAX_NOT_FOUND:
      LCD_display.setCursor(0, 1);
      LCD_display.print("MV2 NOT FOUND");
      //saveOnSD("MAX VACUUM 2 VALUE NOT FOUND");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- RELATIVE ZERO 1 NOT FOUND VALUE NOT FOUND ERROR HANDLING: */
  case RELATIVE_ZERO_1_NOT_FOUND:
      LCD_display.setCursor(0, 1);
      LCD_display.print("RZ1 NOT FOUND");
      //saveOnSD("RELATIVE ZERO 1 VALUE NOT FOUND");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- RELATIVE ZERO 2 NOT FOUND VALUE NOT FOUND ERROR HANDLING: */
  case RELATIVE_ZERO_2_NOT_FOUND:
      LCD_display.setCursor(0, 1);
      LCD_display.print("RZ2 NOT FOUND");
      //saveOnSD("RELATIVE ZERO 2 VALUE NOT FOUND");
      delay(5000);
      
      while(true){
        LCD_display.setCursor(0, 1);
        LCD_display.print("repeat FtSt");
        delay(2000);
        LCD_display.setCursor(0, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- RTC INCONSISTENT ERROR HANDLING: */
    case RTC_ERROR:
      LCD_display.setCursor(0, 1);
      LCD_display.print("Date not valid");
      //saveOnSD("RTC FAILURE");
      delay(5000);
      LCD_display.setCursor(0, 1);
      LCD_display.print("               ");
      while(true){
        LCD_display.setCursor(1, 1);
        LCD_display.print("restart system");
        delay(2000);
        LCD_display.setCursor(1, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      LCD_display.clear();
      break;


/* -------------------------------------------------- RTC INCONSISTENT ERROR HANDLING: */
    case POWER_ERROR:
      LCD_display.setCursor(0, 1);
      LCD_display.print("SHUTDOWN");
      //saveOnSD("SHUTDOWN");
      while(true);
      break;


/* -------------------------------------------------- BT FAILURE: */
    case BT_NOT_RESPONSE:
      LCD_display.setCursor(0, 1);
      LCD_display.print("BT not response");
      //saveOnSD("BLUETOOTH MODULE FAILURE");
      while(true);          // INSERIRE TENTATIVO DI RISTABILIRE CONNESSIONE IN MODALITA' AT CON MODULO BLUETOOTH
      break;


/* -------------------------------------------------- LOW VACUUM DETECTED BY SENSOR 1 ERROR HANDLING: */
    case VACUUM1_LOW_ERROR:
      LCD_display.setCursor(0, 1);
      LCD_display.print("Vacuum1 LOW");
      //saveOnSD("VACUUM 1 UNDER PRESSURE");
      while(true);
      break;


/* -------------------------------------------------- LOW VACUUM DETECTED BY SENSOR 2 ERROR HANDLING: */
    case VACUUM2_LOW_ERROR:
      LCD_display.setCursor(0, 1);
      LCD_display.print("Vacuum2 LOW");
      //saveOnSD("VACUUM 2 UNDER PRESSURE");
      while(true);
      break;


/* -------------------------------------------------- LOW VACUUM DETECTED BY SENSOR 1 & 2 ERROR HANDLING: */
    case VACUUM_1_2_LOW_ERROR:
      LCD_display.setCursor(1, 1);
      LCD_display.print("Vacuum1&2 LOW");
      delay(5000);
      LCD_display.clear();
      LCD_display.setCursor(1, 0);
      LCD_display.print("[PUMP FAILURE]");
      
      //saveOnSD("VACUUM 1 AND 2 UNDER PRESSURE");
      
      while(true){
        LCD_display.setCursor(1, 1);
        LCD_display.print("restart system");
        delay(2000);
        LCD_display.setCursor(1, 1);
        LCD_display.print("              ");
        delay(2000);
      }
      break;


/* -------------------------------------------------- HIGH VACUUM DETECTED BY SENSOR 1 ERROR HANDLING: */
    case VACUUM1_HIGH_ERROR:
      LCD_display.setCursor(1, 1);
      LCD_display.print("Vacuum1 HIGH");
      
      //saveOnSD("VACUUM 1 OVER PRESSURE");
      while(true);
      break;


/* -------------------------------------------------- HIGH VACUUM DETECTED BY SENSOR 2 ERROR HANDLING: */
    case VACUUM2_HIGH_ERROR:
      LCD_display.setCursor(1, 1);
      LCD_display.print("Vacuum2 HIGH");
      
      //saveOnSD("VACUUM 2 OVER PRESSURE");
      while(true);
      break;


/* -------------------------------------------------- HIGH VACUUM DETECTED BY SENSOR 1 & 2 (RED ALARM) ERROR HANDLING: */
    case VACUUM_1_2_HIGH_ERROR:
      //saveOnSD("RED ALARM\0");
      delay(250);
      digitalWrite(EV, HIGH);
      delay(5000);
      digitalWrite(EV, LOW);
      while(true){
        LCD_display.setCursor(1, 1);
        LCD_display.print("RED ALARM");
        delay(2000);
        LCD_display.setCursor(1, 1);
        LCD_display.print("         ");
        delay(2000);
      }
      break;
  }
  LCD_display.clear();
}

void printTwoDigits(int number){
  if(number < 10){
    LCD_display.print('0');
    LCD_display.print(number);
  }else{
    LCD_display.print(number);
  }
}

Nel codice ho commentato tutte le chiamate a funzione saveOnSD() (quella che sembrerebbe essere la causa del blocco) perchè come vengono decommentate il software si blocca.
La prima chiamata (per intenderci tra le ultime righe di codice della funzione firstStart() ) funziona perfettamente, una volta terminata la firstStart(), metto in loop infinito aspettando il riavvio, dopo il quale la SD non accetta più la scrittura.

Grazie per il momento, io intanto continuo a studiarci ancora!

[AGGIORNAMENTO]:
Sono riuscito a far funzionare la scrittura su scheda SD.
Per motivi miei ho dovuto sostituire il nome del file che ho usato nel programma con il nome "myFile", quello originale è "SwimSafeData".

Premetto che avevo già visto vari forum per quanto riguarda i problemi della lunghezza dei nomi da usare per i file (formato 8.3), mi ero letto anche dei post dove parlavano della LFN, più adatta per la scheda DUE che per altre schede come la Mega o la UNO, insomma mi ero già un po' documentato.

Ho fatto parecchi test con il nome originale del file nel mio programma (SwimSafeData) e tutto aveva funzionato perfettamente, anche nel piccolo programma che ho scritto nella risposta a @Standardoil il nome originale del file è SwimSafeData che però in quel piccolo programma funziona perfettamente.

Anche il fatto che funzionasse almeno una volta (nella fase di first start) nel programma a cui sto lavorando mi aveva fatto escludere a priori la problematica inerente alle LFN e ai nomi dei file in generale.

Mi sono deciso di provare "myFile" per assurdo, memore del problema passato che ho avuto con il nome della variabile globale, commentato nei post precedenti.
Ho risolto il problema.

Sinceramente vorrei capire meglio le nominazioni delle variabili, per evitare questi spiacevoli inconvenienti.
Ho anche intensione di studiarmi tutta la documentazione inerente alla SD, ai fileNames e alle varie problematiche dei caratteri speciali delle formattazioni FAT.

Spero di non aver fatto perdere del tempo a nessuno, ad essere sincero, come già detto, escludevo a priori il problema della LFN perchè con il nome originario ha funzionato bene almeno una volta e soprattutto funziona perfettamente almeno nella fase di first start del mio codice.

Ringrazio tutti per aver cercato di aiutarmi, se avete una spiegazione più precisa sono tutto orecchie, sono qui per imparare e, immagino un po' come in molti, ho ancora parecchia strada da fare.

Grazie di nuovo, un saluto.

non importa più di tanto, si poteva finire prima,
MA:
è stato comunque un piacere

Ringrazio tutti voi, non solo per aver cercato di aiutarmi in questo topic ma anche nei precedenti!

1 Like

Buongiorno,

riapro questo topic perché mi sono accorto, dopo molti tentativi e prove varie, che il problema era alquanto anomalo... Avevo inizialmente pensato alla memoria in primis perché sapevo dell'esorbitante quantità di questa richiesta da uno stream per l'esecuzione di operazioni su SD e poi perché mi risultava assai anomalo il fatto di aver risolto il problema semplicemente cambiando nome ad alcune variabili e all'oggetto che uso per aprire gli stream di lettura/scrittura su SD.

Escludevo però il problema della memoria, pensando che 96K disponibili sul SAM3X8E fossero un'infinità, ed invece pare proprio di no, il problema è proprio la SRAM.

Il programma ha infatti ricominciato a dare problemi da un'altra parte del codice che prima funzionava alla perfezione, senza effettuare nessuna modifica a quella parte stessa di codice.
Più precisamente la funzione che prima funzionava (passatemi il gioco di parole) perfettamente e adesso da problemi è la SDconfiguration.

Insomma, pare stessi semplicemente spostando il problema da un'altra parte, e tornerebbe perché cambiando il nome di una variabile ne viene cambiato l'indirizzo e quindi anche se la cella con l'indirizzo indicato dal vecchio identificatore viene sovrascritta, avendo spostato il contenuto in un altro indirizzo, la variabile in questione non risentiva di alcuna sovrascrittura/cancellazione.
(chissà cosa stavo andando a sovrascrivere cambiando identificatore :sweat_smile:)

A questo punto mi sono informato, non vorrei sbagliarmi, ma la MCU SAM3X8E si basa su architettura Princeton, quindi da escludere a priori la possibilità di utilizzare PROGMEM, inoltre la macro F non mi serve pressoché a niente poiché sulla seriale scrivo poco o nulla.

Una delle soluzioni che ho visto suggerire sul web è quella di utilizzare valori costanti la dove posso evitare di utilizzare variabili, in modo tale che questi non vengano caricati nella SRAM.
Su altri siti ho letto invece che le costanti vengono salvate in flash e caricate in SRAM automaticamente dallo startup code.
Insomma non è molto chiaro come funzioni.

Stavo pensando di ridurre il numero di variabili ed utilizzare un file da caricare su SD come storage per quelle che sono indispensabili ma che uso solamente una volta (intendo letteralmente una sola volta, durante il primo avvio).

Ho inoltre trovato quello che sembrerebbe essere un porting di funzioni per la memoria sul core SAM, pgmspace.h.
Questo è il link: ArduinoCore-sam/pgmspace.h at master · arduino/ArduinoCore-sam · GitHub

Se qualcuno sapesse qualche informazione in più ne sarei grato.

In questi giorni continuo a studiarci sopra, magari sul datasheet della MCU.

Ringrazio tutti.

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