Problema invio sms con GSM SHIELD

Salve allora vi spiego in breve il progetto:
Devo realizzare una sorta di scatola nera per automodelli. Il sistema deve "registare" su sd l'accelerazione con cui un automodello va a sbattere contro una certa barriera e l'ora e la data dell'impatto.Se l'impatto e' forte,inviare un sms.
Il sistema e' composto da :
ARDUINO UNO
Accelerometro ADXL 335 ANALOGICO (connesso ai pin X=A0,Y=A1, Z(non connesso perche' non mi serve),3.3V,GND )
RTC DS 1307 (I2c) Connesso ai pin (SCL A5, SDA A4,5V,GND)
GSM SHIELD CON SD CARD SLOT (BUS SPI CONDIVISO CON GSM E SD)
,questa per l'esattezza:
http://wiki.epalsite.com/index.php?title=SIM900_Quad-Band_GPRS_shield_with_Micro_SD_card_slot

In futuro dovrei aggiungere un sensore di prossimita',ma per ora lo sto "simulando" con un semplice switch.

FUNZIONAMENTO DETTAGLIATO
Il sistema e' posizionato nei pressi di una barriera,in un certo punto della pista.Se il sensore di prossimita' e' off (nel mio caso quando lo switch non e' premuto) il sistema e' in stand by.

Se l'automodello si trova ad una certa distanza dal sensore di prossimita',esso andra' su ON (tasto switch premuto) :comincia a registare i dati su sd (accelerazione di gravita',ora e data corrente) .Se andra' anche a sbattere contro la barriera e se l'accelerazione rilevata e' di una certa entita',il sistema deve anche inviare un sms,altrimenti,torna in stanby e ricomincia il LOOP.

Ho realizzato il seguente sketch:
Ma il sistema non mi invia l'sms quando i valori dell'accelerometro raggiungono o superano i valori impostati:

#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include <SPI.h>
#include "ADXL335.h"
#include <SoftwareSerial.h>
#include <MemoryFree.h>
SoftwareSerial Sim900Serial(2, 3);
ADXL335 accelerometer;

RTC_DS1307 RTC;

File Dati; // La variabile di tipo file che useremo per il log

const int chipSelect =10;

int i=0;
float ax,ay,az;

const int buttonPin = 7;     // the number of the pushbutton pin
const int ledPin =  13;      //  LED CHE INDICA CHE IL SENSORE DI PROSSIMITA' E' ATTIVO (VERDE)
const int ledSms= 5;  // LED IMPATTO  INVIO SMS (ROSSO) 

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

unsigned long time; // serve per misurare il tempo di esecuzione

void setup ()

{
  Serial.begin(115200);
  Sim900Serial.begin(115200);               // the GPRS baud rate  
  delay(500);
  
  Sim900Serial.println("AT+IPR=19200");
  delay(500);
  Sim900Serial.begin(19200);               // the GPRS baud rate   
 delay(1000);
  
  
  
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  
  // Inizializzazione LED invio SMS
  pinMode(ledSms, OUTPUT);
  
 
  Wire.begin(); // inizializziamo la libreria WIRE per usare
  RTC.begin(); //il Real Time clock basato su ds1307
  accelerometer.begin();
  
  
  if (! RTC.isrunning()) 
  
  {
    Serial.println("RTC NON STA FUNZIONANDO");
    
    //LA SEGUENTE ISTRUZIONE SERVE SOLO PER REGOLARE L'OROLOGIO.ATTIVARE SOLO SE NECESSARIO.
  //  RTC.adjust (DateTime(__DATE__, __TIME__)); //imposta ora e data
    }
    
    
    
  Serial.print("\nSto verificando la presenza della scheda..\n");
  pinMode(10, OUTPUT); // fa funzionare la sdlib
  
  if (!SD.begin(chipSelect))
  
  {
     Serial.println("SD card non trovata");
     return;
     
  }
 else 
   {
     Serial.println("Scheda inserita e funzionante");
     Serial.println();
    
   }
}
void loop ()

{
  
    Serial.print("freeMemory()=");  // Controllo per la quantita' di memoria disponibile ad ogni ciclo di LOOP
    Serial.println(freeMemory());
  
  // read the state of the pushbutton value: 
  buttonState = digitalRead(buttonPin);
  
  
  // Se il pulsante e' attivo (il pulsante simula l'attivazione di un sensore di prossimita'
  if (buttonState == HIGH) {
    
    Serial.print("freeMemory()=");
    Serial.println(freeMemory());
    
    // turn LED on:   IL LED VIENE ATTIVATO QUANDO SI PREME IL PULSANTE
    digitalWrite(ledPin, HIGH);
    
    i++;
    
  // MISURO IL TEMPO DI ESECUZIONE 
  Serial.print("Time: ");
  time = millis();
  //prints time since program started
  Serial.println(time);
  
    DateTime now = RTC.now(); // leggiamo l'ora
   accelerometer.getAcceleration(&ax,&ay,&az);
   
   // Stampa su seriale l'accelerazione di Gravita' del sensore ADXL 335
  
   Serial.print(ax,2);
   Serial.print("g");
   Serial.print(",");
   Serial.print(ay,2);
   Serial.print("g");
   Serial.print("\t");
   
  
   // // Stampa su seriale ORA E DATA
   Serial.print(now.day(), DEC);
   Serial.print('/');
   Serial.print(now.month(), DEC);
   Serial.print('/');
   Serial.print(now.year(), DEC);
   Serial.print(' ');
   Serial.print(now.hour(), DEC);
   Serial.print(':');
   Serial.print(now.minute(), DEC);
   Serial.print(':');
   Serial.print(now.second(), DEC);
   Serial.print("\n");
   
   Dati = SD.open("datalog.txt", FILE_WRITE); // apriamo il file in scrittura
  
  if (Dati)
  {

  // SCRITTURA DEI DATI DEL SENSORE SU SD
   Dati.print(ax,2);
   Dati.print("g");
   Dati.print(",");
   Dati.print(ay,2);
   Dati.print("g");
   Dati.print("\t");
 
   // SCRITTURA ORA E DATA SU SD
   Dati.print(now.day(), DEC);
   Dati.print('/');
   Dati.print(now.month(), DEC);
   Dati.print('/');
   Dati.print(now.year(), DEC);
   Dati.print(' ');
   Dati.print(now.hour(), DEC);
   Dati.print(':');
   Dati.print(now.minute(), DEC);
   Dati.print(':');
   Dati.print(now.second(), DEC);
   Dati.println(); 
   
   Dati.close();     // chiudiamo e trasferiamo su SD
   Serial.print("Dati rilevati \t");
   
  }
  else
  {
    Serial.println("Errore nell'apertura di datalog.txt");
  } 
  
  Serial.println(time);
   
   // CONDIZIONE AX,AY >N
  
  if (ax>=1 || ay>=1) {         //Se la collisione è forte
    
    if (i==5) {           //se la collisione forte dura da 5 loop
      digitalWrite(ledSms, HIGH);
      Serial.println ("Impatto avvenuto,sto inviando SMS");
      // INVIA SMS
      SendTextMessage();
      
            }
            
    }  
      else 
           { //altrimenti no fare nulla, c'è una collisione ed  è forte, 
           //ma non abbiamo ancora raggiunto 50 loop consecuutivi, OPPURE li abbiamo superati
           
   //  Spegni led INVIO SMS
        digitalWrite(ledSms, LOW);
   
       i=0;  //La collisione forte è finita o non c'è mai stata, assicurati di ricominciare a contare da 0
           }
         
         }  // Parentesi del IF PRINCIPALE
             
       
  else {
        
    i=0;//collisione finita o non presente, assicurati di ricominicare a contare da 0
    
    // Spegni il LED  VERDE :
    digitalWrite(ledPin, LOW);
    }
    delay (0);  // cadenza della scrittura dei dati
    
  }
  
 void SendTextMessage()
{
  Sim900Serial.print("AT+CMGF=1\r");    //Sending the SMS in text mode
  delay(100);
  Sim900Serial.println("AT + CMGS = \"123456789\"");//Mio numero di telefono
  delay(100);
  Sim900Serial.println("hello");//the content of the message
  delay(100);
  Sim900Serial.println((char)26);//the ASCII code of the ctrl+z is 26
  delay(100);
  Sim900Serial.println();
}

Ho provato ad inserire la chiamata SendTextMessage,quando lo switch e' su off,e in effetti i messaggi vengono inviati (a ripetizione)

 else { //altrimenti no fare nulla, c'è una collisione, è forte, ma non abbiamo ancora raggiunto 5 loop consecuutivi, OPPURE li abbiamo supertati
      digitalWrite(ledSms, LOW);
       i=0;         //La collisione forte è finita o non c'è mai stata, assicurati di ricominciare a contare da 0
           }
         
         }
             
        // Parentesi del IF PRINCIPALE
  else {
    // turn LED off:
    i=0;//collisione finita o non presente, assicurati di ricominicare a contare da 0
    
    // turn LED off:
    digitalWrite(ledPin, LOW);
    SendTextMessage(); 
      }
    delay (0);  // cadenza della scrittura dei dati
    }

Inoltre ho provato anche eseguire lo sketch escludendo:
la scrittura su SD,e l'RTC.

In caso che aggiungo l'RTC il sistema dopo un po che ho premuto il tasto SWITCH si blocca,non succede invece se escludo l'RTC dallo sketch.
Inoltre ho anche inserito la procedura per verificare la quantita' di memoria disponibile:

RTC E SD DISATTIVATI = 1367 byte FREE
SD ATTIVA, RTC DISATTIVA = 521 byte Free
SD ATTIVA e RTC ATTIVA 474 byte free (BLOCCO DEL SISTEMA SE LO SWITCH E' TENUTO PREMUTO PER UN PO DI TEMPO)

Cosa sbaglio?Grazie mille a tutti in anticipo.

devo ancora guardare bene il codice, ma esattamente quando hai verificato la ram disponibile? puoi mettere delle Serial.println() in modo da capire esattamente dove il codice si blocca?

Ciao,
banalemte hai provato i vari pezzi singolarmente prima di mettere tutto assieme?

Se vedi il codice,la ram disponibile e' verificata all'inizo del loop.Sto verificando ogni singolo componente e rifacendo i cablaggi!Forse l' RTC crea qualche problema!Ma mi sorge un dubbio,ho notato che nello stesso istante in cui i dati vengono scritti su sd,il sistema dovrebbe anche inviare l'sms.Quindi visto che la gsm shield che ho io e' simile alla Ethernet shield (cioe' ha lo slot sd on board),potrebbero esserci conflitti spi?Come faccio a fare in modo di eliminare eventualmente questi conflitti?So che dovrei fare in modo che non debbano essere attivi entrambi,ma nel mio caso come faccio,visto che per forza dovrei far funzionare contemporaneamente gsm e sd.Avrei a disposizione anche una shield SD a parte,potrebbe facilitarmi la vita?

non puoi usarli CONTEMPORANEAMENTE, anche perchè arduino fa una cosa alla volta :slight_smile:

però scusa che libreria usi? io per il tuo chip le trovo I2C, non SPI! metti il link.

in teoria la SD usa il pin 10 come CS e la RTC non lo so. SOLO UNO di questi pin deve essere ad HIGH, quello del chip che stai usando in quel momento.

Allora forse sto facendo un po di confusione. La scheda GSM che sto usando e' questa:
http://wiki.epalsite.com/index.php?title=SIM900_Quad-Band_GPRS_shield_with_Micro_SD_card_slot

Da quanto ho capito,la parte GSM e' gestita in modo "seriale":

Leggo dal link sopra
Software or Hardware UART select: Uart Selection. SIM900 GPRS shield can communicate with Arduino through the Hardware Serial port(D0/D1) or the Software Serial port(D2/D3). We can use the jumper to do the selection. The detailed signal are as following.

D0: Hardware serial RX of Arduino
D1: Hardware serial TX of Arduino
D2: Software serial RX of Arduino
D3: Software serial TX of Arduino
D7: Used as Software Power ON/OFF button for SIM900

Io sto usando nel mio sketch:
La comunicazione su SoftwareSerial (D2 e D3)

Invece l'sd,sempre della scheda GSM,comunica con arduino tramite protocollo SPI:

Micro SD card(TF card)Slot: Used with Micro SD card. Can use the jumper labeled with "SD_ENABLE" to enable or disable the SD card slot. If it is disabled, then the SD card will have no effect to the IOs(SPI port which are D10-D13)of Arduino.

Nel mio caso,la sd ha CS=10

L'RTC invece che sto utilizzando e' questo,e comunica tramite I2C (connessioni SCL= A5 SDA A4 5V GND)
http://www.suntekstore.com/goods-14006824-i2c_ds1307_real_time_clock_module_for_arduino_tiny_rtc.html

infine il sensore accelerometro e' questo:
ADXL 335

Dove X= A0 Y=A1 Z=Non l'ho connesso, Vcc=3.3V GND=GND arduino

Quindi a sto punto e' solo l'sd ad utilizzare l'spi,e quindi non c'e' conflitto?

esatto. il che fa credere ad un problema di ram.

puoi mettere delle Serial.println(); in vari punti del codice, ognuno che stama una cosa diversa, e così vedi dove si impalla?

poi in quel punto leggi la ram, e cerchiamo di capire come risolvere

Ho inserito i controlli che mi hai detto,il compilatore mi avvisa che non ha abbastanza memoria!Devo dire che ne ho messi un bel po'..
Lo sketch usa 24.134 byte (74%) dello spazio disponibile per i programmi. Il massimo è 32.256 byte.
Le variabili globali usano 2.124 byte (103%) di memoria dinamica, lasciando altri -76 byte liberi per le variabili locali. Il massimo è 2.048 byte.
processing.app.debug.RunnerException: Memoria esaurita; guarda http://www.arduino.cc/en/Guide/Troubleshooting#size per consigli su come ridurne l'utilizzo.
at processing.app.Sketch.size(Sketch.java:1680)
at processing.app.Sketch.build(Sketch.java:1590)
at processing.app.Sketch.exportApplet(Sketch.java:1611)
at processing.app.Sketch.exportApplet(Sketch.java:1597)
at processing.app.Editor$DefaultExportHandler.run(Editor.java:2397)
at java.lang.Thread.run(Unknown Source)

Ne ho tolti qualcuno,sono riuscito a compilarlo:
Lo sketch usa 23.860 byte (73%) dello spazio disponibile per i programmi. Il massimo è 32.256 byte.
Le variabili globali usano 2.032 byte (99%) di memoria dinamica, lasciando altri 16 byte liberi per le variabili locali. Il massimo è 2.048 byte.
Poca memoria disponibile, potrebbero verificarsi problemi di stabilità

infatti su seriale compaiono caratteri strani

lol, non sono i controlli ad usare la RAM, ma le variabili (se però per ogni controllo hai messo una stringa... piuttosto fai una funzione e chiamala spesso). Dobbiamo tagliare un poò di grasso dalla tuo codice, il problema è che il grosso sta DENTRO le librerie..

dovresti cercare di capire quale ti occupa tuttoquello spazio. intantopuoi recuperare un pò metterndo tutte le stringhe dentro la F(), che le salva in FLASH invece che in RAM

per esempio, invece che scrivere sempre

Serial.print("freeMemory()=");
    Serial.println(freeMemory());

puoi dichiarare char[] strFree= "freeMemory()="; e poi

Serial.print(strFree);
    Serial.println(freeMemory());

Scusami se dico qualche stupidaggine ma sono alle prime armi =( ,io non ho fatto altro che inserire questo blocco di codice ad ogni sezione rilevante dello sketch: tipo questo
Serial.print("freeMemory()=TASTO ON");
Serial.println(freeMemory());
Serial.println();

Non va bene cosi'?Quale altra libreria potrei "tagliare"? Ho fatto gia questa operazione cone la libreria GSM.H,ho utilizzato solo la parte necessaria per l'invio degli sms.Ma vorrei capire,e' un problema di codice sbagliato,oppure magari Arduino Uno non e' adatto per via della poca memoria?Per esempio se usassi Arduino MEGA o Arduino DUE?

secondo me anche qeulla dell'ADXL può essere tagliata, in oltre esistono librerie per l'sd più leggere. maprima vediamo come va così

ogni volta che dichiari una variabile, SPECIALMENTE le stringhe, stai occupando RAM. Che io sappia il compilatore NON capisce che stai scrivendo sempre la stessa cosa e quindi NON ottimizza, devi essere tu a creare UNA variabile con la scritta e poi usarla varie volte. In oltre racchiudendo le stringhe nella macro F() (esempio: F("salvata in flash"); ) sposta tutte le stringhe in flash: vedrai il compilato aumentare, ma la ram usata diminuire.

La mega ha il doppio (mi pare) di ram e falsh della UNO, la due ne ha molto di pià, ma essendo una architettura completamente diversa potrebbe non supportare tutte le librerie (esempio, lavora a 3V, se l'ADXL non funziona a 3v devi scegliere una ltro modello o fare un partitore di tensione)

Si in effetti con la libreria adxl335.h e' necessario dichiarare le variabili di tipo float: float ax,ay,az;,e da quanto ne so,occupano parecchia memoria.L'adxl335,funziona a 3.3v,quindi non ci sarebbero problemi ad usarlo con arduino DUE,tra l'altro dovrebbe arrivarmi a breve. Forse potrei farmi prestare un ARDUINO MEGA,magari potrei caricare il codice cosi' com'e' per verificare se funziona.Se fosse un problema di memoria,con arduino mega o DUE non dovrebbero esserci problemi.Tu dici che dovrebbe andare?Intanto provvedo a fare come mi hai suggerito,anzitutto snellire le librerie,e poi fare il test della memoria.Per adesso ti ringrazio per l'aiuto che mi stai dando.

guarda, secondo me taglizzando ancora puoi starci, certo è che se vuoi aggiungere qualcosa...

se non hai problemi la due è un mondo moooooolto diverso e meno frequentato, ma la sua potenza di calcolo offre molto più spazio per giocare..

sta a te

ps. i float occupano 4 byte, come 4 lettere.gli int 2, i byte/char 1.. le stringhe 1 byte per lettera + 1 per la lettera speciale "\0" di fine stringa.Gli oggetti in oltre occupano molto di più.

Credo di aver trovato (Uno) dei problemi..In pratica il delay del loop era troppo "corto" (l'avevo impostato a 0,in quanto ho necessita' che il sistema acquisisca segnali in tempi rapidissimi (decina di ms),invece la GSM shield,da come si vede nel codice seguente richiede almeno 400 ms totali per inviare un sms:

void SendTextMessage()
{
  Sim900Serial.print("AT+CMGF=1\r");    //Sending the SMS in text mode
  delay(100);
  Sim900Serial.println("AT + CMGS = \"12345677\"");//The target phone number
  delay(100);
  Sim900Serial.println("hello");//the content of the message
  delay(100);
  Sim900Serial.println((char)26);//the ASCII code of the ctrl+z is 26
  delay(100);
  Sim900Serial.println();
}

E questa differenza di "delay" eventualmente mi creava anche problema con la scrittura su SD. Infatti se imposto il delay a 0,il sistema o si blocca o non scrive su SD.

Ora ho impostato il delay del loop principale a 2 secondi,e lasciato i delay a 100 ms come si vede dallo sketch in alto.
E il sistema funziona bene.Il problema e' che per il sistema che devo realizzare 2 secondi e' un eternita'.
Dovrei fare in modo dunque di inviare l'sms,quando lo switch e' off.
In pratica dopo l'impatto,se AX O AY sono > = 1, potrei inserire una variabile di tipo boleana che va a true

Quando premo lo switch su off,se la variabile e' su true,allora invia l'sms,altrimenti rimane cosi' com'e?E' giust come ragionamento?Eventualmente come potrei modificare il codice?

Ah poi per l'invio degli sms,ho eliminato la condizione che se il valore di ax o ay era maggiore di 1,per 5 loop,allora veniva inviato l'sms.Era anche per questo che non mi inviava l'sms.
Ecco il codice funzionante,ma LENTO!

#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include <SPI.h>
#include "ADXL335.h"
#include <SoftwareSerial.h>

SoftwareSerial Sim900Serial(2, 3);
ADXL335 accelerometer;

RTC_DS1307 RTC;

File Dati; // La variabile di tipo file che useremo per il log

const int chipSelect =10;

int i=0;
float ax,ay,az;

const int buttonPin = 8;     // the number of the pushbutton pin
const int ledPin =  13;      //  LED CHE INDICA CHE IL SENSORE DI PROSSIMITA' E' ATTIVO (VERDE)
const int ledSms= 5;  // LED IMPATTO  INVIO SMS (ROSSO) 

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status


void setup ()

{
  Serial.begin(115200);
  Sim900Serial.begin(115200);               // the GPRS baud rate  
  delay(500);
  
  Sim900Serial.println("AT+IPR=19200");
  delay(500);
  Sim900Serial.begin(19200);               // the GPRS baud rate   
 delay(1000);
  
  
  
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  
  // Inizializzazione LED invio SMS
  pinMode(ledSms, OUTPUT);
  
 
  Wire.begin(); // inizializziamo la libreria WIRE per usare
  RTC.begin(); //il Real Time clock basato su ds1307
  accelerometer.begin();
  
  
  if (! RTC.isrunning()) 
  
  {
    Serial.println("RTC NON STA FUNZIONANDO");
    
    //LA SEGUENTE ISTRUZIONE SERVE SOLO PER REGOLARE L'OROLOGIO.ATTIVARE SOLO SE NECESSARIO.
  //  RTC.adjust (DateTime(__DATE__, __TIME__)); //imposta ora e data
    }
    
    
    
  Serial.print("\nSto verificando la presenza della scheda..\n");
  pinMode(10, OUTPUT); // fa funzionare la sdlib
  
  if (!SD.begin(chipSelect))
  
  {
     Serial.println("SD card non trovata");
     return;
     
  }
 else 
   {
     Serial.println("Scheda inserita e funzionante");
     Serial.println();
    
   }
}
void loop ()

{
  
  // read the state of the pushbutton value: 
  buttonState = digitalRead(buttonPin);
  
  // Se il pulsante e' attivo (il pulsante simula l'attivazione di un sensore di prossimita'
  if (buttonState == HIGH) {
    
 // turn LED on:   IL LED VIENE ATTIVATO QUANDO SI PREME IL PULSANTE
    digitalWrite(ledPin, HIGH);
    
 DateTime now = RTC.now(); // leggiamo l'ora
   accelerometer.getAcceleration(&ax,&ay,&az);
   
   // Stampa su seriale l'accelerazione di Gravita' del sensore ADXL 335
  
   Serial.print(ax,2);
   Serial.print("g");
   Serial.print(",");
   Serial.print(ay,2);
   Serial.print("g");
   Serial.print("\t");
   
  
   // // Stampa su seriale ORA E DATA
   Serial.print(now.day(), DEC);
   Serial.print('/');
   Serial.print(now.month(), DEC);
   Serial.print('/');
   Serial.print(now.year(), DEC);
   Serial.print(' ');
   Serial.print(now.hour(), DEC);
   Serial.print(':');
   Serial.print(now.minute(), DEC);
   Serial.print(':');
   Serial.print(now.second(), DEC);
   Serial.print("\n");
   
   Dati = SD.open("datalog.txt", FILE_WRITE); // apriamo il file in scrittura
  
  if (Dati)
  {

  // SCRITTURA DEI DATI DEL SENSORE SU SD
   Dati.print(ax,2);
   Dati.print("g");
   Dati.print(",");
   Dati.print(ay,2);
   Dati.print("g");
   Dati.print("\t");
 
   // SCRITTURA ORA E DATA SU SD
   Dati.print(now.day(), DEC);
   Dati.print('/');
   Dati.print(now.month(), DEC);
   Dati.print('/');
   Dati.print(now.year(), DEC);
   Dati.print(' ');
   Dati.print(now.hour(), DEC);
   Dati.print(':');
   Dati.print(now.minute(), DEC);
   Dati.print(':');
   Dati.print(now.second(), DEC);
   Dati.println(); 
   
   Dati.close();     // chiudiamo e trasferiamo su SD
   Serial.print("Dati rilevati \t");
   
  }
  else
  {
    Serial.println("Errore nell'apertura di datalog.txt");
  } 
  
  // CONDIZIONE AX,AY >N
  
 if ((ax >=1) || (ay >=1)) {         //Se la collisione è forte
  
  digitalWrite(ledSms, HIGH);
  Serial.println ("Impatto avvenuto,sto inviando SMS");
      // INVIA SMS
      Sim900Serial.print("AT+CMGF=1\r");    //Sending the SMS in text mode
  delay(100);
  Sim900Serial.println("AT + CMGS = \"3392747536\"");//The target phone number
  delay(100);
  Sim900Serial.println("Arduino impatto");//the content of the message
  delay(100);
  Sim900Serial.println((char)26);//the ASCII code of the ctrl+z is 26
  delay(100);
  Sim900Serial.println();
 }       
       
  else {
       
    // Spegni il LED  VERDE :
    digitalWrite(ledPin, LOW);
     }
    
     digitalWrite(ledPin, LOW);
   
  }
 delay (2000);  // durata del loop
 
}

immagino che queio tempi siano scritti da qualche parte, non vadano sempre e siano moltopiù piccoli, ma io opereri così:

dividerei la parte di codice che rileva l'urto, e quello che salva su SD/invia l'SMS

la parte di urto gira e fa un check completo ogni loop(), se avviene un urto salva in una variuabile il tempo in cui è avvenuto (ed altre info che ti saranno utili, e settauna flag "nuovo urto"

poi a fine loop() chiami una funzione che:
se è stato rilevato un nuovo urto, o era un esecuzione un salvataggio, allora: ogni loop esegue UNA istruzione SD o SMS (intesa come una serie di istruzioni fino al delay), semplicemente poi incrementa la variabile di "stato_salvataggio" che gli farà fare al prossimo loop l'operazione successiva.

In questo modo il salvataggio + SMS NON blocca il codice urto, PERO' se tieni i delay alti (non esegui un istruzione SD+SMS ogni loop, ma ogni tot loop per assicurarti che passi ababstanza tempo) è possibile che più urti si "sovrappongano". A te la decisione di come gestire, puoi creare una coda di TOT urti (limitata, se no sfori la ram e si impalla tutto), oppure (soluzione che cosniglio per semplicità) ignori gli urti "di mezzo", o magari li conti e mandi un alert che li racchiude.

che io sappia la SD può scrivere a piena velocità arduino, quindi mi sembra moolto strano che si impalli senza delay.