ARDUINO UNO, RTC, SD, SIM800L

Estoy realizando un proyecto usando un Arduino UNO, un modulo RTC, una SD y un SIM800L.

Funcionamiento: el contador se activa por interrupcion y almacena los datos en una SD como la fecha, hora y numero de pulsaciones, la fecha y hora puede programarse mediante la SD en caso de estar desprogramado el rtc, luego los datos almacenados en la SD se envian a un servidor FTP en una hora fijada.

Trabaje en dos partes por una parte un codigo que almacena y hace todo perfecto y por otro un codigo que envia un archivo de la SD al servidor FTP y hace todo perfecto pero al unirlos tengo inconvenientes con la memoria sram, esta usando aproximadamente un 85% y me indica que habra posiblemente inestabilidad, me gustaria compartir el codigo y ver si es posible hacer alguna mejora dado que soy de nivel bajo en programacion e hice el codigo poco a poco con la ayuda de google. Queria usar el Arduino UNO porque es mas facil luego colocar el atmega328 en una placa aparte y usarlo con bateria para bajo consumo, de usar un MEGA 2560 el consumo de bateria seria elevado y no seria viable con dos paneles solares, compre tambien un STM32F103C8T6 pero aun desconozco como usarlo. Agradeceria si pudieran ayudarme indicandome si es posible hacer mejoras que eviten tanto consumo de memoria sram, Saludos.

Codigo para obtener y registrar datos en la sd:

#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;

#include <SPI.h>
#include <SD.h>

int year;
int month;
int day;
int hour;
int minute;
int second;
int periodo=60;
int veces;
int min_registro[20],i;
volatile int sensor;
long T0=0;
File myFile;


void add0(byte numero) // imprime 2 dígitos
{
if (numero >= 0 && numero < 10)
{
myFile.print('0');
}
myFile.print(numero, DEC);
}

void alarma_registro () //Crea arreglo con los minutos para
// Registrar en la memoria
{
veces=60/periodo;
for(i=0;i<veces;i++)
{
min_registro[i]=periodo*i;
}
}

void interrupcion_sensor()
   {
       if ( millis() > T0  + 250)
          {   sensor++ ;
              T0 = millis();
          }
    }

void setup()
{
  Serial.begin(9600);
  pinMode(10, OUTPUT); 
  attachInterrupt( 0, interrupcion_sensor, FALLING);
  rtc.begin();
    
 if (!SD.begin(10)){
    
 //   Serial.println("Se ha producido un fallo al iniciar la comunicacion");
    return;
  }
//  Serial.println("Se ha iniciado la comunicacion correctamente");

  if (! rtc.isrunning())
  {
  File myFile = SD.open("cfgrtc.txt");
  if (myFile) {
//    Serial.println("abriendo cfgrtc.txt");
    while (myFile.available()) {
      year = myFile.parseInt();
      month = myFile.parseInt();
      day = myFile.parseInt();
      hour = myFile.parseInt();
      minute = myFile.parseInt();
      second = myFile.parseInt();
      myFile.close();
      rtc.adjust(DateTime(year,month,day,hour,minute,second));
//      Serial.println("datos cargados en el rtc  ");
    }
    }
  else {
    // si no abre cfgrtc.txt
//    Serial.println("error abriendo cfgrtc.txt");
  }
  }

  File myFile = SD.open("periodo.txt");
  if (myFile) {
//  Serial.println("abriendo periodo.txt");
  while (myFile.available()) {
      periodo = myFile.parseInt();
      myFile.close();
      alarma_registro ();
  }
  }
  else {
    // si no abre el periodo.txt
//    Serial.println("error abriendo periodo.txt");
  }
       
  }//FIN SETUP


void loop() 
{

DateTime now = rtc.now(); // Obtiene la fecha y hora del RTC

for (i=0;i<veces;i++)
{ 
if((now.minute()==min_registro[i]) && (now.second()==0))  // comparar la hora del RTC con el ciclo de medicion
{
SD.begin(10); // se inicializa SD por si se retiro
delay(20);
myFile = SD.open("log.txt", FILE_WRITE);
if (myFile) // Si el archivo abre escribir la hora
{
myFile.print(now.day());
myFile.print('/');
myFile.print(now.month());
myFile.print('/');
myFile.print(now.year(), DEC);
myFile.print(' ');
myFile.print(' ');
myFile.print(now.hour());
myFile.print(':');
add0(now.minute());
myFile.print(':');
add0(now.second());
myFile.print(' ');
myFile.print(' ');
myFile.print(' ');
myFile.print(sensor);
myFile.println();
myFile.close(); // cerrar archivo log.txt
Serial.println("GUARDO DATOS EN SD");
sensor=0;
}
}
}

delay(1000);
  
} // FIN LOOP*/

Codigo para enviar archivo .txt a servidor ftp

#include <SD.h>
#include <SPI.h>
#include <SoftwareSerial.h>
SoftwareSerial SIM800L(2, 3); // Declaramos los pines RX(2) y TX(3)


int8_t answer;
int data_size=0;
int aux;
int seconds=0;
int GsmDo=0;
int GPRS_IDLE_TIME=0;
int GsmStatut=0;



void setup(){
  delay(5000);
  Serial.begin(9600);
//  Serial.print("Initializing SD card...");
   pinMode(10, OUTPUT);
  
  if (!SD.begin(10)) {
//    Serial.println("initialization failed!");
    return;
  }
//  Serial.println("initialization done.");
    File myFile = SD.open("prueba.txt", FILE_READ);
    if (myFile)
//      Serial.println("prueba.txt is opened in read mode.");
  
    SIM800L.begin(9600);
    delay(3000);
    
    sendATcommand("AT", "OK", 5000);
    sendATcommand("AT+CSQ", "OK", 5000);
    while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) || sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );
    // Serial.println("GSM modem working!");
    delay(3000);
    
    sendATcommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\"", "OK", 2000);
    sendATcommand("AT+SAPBR=3,1,\"APN\",\"internet.movistar.ve\"", "OK", 2000);
        
    while (sendATcommand("AT+SAPBR=2,1", "OK", 20000) != 1);
    {
      //Serial.println("Querting Bearer 1...");
    }
    while (sendATcommand("AT+SAPBR=1,1", "OK", 20000) != 1);
    {
      //Serial.println("Opening Bearer 1...");
    }
    delay(1000);
 //   Serial.println("Setting up FTP");
    sendATcommand("AT+FTPCID=1", "OK", 2000);
    sendATcommand("AT+FTPSERV=\"xxxx\"", "OK", 2000);
    sendATcommand("AT+FTPPORT=21", "OK", 2000);
    sendATcommand("AT+FTPUN=\"xxxx\"", "OK", 2000);
    sendATcommand("AT+FTPPW=\"xxxx\"", "OK", 2000);

    sendATcommand("AT+FTPPUTNAME=\"prueba.txt\"", "OK", 2000);
    sendATcommand("AT+FTPPUTPATH=\"/\"", "OK", 2000);
    
    // waits for signal
  if (sendATcommand("AT+FTPPUT=1", "+FTPPUT: 1,1,", 30000) == 1)
            {
                data_size = 0;
                while(SIM800L.available()==0);
                aux = SIM800L.read();
                do{
                    data_size *= 10;
                    data_size += (aux-0x30);
                    while(SIM800L.available()==0);
                    aux = SIM800L.read();                      
                }while(aux != 0x0D);
                myFile = SD.open("prueba.txt");
                String XcomA = "";
                String XcomB = "";
                // archivosize += 1;
                XcomA.concat("AT+FTPPUT=2,");
                XcomA.concat(data_size);
                XcomA.concat("\"");
        
                XcomB.concat("+FTPPUT: 2,");
                XcomB.concat(data_size);
                XcomB.concat("\"");
        
                char XxcomA[XcomA.length()], XxcomB[XcomB.length()];
        
                XcomA.toCharArray(XxcomA,XcomA.length());
                XcomB.toCharArray(XxcomB,XcomB.length());
        
                if (myFile) {
                    int archivosize = myFile.size();
                    while(myFile.available()){
                        //Serial.println(archivosize);
                        
                        while(archivosize >= data_size){
                            if (sendATcommand(XxcomA,XxcomB,3000) == 1){
                            for(int d = 0; d < data_size; d++){
                                SIM800L.write(myFile.read());
                                archivosize -= 1;
                          //      Serial.print("Archive size : ");
                          //      Serial.println(archivosize);
                                }
                            }
                        }
               // Serial.print("El resto : ");
                                //Serial.println(archivosize);
                        String ScomA = "";
                        String ScomB = "";
                        ScomA.concat("AT+FTPPUT=2,");
                        ScomA.concat(archivosize);
                        ScomA.concat("\"");
                
                        ScomB.concat("+FTPPUT: 2,");
                        ScomB.concat(archivosize);
                        ScomB.concat("\"");
                
                        char CcomA[ScomA.length()], CcomB[ScomB.length()];
                
                        ScomA.toCharArray(CcomA,ScomA.length());
                        ScomB.toCharArray(CcomB,ScomB.length());
                        
                        if (sendATcommand(CcomA,CcomB,3000) == 1){
                        for(int t = 0; t < archivosize; t++){
                        SIM800L.write(myFile.read());
                       // Serial.print("Archive size : ");
                       // Serial.println(archivosize);
                        //Serial.println(t);
                        }
                        }
                    }
                      // close the file:
                      myFile.close();
                    }
                    delay(500);
                    if (sendATcommand("AT+FTPPUT=2,0", "+FTPPUT: 1,0", 30000)==1){
                        GPRS_IDLE_TIME = seconds + 10;        
                        GsmDo = 3;
                        GsmStatut = 1;
                    }
                
                }else{
                //Erreur

}}
void loop(){
    
    

}


unsigned char sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout)
{

    unsigned char x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '\0', 100);    // Initialize the string

    delay(100);

    while( SIM800L.available() > 0) SIM800L.read();    // Clean the input buffer

    SIM800L.println(ATcommand);    // Send the AT command


        x = 0;
    previous = millis();

    // this loop waits for the answer
    do{

        if(SIM800L.available() != 0){    
            response[x] = SIM800L.read();
       //     Serial.print(response[x]);
            x++;
            // check if the desired answer is in the response of the module
            if (strstr(response, expected_answer1) != NULL)    
            {
                answer = 1;
            }
        }
        // Waits for the asnwer with time out
    }
    while((answer == 0) && ((millis() - previous) < timeout));    

    return answer;
}

El segundo código me arroja estos datos de salida

Device: atmega328p
Program:   14384 bytes (43.9% Full)
(.text + .data + .bootloader)
Data:       1324 bytes (64.6% Full)
(.data + .bss + .noinit)

Yo uso Sublime Text + Platformio +DEVIOT.
son muy similares al IDE.

El IDE al compilar dice

El Sketch usa 14.434 bytes (44%) del espacio de almacenamiento de programa. El máximo es 32.256 bytes.
Las variables Globales usan 1.340 bytes (65%) de la memoria dinámica, dejando 708 bytes para las variables locales. El máximo es 2.048 bytes.

Porque hablas de 85% ?

De momento voy a empezar a ver el código para ver qué se le puede mejorar; mientras tanto te recomiendo usar esta librería en vez de la que trae para tarjetas SD.

Esa librería tiene menor "huella" en memoria que la que viene en la IDE.

El código tal como esta funciona bien, y no se en que condiciones dice que ocupa 85% de la SRAM.

85% cuando uno los dos porque necesito unir los dos, lo puse asi porque primero lo trabaje en dos partes ya colocare el codigo en su totalidad y notaran el 85%.

#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;

#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
SoftwareSerial SIM800L(2, 3); // Declaramos los pines RX(2) y TX(3)

int8_t answer;
int data_size=0;
int aux;
int seconds=0;
int GsmDo=0;
int GPRS_IDLE_TIME=0;
int GsmStatut=0;

int year;
int month;
int day;
int hour;
int minute;
int second;
int periodo=60;
int veces;
int min_registro[20],i;
volatile int sensor;
long T0=0;
File myFile;


void add0(byte numero) // imprime 2 dígitos
{
if (numero >= 0 && numero < 10)
{
myFile.print('0');
}
myFile.print(numero, DEC);
}

void alarma_registro () //Crea arreglo con los minutos para
// Registrar en la memoria
{
veces=60/periodo;
for(i=0;i<veces;i++)
{
min_registro[i]=periodo*i;
}
}

void interrupcion_sensor()
  {
      if ( millis() > T0  + 250)
         {   sensor++ ;
             T0 = millis();
         }
   }

void setup()
{
 Serial.begin(9600);
 SIM800L.begin(9600);
 delay(3000);
 
 pinMode(10, OUTPUT); 
 attachInterrupt( 0, interrupcion_sensor, FALLING);
 rtc.begin();
   
if (!SD.begin(10)){
   
//   Serial.println("Se ha producido un fallo al iniciar la comunicacion");
   
   return;
 }
 
//  Serial.println("Se ha iniciado la comunicacion correctamente");

 if (! rtc.isrunning())
 {
 File myFile = SD.open("cfgrtc.txt");
 if (myFile) {

  // Serial.println("abriendo cfgrtc.txt");
   
   while (myFile.available()) {
     year = myFile.parseInt();
     month = myFile.parseInt();
     day = myFile.parseInt();
     hour = myFile.parseInt();
     minute = myFile.parseInt();
     second = myFile.parseInt();
     myFile.close();
     rtc.adjust(DateTime(year,month,day,hour,minute,second));
   
     // Serial.println("datos cargados en el rtc  ");
     
   }
   }
 else {
   // si no abre cfgrtc.txt
   //Serial.println("error abriendo cfgrtc.txt");
 }
 }

 
 File myFile = SD.open("periodo.txt");
 if (myFile) {
   
 // Serial.println("abriendo periodo.txt");
 
 while (myFile.available()) {
     periodo = myFile.parseInt();
     myFile.close();
     alarma_registro ();
     
   }
 }
 else {
   // si no abre el periodo.txt
 //  Serial.println("error abriendo periodo.txt");
 }
      
   
 }//FIN SETUP




void loop() 
{

DateTime now = rtc.now(); // Obtiene la fecha y hora del RTC

for (i=0;i<veces;i++)
{ 
if((now.minute()==min_registro[i]) && (now.second()==0))  // comparar la hora del RTC con el ciclo de medicion
{
SD.begin(10); // se inicializa SD por si se retiro
delay(20);
myFile = SD.open("log.txt", FILE_WRITE);
if (myFile) // Si el archivo abre escribir la hora
{
myFile.print(now.day());
myFile.print('/');
myFile.print(now.month());
myFile.print('/');
myFile.print(now.year(), DEC);
myFile.print(' ');
myFile.print(' ');
myFile.print(now.hour());
myFile.print(':');
add0(now.minute());
myFile.print(':');
add0(now.second());
myFile.print(' ');
myFile.print(' ');
myFile.print(' ');
myFile.print(sensor);
myFile.println();
myFile.close(); // cerrar archivo log.txt
Serial.println("GUARDO DATOS EN SD");
sensor=0;

if((now.hour()==0) && (now.minute()==0) && (now.second()==0))
{

   File myFile = SD.open("log.txt", FILE_READ);
   if (myFile)
 //    Serial.println("log.txt is opened in read mode.");
   // GSM function
   //pinMode(onModulePin, OUTPUT);
   
   sendATcommand("AT", "OK", 5000);
   sendATcommand("AT+CSQ", "OK", 5000);
   while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) || sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );
//   Serial.println("GSM modem working!");
   delay(3000);
   
   sendATcommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\"", "OK", 2000);
   sendATcommand("AT+SAPBR=3,1,\"APN\",\"internet.movistar.ve\"", "OK", 2000);
       
   while (sendATcommand("AT+SAPBR=2,1", "OK", 20000) != 1);
   {
     //    Serial.println("Querting Bearer 1...");
   }
   while (sendATcommand("AT+SAPBR=1,1", "OK", 20000) != 1);
   {
     //    Serial.println("Opening Bearer 1...");
   }
   delay(1000);
   
   //     Serial.println("Setting up FTP");
   
   sendATcommand("AT+FTPCID=1", "OK", 2000);
   sendATcommand("AT+FTPSERV=\"xxxx\"", "OK", 2000);
   sendATcommand("AT+FTPPORT=21", "OK", 2000);
   sendATcommand("AT+FTPUN=\"xxxx\"", "OK", 2000);
   sendATcommand("AT+FTPPW=\"xxxx\"", "OK", 2000);

   sendATcommand("AT+FTPPUTNAME=\"log.txt\"", "OK", 2000);
   sendATcommand("AT+FTPPUTPATH=\"/\"", "OK", 2000);
   
   // waits for signal
 if (sendATcommand("AT+FTPPUT=1", "+FTPPUT: 1,1,", 30000) == 1)
           {
               data_size = 0;
               while(SIM800L.available()==0);
               aux = SIM800L.read();
               do{
                   data_size *= 10;
                   data_size += (aux-0x30);
                   while(SIM800L.available()==0);
                   aux = SIM800L.read();                      
               }while(aux != 0x0D);
               myFile = SD.open("log.txt");
               String XcomA = "";
               String XcomB = "";
               // archivosize += 1;
               XcomA.concat("AT+FTPPUT=2,");
               XcomA.concat(data_size);
               XcomA.concat("\"");
       
               XcomB.concat("+FTPPUT: 2,");
               XcomB.concat(data_size);
               XcomB.concat("\"");
       
               char XxcomA[XcomA.length()], XxcomB[XcomB.length()];
       
               XcomA.toCharArray(XxcomA,XcomA.length());
               XcomB.toCharArray(XxcomB,XcomB.length());
       
               if (myFile) {
                   int archivosize = myFile.size();
                   while(myFile.available()){
   
                       //Serial.println(archivosize);
                       
                       while(archivosize >= data_size){
                           if (sendATcommand(XxcomA,XxcomB,3000) == 1){
                           for(int d = 0; d < data_size; d++){
                               SIM800L.write(myFile.read());
                               archivosize -= 1;
                            
                            //   Serial.print("Archive size : ");
                            //   Serial.println(archivosize);
                            
                               }
                           }
                       }
              // Serial.print("El resto : ");
                               //Serial.println(archivosize);
                       String ScomA = "";
                       String ScomB = "";
                       ScomA.concat("AT+FTPPUT=2,");
                       ScomA.concat(archivosize);
                       ScomA.concat("\"");
               
                       ScomB.concat("+FTPPUT: 2,");
                       ScomB.concat(archivosize);
                       ScomB.concat("\"");
               
                       char CcomA[ScomA.length()], CcomB[ScomB.length()];
               
                       ScomA.toCharArray(CcomA,ScomA.length());
                       ScomB.toCharArray(CcomB,ScomB.length());
                       
                       if (sendATcommand(CcomA,CcomB,3000) == 1){
                       for(int t = 0; t < archivosize; t++){
                       SIM800L.write(myFile.read());
                      // Serial.print("Archive size : ");
                      // Serial.println(archivosize);
                       //Serial.println(t);
                       }
                       }
                   }
                     // close the file:
                     myFile.close();
                   }
                   delay(500);
                   if (sendATcommand("AT+FTPPUT=2,0", "+FTPPUT: 1,0", 30000)==1){
                    
                       //GPRS_IDLE_TIME = seconds + 10;        
                       //GsmDo = 3;
                       //GsmStatut = 1;
                   }
               
               }else{
               //Erreur

}
}
}
}
}
 
} // FIN LOOP*/
unsigned char sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout)
{

   unsigned char x=0,  answer=0;
   char response[100];
   unsigned long previous;

   memset(response, '\0', 100);    // Initialize the string

   delay(100);

   while( SIM800L.available() > 0) SIM800L.read();    // Clean the input buffer

   SIM800L.println(ATcommand);    // Send the AT command


       x = 0;
   previous = millis();

   // this loop waits for the answer
   do{

       if(SIM800L.available() != 0){    
           response[x] = SIM800L.read();
         
         //  Serial.print(response[x]);
         
           x++;
           // check if the desired answer is in the response of the module
           if (strstr(response, expected_answer1) != NULL)    
           {
               answer = 1;
           }
       }
       // Waits for the asnwer with time out
   }
   while((answer == 0) && ((millis() - previous) < timeout));    

   return answer;
}

Segun todos los foros que he leido el uso de memoria sram no debe superar el 70-75% para que funcione de forma estable, he logrado llevarlo alrededor de 76% tan solo eliminando los Serial.print. y quitando la configuracion de RTC y periodo por memoria SD.

Si logro reducir esta parte del codigo creo que podria hacerlo trabajar sin problemas:

Esta parte del codigo la consigui en el foro, permite calcular el tamaño del archivo y asi enviar 1360 byte por sesion que es el limite del SIM800L, hay partes de este codigo que me generan muchas dudas, si alguien puede ayudarme a entenderlo en su totalidad para simplificarlo y poder usarlo para enviar un archivo que tiene alrededor de 12.288 byte se lo agradeceria. :slight_smile:

data_size = 0;
                while(SIM800L.available()==0);
                aux = SIM800L.read();
                do{
                    data_size *= 10;
                    data_size += (aux-0x30);
                    while(SIM800L.available()==0);
                    aux = SIM800L.read();                      
                }while(aux != 0x0D);
                myFile = SD.open("log.txt");
                String XcomA = "";
                String XcomB = "";
                // archivosize += 1;
                XcomA.concat("AT+FTPPUT=2,");
                XcomA.concat(data_size);
                XcomA.concat("\"");
        
                XcomB.concat("+FTPPUT: 2,");
                XcomB.concat(data_size);
                XcomB.concat("\"");
        
                char XxcomA[XcomA.length()], XxcomB[XcomB.length()];
        
                XcomA.toCharArray(XxcomA,XcomA.length());
                XcomB.toCharArray(XxcomB,XcomB.length());
        
                if (myFile) {
                    int archivosize = myFile.size();
                    while(myFile.available()){
    
                        //Serial.println(archivosize);
                        
                        while(archivosize >= data_size){
                            if (sendATcommand(XxcomA,XxcomB,3000) == 1){
                            for(int d = 0; d < data_size; d++){
                                SIM800L.write(myFile.read());
                                archivosize -= 1;
                             
                             //   Serial.print("Archive size : ");
                             //   Serial.println(archivosize);
                             
                                }
                            }
                        }
               // Serial.print("il reste : ");
                                //Serial.println(archivosize);
                        String ScomA = "";
                        String ScomB = "";
                        ScomA.concat("AT+FTPPUT=2,");
                        ScomA.concat(archivosize);
                        ScomA.concat("\"");
                
                        ScomB.concat("+FTPPUT: 2,");
                        ScomB.concat(archivosize);
                        ScomB.concat("\"");
                
                        char CcomA[ScomA.length()], CcomB[ScomB.length()];
                
                        ScomA.toCharArray(CcomA,ScomA.length());
                        ScomB.toCharArray(CcomB,ScomB.length());
                        
                        if (sendATcommand(CcomA,CcomB,3000) == 1){
                        for(int t = 0; t < archivosize; t++){
                        SIM800L.write(myFile.read());
                       // Serial.print("Archive size : ");
                       // Serial.println(archivosize);
                        //Serial.println(t);
                        }
                        }
                    }
                      // close the file:
                      myFile.close();
                      SD.remove("log.txt");
                    }

Otra opcion que manejo seria usar el STM32F103C8T6 para el proyecto, me gustaria saber si amerita grandes cambios o es practicamente lo mismo.

Bien ahora si,

El Sketch usa 19.444 bytes (60%) del espacio de almacenamiento de programa. El máximo es 32.256 bytes.
Las variables Globales usan 1.675 bytes (81%) de la memoria dinámica, dejando 373 bytes para las variables locales. El máximo es 2.048 bytes.

Revisando.

Creo que el tramo mas ineficiente es este

String XcomA = "";
            String XcomB = "";
            // archivosize += 1;
            XcomA.concat("AT+FTPPUT=2,");
            XcomA.concat(data_size);
            XcomA.concat("\"");

            XcomB.concat("+FTPPUT: 2,");
            XcomB.concat(data_size);
            XcomB.concat("\"");

            char XxcomA[XcomA.length()], XxcomB[XcomB.length()];

            XcomA.toCharArray(XxcomA, XcomA.length());
            XcomB.toCharArray(XxcomB, XcomB.length());

En total las opciones que manejo serian:

1- Lograr reducir el consumo de ram por lo menos a un 70%.

2- Agregar memoria SRAM una 23K256 o 23LC1024 pero se me hace dificil conseguirla y no se si esto me de problemas con el Modulo SD.

3- Comprar un Mega2560 pero consume mas bateria y el core mini no lo consigo.

4- Utilizar el STM32F103C8T6 pero aun no lo domino bien y hay poco soporte.

5- En caso de ser posible utilizar dos atmega328 uno que realice la programacion del RTC usando la SD, guarde los datos en la SD y otro atmega328 que solo se encargue de enviar los datos de la SD al servidor FTP usando el SIM800L.

En eso acabé tratando de optimizar ambos códigos:

Primero:

#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;

#include <SdFat.h>
SdFat SD;

char registro[64];
unsigned int periodo = 60;
unsigned int veces;
unsigned int min_registro[20]; // ¿En serio necesitas tantos? Si periodo == 1, entonces necesitarás 60
volatile unsigned int sensor;
unsigned long T0 = 0;

void alarma_registro() //Crea arreglo con los minutos para
// Registrar en la memoria
{
  veces = 60 / periodo;
  for (byte i = 0; i < veces; i++)
  {
    min_registro[i] = periodo * i;
  }
}

void interrupcion_sensor()
{
  if (millis() > T0 + 250)
  { sensor++;
    T0 = millis();
  }
}

void setup()
{
  pinMode(10, OUTPUT);
  attachInterrupt(0, interrupcion_sensor, FALLING);
  rtc.begin();

  if (!SD.begin(10)) {
    return;
  }

  if (!rtc.isrunning())
  {
    File myFile = SD.open("cfgrtc.txt");
    if (myFile) {
      if (myFile.available()) {
        unsigned int year = myFile.parseInt();
        byte month = myFile.parseInt();
        byte day = myFile.parseInt();
        byte hour = myFile.parseInt();
        byte minute = myFile.parseInt();
        byte second = myFile.parseInt();
        rtc.adjust(DateTime(year, month, day, hour, minute, second));
      }
      myFile.close();
    } else {
      // si no abre cfgrtc.txt
    }
  }

  myFile = SD.open("periodo.txt");
  if (myFile) {
    if (myFile.available()) {
      periodo = myFile.parseInt();
      alarma_registro ();
    }
    myFile.close();
  }
  else {
    // si no abre el periodo.txt
  }

}//FIN SETUP


void loop()
{

  DateTime now = rtc.now(); // Obtiene la fecha y hora del RTC

  for (byte i = 0; i < veces; i++)
  {
    if ((now.minute() == min_registro[i]) && (now.second() == 0)) // comparar la hora del RTC con el ciclo de medicion
    {
      SD.begin(10); // se inicializa SD por si se retiro
      delay(20);
      File myFile = SD.open("log.txt", FILE_WRITE);
      if (myFile) // Si el archivo abre escribir la hora
      {
        detachInterrupt(0);
        sprintf(registro, "%d/%d/%d\t%d:%02d:%02d: %d", now.day(), now.month(), now.year(), now.hour(), now.minute(),
                now.second(), sensor);
        myFile.println(registro);
        myFile.close(); // cerrar archivo log.txt
        sensor = 0;
        attachInterrupt(0, interrupcion_sensor, FALLING);
      }
    }
  }

  delay(1000);

} // FIN LOOP*/

Segundo:

#include <SdFat.h>
SdFat SD;

unsigned int seconds = 0;
unsigned int GPRS_IDLE_TIME = 0;

char response[100];
char exp[16];
char comA[32];
char comB[32]

void setup() {
  delay(5000);
  Serial.begin(9600); // ¿Ya no necesitas SoftwareSerial? Usa este
  pinMode(10, OUTPUT);

  if (!SD.begin(10)) {
    return;
  }


  Serial.begin(9600);
  delay(3000);

  sendATcommand(F("AT"), F("OK"), 5000);
  sendATcommand(F("AT+CSQ"), F("OK"), 5000);
  while ( (sendATcommand(F("AT+CREG?"), F("+CREG: 0,1"), 500) || sendATcommand(F("AT+CREG?"), F("+CREG: 0,5"), 500)) == 0 );
  delay(3000);

  sendATcommand(F("AT+SAPBR=3,1,\"Contype\",\"GPRS\""), F("OK"), 2000);
  sendATcommand(F("AT+SAPBR=3,1,\"APN\",\"internet.movistar.ve\""), F("OK"), 2000);

  while (!sendATcommand(F("AT+SAPBR=2,1", F("OK")), 20000));
  while (!sendATcommand(F("AT+SAPBR=1,1"), F("OK"), 20000));

  delay(1000);
  sendATcommand(F("AT+FTPCID=1"), F("OK"), 2000);
  sendATcommand(F("AT+FTPSERV=\"xxxx\""), F("OK"), 2000);
  sendATcommand(F("AT+FTPPORT=21"), F("OK"), 2000);
  sendATcommand(F("AT+FTPUN=\"xxxx\""), F("OK"), 2000);
  sendATcommand(F("AT+FTPPW=\"xxxx\""), F("OK"), 2000);

  sendATcommand(F("AT+FTPPUTNAME=\"prueba.txt\""), F("OK"), 2000);
  sendATcommand(F("AT+FTPPUTPATH=\"/\""), F("OK"), 2000);

  // waits for signal
  if (sendATcommand(F("AT+FTPPUT=1"), F("+FTPPUT: 1,1,"), 30000))
  {
    unsigned int data_size = 0;
    while (Serial.available() == 0);
    byte aux = Serial.read();
    do {
      data_size *= 10;
      data_size += (aux - 0x30);
      while (Serial.available() == 0);
      aux = Serial.read();
    } while (aux != 0x0D);
    File myFile = SD.open("prueba.txt");
    sprintf(comA, "AT+FTPPUT=2,%lu\"", data_size);
    sprintf(comB, "+FTPPUT: 2,%lu\"", data_size);

    if (myFile) {
      unsigned long archivosize = myFile.size();
      while (myFile.available()) {

        while (archivosize >= data_size) {
          if (sendATcommand(comA, comB, 3000) == 1) {
            for (; data_size; data_size--) {
              Serial.write(myFile.read());
              archivosize--;
            }
          }
        }
        sprintf(comA, "AT+FTPPUT=2,%lu\"", archivosize);
        sprintf(comB, "+FTPPUT: 2,%lu\"", archivosize);

        if (sendATcommand(comA, comB, 3000) == 1) {
          for ( ; archivosize; archivosize--) {
            Serial.write(myFile.read());
          }
        }
      }
      // close the file:
      myFile.close();
    }
    delay(500);
    if (sendATcommand(F("AT+FTPPUT=2,0"), F("+FTPPUT: 1,0"), 30000)) {
      GPRS_IDLE_TIME = seconds + 10;
    }

  } else {
    //Erreur

  }
}
void loop() {
}


unsigned char sendATcommand(const __FlashStringHelper* ATcommand, const __FlashStringHelper* expected_answer, unsigned int timeout)
{

  unsigned char x = 0,  answer = 0;
  unsigned long previous;
  strcpy_P(exp, reinterpret_cast<PGM_P>(expected_answer));

  delay(100);

  Serial.flush();    // Clean the input buffer
  memset(response, 0, sizeof(response));
  Serial.println(ATcommand);    // Send the AT command
  previous = millis();
  
  // this loop waits for the answer
  do {

    if (Serial.available() != 0) {
      response[x] = Serial.read();
      //     Serial.print(response[x]);
      x++;
      // check if the desired answer is in the response of the module
      if (strstr(response, exp) != NULL)
      {
        answer = 1;
      }
    }
    // Waits for the asnwer with time out
  }
  while ((answer == 0) && ((millis() - previous) < timeout));

  return answer;
}

unsigned char sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout)
{

  unsigned char x = 0,  answer = 0;
  unsigned long previous;

  delay(100);

  Serial.flush();    // Clean the input buffer
  memset(response, 0, sizeof(response));
  Serial.println(ATcommand);    // Send the AT command
  previous = millis();

  // this loop waits for the answer
  do {

    if (Serial.available() != 0) {
      response[x] = Serial.read();
      //     Serial.print(response[x]);
      x++;
      // check if the desired answer is in the response of the module
      if (strstr(response, expected_answer1) != NULL)
      {
        answer = 1;
      }
    }
    // Waits for the asnwer with time out
  }
  while ((answer == 0) && ((millis() - previous) < timeout));

  return answer;
}

Si sientes que algo desapareció; posiblemente esté como variable local, global o por contexto del código no se usaba.
Además no los comprendía al 100%; por lo tanto puede que la haya liado o que la optimización no sea plena.

Bueno Lucario cayó en el mismo problema que yo al comienzo. El código no era es Lucario sino el siguiente posteado.

Muchas gracias Lucario y Surbyte por la ayuda recibida :slight_smile:

Realmente el codigo 1 no interfiere con el 2 en un sentido, funcionan por separado, pero al final van unidos en un arreglo simple para que a una determinada hora envie el .txt a un servidor como publique luego de haberlos colocado, me falta realizar el arreglo que tambien borre el .txt y me falta el el sleep para que no consuma tanta bateria.

Noto que falto File, el arreglo de las interrupciones en Loop no las comprendo muy bien.

En el periodo lo voy a fijar a 5 para que de la mayor cantidad en 24 horas.
Necesito que quede asi en la SD.

y pongo una condicion que cuando now.minute()= 0,5,10,15,20,25,30,35,40,45,50 registre en memoria el numero de pulsaciones.

Esto se repetira 12 veces:

01/01/2017 00:00:00 1000
01/01/2017 00:05:00 1000
01/01/2017 00:10:00 1000
01/01/2017 00:15:00 1000
01/01/2017 00:20:00 1000
01/01/2017 00:25:00 1000
01/01/2017 00:30:00 1000
01/01/2017 00:35:00 1000
01/01/2017 00:40:00 1000
01/01/2017 00:45:00 1000
01/01/2017 00:50:00 1000
01/01/2017 00:55:00 1000
01/01/2017 01:00:00 1000

Mas alla que se puede optimizar porque no miras este hilo STM32F103C8T6 y Arduino IDE de lightcalarmar

Lucario con el Arduino UNO el software serial se amerita con el SIM800L de lo contrario no funciona, hay que utilizar dos puertos serial, en el Mega usan dos pero no se amerita software serial porque cuenta con 3 puertos serial de hardware.

Con el codigo 2 noto que unsigned char sendATcommand esta repetido 2 veces.

me aparece este error macro "F" passed 2 arguments, but takes just 1, pero ya lo corregi era un parentesis.

me salia error con exp

char exp [16]' redeclared as different kind of symbol

y lo renombre a exp1

y ahora me indica esto

expected initializer before 'void'

Tato84:
Noto que falto File

Posiblemente esté como variable local porque solo se necesita en una única función.

Tato84:
el arreglo de las interrupciones en Loop no las comprendo muy bien.

¿Esto?

detachInterrupt(0);
sprintf(registro, "%d/%d/%d\t%d:%02d:%02d: %d", now.day(), now.month(), now.year(), now.hour(), now.minute(),
        now.second(), sensor);
myFile.println(registro);
myFile.close(); // cerrar archivo log.txt
sensor = 0;
attachInterrupt(0, interrupcion_sensor, FALLING);

Por definición significa que ya corresponde registrar el conteo. Sería inconsistente que el contador siga incrementando durante el proceso.

colocare el codigo con SdFat y el arreglo de SIM800L de antes, este consume 80%, no coloco con Macro F() xq da errores.

En este fije el periodo a 5, y las veces a 12, ya no las declare, solo deje que configure el rtc por memoria SD.

#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;

#include <SdFat.h>
SdFat SD;

#include <SoftwareSerial.h>
SoftwareSerial SIM800L(2, 3); // Declaramos los pines RX(2) y TX(3)


int8_t answer;
int data_size=0;
int aux;
int GPRS_IDLE_TIME;
int seconds;
char registro[64];
byte min_registro[12]={0,5,10,15,20,25,30,35,40,45,50,55};
volatile unsigned int sensor;
unsigned long T0 = 0;

void interrupcion_sensor()
{
  if (millis() > T0 + 250)
  { sensor++;
    T0 = millis();
  }
}

void setup()
{
  Serial.begin(9600);
  SIM800L.begin(9600);
  delay(3000);
  pinMode(10, OUTPUT);
  attachInterrupt(0, interrupcion_sensor, FALLING);
  rtc.begin();

  if (!SD.begin(10)) {
    return;
  }

  if (!rtc.isrunning())
  {
    File myFile = SD.open("cfgrtc.txt");
    if (myFile) {
      if (myFile.available()) {
        unsigned int year = myFile.parseInt();
        byte month = myFile.parseInt();
        byte day = myFile.parseInt();
        byte hour = myFile.parseInt();
        byte minute = myFile.parseInt();
        byte second = myFile.parseInt();
        rtc.adjust(DateTime(year, month, day, hour, minute, second));
      }
      myFile.close();
    } else {
      // si no abre cfgrtc.txt
    }
  }

}//FIN SETUP


void loop()
{

  DateTime now = rtc.now(); // Obtiene la fecha y hora del RTC

  for (byte i = 0; i < 11; i++)
  {
    if ((now.minute() == min_registro[i]) && (now.second() == 0)) // comparar la hora del RTC con el ciclo de medicion
    {
      SD.begin(10); // se inicializa SD por si se retiro
      delay(20);
      File myFile = SD.open("log.txt", FILE_WRITE);
      if (myFile) // Si el archivo abre escribir la hora
      {
        detachInterrupt(0);
        sprintf(registro, "%d/%d/%d\t%d:%02d:%02d: %d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(), sensor);
        myFile.println(registro);
        myFile.close(); // cerrar archivo log.txt
        sensor = 0;
        if((now.hour()==0) && (now.minute()==0) && (now.second()==0))
{

    File myFile = SD.open("log.txt", FILE_READ);
    if (myFile)
  //    Serial.println("log.txt is opened in read mode.");
    // GSM function
    //pinMode(onModulePin, OUTPUT);
    
    sendATcommand("AT", "OK", 5000);
    sendATcommand("AT+CSQ", "OK", 5000);
    while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) || sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );
 //   Serial.println("GSM modem working!");
    delay(3000);
    
    sendATcommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\"", "OK", 2000);
    sendATcommand("AT+SAPBR=3,1,\"APN\",\"internet.movistar.ve\"", "OK", 2000);
        
    while (sendATcommand("AT+SAPBR=2,1", "OK", 20000) != 1);
    {
      //    Serial.println("Querting Bearer 1...");
    }
    while (sendATcommand("AT+SAPBR=1,1", "OK", 20000) != 1);
    {
      //    Serial.println("Opening Bearer 1...");
    }
    delay(1000);
    
    //     Serial.println("Setting up FTP");
    
    sendATcommand("AT+FTPCID=1", "OK", 2000);
    sendATcommand("AT+FTPSERV=\"xxxx\"", "OK", 2000);
    sendATcommand("AT+FTPPORT=21", "OK", 2000);
    sendATcommand("AT+FTPUN=\"ld\"", "OK", 2000);
    sendATcommand("AT+FTPPW=\"xxxx\"", "OK", 2000);

    sendATcommand("AT+FTPPUTNAME=\"test.txt\"", "OK", 2000);
    sendATcommand("AT+FTPPUTPATH=\"/\"", "OK", 2000);
    
    // waits for signal
  if (sendATcommand("AT+FTPPUT=1", "+FTPPUT: 1,1,", 30000) == 1)
            {
                data_size = 0;
                while(SIM800L.available()==0);
                aux = SIM800L.read();
                do{
                    data_size *= 10;
                    data_size += (aux-0x30);
                    while(SIM800L.available()==0);
                    aux = SIM800L.read();                      
                }while(aux != 0x0D);
                myFile = SD.open("log.txt");
                String XcomA = "";
                String XcomB = "";
                // archivosize += 1;
                XcomA.concat("AT+FTPPUT=2,");
                XcomA.concat(data_size);
                XcomA.concat("\"");
        
                XcomB.concat("+FTPPUT: 2,");
                XcomB.concat(data_size);
                XcomB.concat("\"");
        
                char XxcomA[XcomA.length()], XxcomB[XcomB.length()];
        
                XcomA.toCharArray(XxcomA,XcomA.length());
                XcomB.toCharArray(XxcomB,XcomB.length());
        
                if (myFile) {
                    int archivosize = myFile.size();
                    while(myFile.available()){
    
                        //Serial.println(archivosize);
                        
                        while(archivosize >= data_size){
                            if (sendATcommand(XxcomA,XxcomB,3000) == 1){
                            for(int d = 0; d < data_size; d++){
                                SIM800L.write(myFile.read());
                                archivosize -= 1;
                             
                             //   Serial.print("Archive size : ");
                             //   Serial.println(archivosize);
                             
                                }
                            }
                        }
               // Serial.print("il reste : ");
                                //Serial.println(archivosize);
                        String ScomA = "";
                        String ScomB = "";
                        ScomA.concat("AT+FTPPUT=2,");
                        ScomA.concat(archivosize);
                        ScomA.concat("\"");
                
                        ScomB.concat("+FTPPUT: 2,");
                        ScomB.concat(archivosize);
                        ScomB.concat("\"");
                
                        char CcomA[ScomA.length()], CcomB[ScomB.length()];
                
                        ScomA.toCharArray(CcomA,ScomA.length());
                        ScomB.toCharArray(CcomB,ScomB.length());
                        
                        if (sendATcommand(CcomA,CcomB,3000) == 1){
                        for(int t = 0; t < archivosize; t++){
                        SIM800L.write(myFile.read());
                       // Serial.print("Archive size : ");
                       // Serial.println(archivosize);
                        //Serial.println(t);
                        }
                        }
                    }
                      // close the file:
                      myFile.close();
                      SD.remove("log.txt");
                    }
                   // delay(500);
                  if (sendATcommand("AT+FTPPUT=2,0", "+FTPPUT: 1,0", 30000)==1){
                     
                     GPRS_IDLE_TIME = seconds + 10;        
                     
                    }
                
                }
                //else{
                //Erreur
                //}
}
        attachInterrupt(0, interrupcion_sensor, FALLING);
      }
    }
  }

  delay(1000);

} // FIN LOOP

unsigned char sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout)
{

    unsigned char x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '\0', 100);    // Initialize the string

    delay(100);

    while( SIM800L.available() > 0) SIM800L.read();    // Clean the input buffer

    SIM800L.println(ATcommand);    // Send the AT command


        x = 0;
    previous = millis();

    // this loop waits for the answer
    do{

        if(SIM800L.available() != 0){    
            response[x] = SIM800L.read();
          
          //  Serial.print(response[x]);
          
            x++;
            // check if the desired answer is in the response of the module
            if (strstr(response, expected_answer1) != NULL)    
            {
                answer = 1;
            }
        }
        // Waits for the asnwer with time out
    }
    while((answer == 0) && ((millis() - previous) < timeout));    

    return answer;
}

Este con la SD.h me consume menos ram

#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;

#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
SoftwareSerial SIM800L(2, 3); // Declaramos los pines RX(2) y TX(3)

int8_t answer;
int data_size=0;
int aux;
int seconds=0;
int GPRS_IDLE_TIME=0;


byte year, month, day, hour, minute, second;
byte min_registro[12]={0,5,10,15,20,25,30,35,40,45,50,55};
int i;
volatile int sensor;
long T0=0;
File myFile;


void add0(byte numero) // imprime 2 dígitos
{
if (numero >= 0 && numero < 10)
{
myFile.print('0');
}
myFile.print(numero, DEC);
}


void interrupcion_sensor()
   {
       if ( millis() > T0  + 250)
          {   sensor++ ;
              T0 = millis();
          }
    }

void setup()
{
  Serial.begin(9600);
  SIM800L.begin(9600);
  delay(3000);
  
  pinMode(10, OUTPUT); 
  attachInterrupt( 0, interrupcion_sensor, FALLING);
  rtc.begin();
    
 if (!SD.begin(10)){
    
 //   Serial.println("Se ha producido un fallo al iniciar la comunicacion");
    
    return;
  }
  
//  Serial.println("Se ha iniciado la comunicacion correctamente");

  if (! rtc.isrunning())
  {
  File myFile = SD.open("cfgrtc.txt");
  if (myFile) {
 
   // Serial.println("abriendo cfgrtc.txt");
    
    while (myFile.available()) {
      year = myFile.parseInt();
      month = myFile.parseInt();
      day = myFile.parseInt();
      hour = myFile.parseInt();
      minute = myFile.parseInt();
      second = myFile.parseInt();
      myFile.close();
      rtc.adjust(DateTime(year,month,day,hour,minute,second));
    
      // Serial.println("datos cargados en el rtc  ");
      
    }
    }
  else {
    // si no abre cfgrtc.txt
    //Serial.println("error abriendo cfgrtc.txt");
  }
  }

  
  }//FIN SETUP




void loop() 
{

DateTime now = rtc.now(); // Obtiene la fecha y hora del RTC

for (i=0;i<12;i++)
{ 
if((now.minute()==min_registro[i]) && (now.second()==0))  // comparar la hora del RTC con el ciclo de medicion
{
SD.begin(10); // se inicializa SD por si se retiro
delay(20);
myFile = SD.open("log.txt", FILE_WRITE);
if (myFile) // Si el archivo abre escribir la hora
{
myFile.print(now.day());
myFile.print('/');
myFile.print(now.month());
myFile.print('/');
myFile.print(now.year(), DEC);
myFile.print(' ');
myFile.print(' ');
myFile.print(now.hour());
myFile.print(':');
add0(now.minute());
myFile.print(':');
add0(now.second());
myFile.print(' ');
myFile.print(' ');
myFile.print(' ');
myFile.print(sensor);
myFile.println();
myFile.close(); // cerrar archivo log.txt
//Serial.println("GUARDO DATOS EN SD");
sensor=0;

if((now.hour()==0) && (now.minute()==0) && (now.second()==0))
{

    File myFile = SD.open("log.txt", FILE_READ);
    if (myFile)
  //    Serial.println("log.txt is opened in read mode.");
    // GSM function
    //pinMode(onModulePin, OUTPUT);
    
    sendATcommand("AT", "OK", 5000);
    sendATcommand("AT+CSQ", "OK", 5000);
    while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) || sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );
 //   Serial.println("GSM modem working!");
    delay(3000);
    
    sendATcommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\"", "OK", 2000);
    sendATcommand("AT+SAPBR=3,1,\"APN\",\"internet.movistar.ve\"", "OK", 2000);
        
    while (sendATcommand("AT+SAPBR=2,1", "OK", 20000) != 1);
    {
      //    Serial.println("Querting Bearer 1...");
    }
    while (sendATcommand("AT+SAPBR=1,1", "OK", 20000) != 1);
    {
      //    Serial.println("Opening Bearer 1...");
    }
    delay(1000);
    
    //     Serial.println("Setting up FTP");
    
    sendATcommand("AT+FTPCID=1", "OK", 2000);
    sendATcommand("AT+FTPSERV=\"xxxx\"", "OK", 2000);
    sendATcommand("AT+FTPPORT=21", "OK", 2000);
    sendATcommand("AT+FTPUN=\"ld\"", "OK", 2000);
    sendATcommand("AT+FTPPW=\"xxxx\"", "OK", 2000);

    sendATcommand("AT+FTPPUTNAME=\"test.txt\"", "OK", 2000);
    sendATcommand("AT+FTPPUTPATH=\"/\"", "OK", 2000);
    
    // waits for signal
  if (sendATcommand("AT+FTPPUT=1", "+FTPPUT: 1,1,", 30000) == 1)
            {
                data_size = 0;
                while(SIM800L.available()==0);
                aux = SIM800L.read();
                do{
                    data_size *= 10;
                    data_size += (aux-0x30);
                    while(SIM800L.available()==0);
                    aux = SIM800L.read();                      
                }while(aux != 0x0D);
                myFile = SD.open("log.txt");
                String XcomA = "";
                String XcomB = "";
                // archivosize += 1;
                XcomA.concat("AT+FTPPUT=2,");
                XcomA.concat(data_size);
                XcomA.concat("\"");
        
                XcomB.concat("+FTPPUT: 2,");
                XcomB.concat(data_size);
                XcomB.concat("\"");
        
                char XxcomA[XcomA.length()], XxcomB[XcomB.length()];
        
                XcomA.toCharArray(XxcomA,XcomA.length());
                XcomB.toCharArray(XxcomB,XcomB.length());
        
                if (myFile) {
                    int archivosize = myFile.size();
                    while(myFile.available()){
    
                        //Serial.println(archivosize);
                        
                        while(archivosize >= data_size){
                            if (sendATcommand(XxcomA,XxcomB,3000) == 1){
                            for(int d = 0; d < data_size; d++){
                                SIM800L.write(myFile.read());
                                archivosize -= 1;
                             
                             //   Serial.print("Archive size : ");
                             //   Serial.println(archivosize);
                             
                                }
                            }
                        }
               // Serial.print("il reste : ");
                                //Serial.println(archivosize);
                        String ScomA = "";
                        String ScomB = "";
                        ScomA.concat("AT+FTPPUT=2,");
                        ScomA.concat(archivosize);
                        ScomA.concat("\"");
                
                        ScomB.concat("+FTPPUT: 2,");
                        ScomB.concat(archivosize);
                        ScomB.concat("\"");
                
                        char CcomA[ScomA.length()], CcomB[ScomB.length()];
                
                        ScomA.toCharArray(CcomA,ScomA.length());
                        ScomB.toCharArray(CcomB,ScomB.length());
                        
                        if (sendATcommand(CcomA,CcomB,3000) == 1){
                        for(int t = 0; t < archivosize; t++){
                        SIM800L.write(myFile.read());
                       // Serial.print("Archive size : ");
                       // Serial.println(archivosize);
                        //Serial.println(t);
                        }
                        }
                    }
                      // close the file:
                      myFile.close();
                      SD.remove("log.txt");
                    }
                   // delay(500);
                  if (sendATcommand("AT+FTPPUT=2,0", "+FTPPUT: 1,0", 30000)==1){
                  GPRS_IDLE_TIME = seconds + 10;        
                  }               
                 }
                //else{
                //Error
                //}
}
}
}
}
  
} // FIN LOOP*/


unsigned char sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout)
{

    unsigned char x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '\0', 100);    // Initialize the string

    delay(100);

    while( SIM800L.available() > 0) SIM800L.read();    // Clean the input buffer

    SIM800L.println(ATcommand);    // Send the AT command


        x = 0;
    previous = millis();

    // this loop waits for the answer
    do{

        if(SIM800L.available() != 0){    
            response[x] = SIM800L.read();
          
          //  Serial.print(response[x]);
          
            x++;
            // check if the desired answer is in the response of the module
            if (strstr(response, expected_answer1) != NULL)    
            {
                answer = 1;
            }
        }
        // Waits for the asnwer with time out
    }
    while((answer == 0) && ((millis() - previous) < timeout));    

    return answer;
}

Si esta parte del codigo funcionara bien creo que el ahorro de ram seria significativo :slight_smile:

sendATcommand(F("AT"), F("OK"), 5000);
  sendATcommand(F("AT+CSQ"), F("OK"), 5000);
  while ( (sendATcommand(F("AT+CREG?"), F("+CREG: 0,1"), 500) || sendATcommand(F("AT+CREG?"), F("+CREG: 0,5"), 500)) == 0 );
  delay(3000);

  sendATcommand(F("AT+SAPBR=3,1,\"Contype\",\"GPRS\""), F("OK"), 2000);
  sendATcommand(F("AT+SAPBR=3,1,\"APN\",\"internet.movistar.ve\""), F("OK"), 2000);

  while (!sendATcommand(F("AT+SAPBR=2,1", F("OK")), 20000));
  while (!sendATcommand(F("AT+SAPBR=1,1"), F("OK"), 20000));

  delay(1000);
  sendATcommand(F("AT+FTPCID=1"), F("OK"), 2000);
  sendATcommand(F("AT+FTPSERV=\"xxxx\""), F("OK"), 2000);
  sendATcommand(F("AT+FTPPORT=21"), F("OK"), 2000);
  sendATcommand(F("AT+FTPUN=\"xxxx\""), F("OK"), 2000);
  sendATcommand(F("AT+FTPPW=\"xxxx\""), F("OK"), 2000);

  sendATcommand(F("AT+FTPPUTNAME=\"prueba.txt\""), F("OK"), 2000);
  sendATcommand(F("AT+FTPPUTPATH=\"/\""), F("OK"), 2000);

  // waits for signal
  if (sendATcommand(F("AT+FTPPUT=1"), F("+FTPPUT: 1,1,"), 30000))
  {
    unsigned int data_size = 0;
    while (Serial.available() == 0);
    byte aux = Serial.read();
    do {
      data_size *= 10;
      data_size += (aux - 0x30);
      while (Serial.available() == 0);
      aux = Serial.read();
    } while (aux != 0x0D);
    File myFile = SD.open("prueba.txt");
    sprintf(comA, "AT+FTPPUT=2,%lu\"", data_size);
    sprintf(comB, "+FTPPUT: 2,%lu\"", data_size);

    if (myFile) {
      unsigned long archivosize = myFile.size();
      while (myFile.available()) {

        while (archivosize >= data_size) {
          if (sendATcommand(comA, comB, 3000) == 1) {
            for (; data_size; data_size--) {
              Serial.write(myFile.read());
              archivosize--;
            }
          }
        }
        sprintf(comA, "AT+FTPPUT=2,%lu\"", archivosize);
        sprintf(comB, "+FTPPUT: 2,%lu\"", archivosize);

        if (sendATcommand(comA, comB, 3000) == 1) {
          for ( ; archivosize; archivosize--) {
            Serial.write(myFile.read());
          }
        }
      }
      // close the file:
      myFile.close();
    }
    delay(500);
    if (sendATcommand(F("AT+FTPPUT=2,0"), F("+FTPPUT: 1,0"), 30000)) {
      GPRS_IDLE_TIME = seconds + 10;
    }

  } else {
    //Erreur

  }
}
void loop() {
}


unsigned char sendATcommand(const __FlashStringHelper* ATcommand, const __FlashStringHelper* expected_answer, unsigned int timeout)
{

  unsigned char x = 0,  answer = 0;
  unsigned long previous;
  strcpy_P(exp, reinterpret_cast<PGM_P>(expected_answer));

  delay(100);

  Serial.flush();    // Clean the input buffer
  memset(response, 0, sizeof(response));
  Serial.println(ATcommand);    // Send the AT command
  previous = millis();
  
  // this loop waits for the answer
  do {

    if (Serial.available() != 0) {
      response[x] = Serial.read();
      //     Serial.print(response[x]);
      x++;
      // check if the desired answer is in the response of the module
      if (strstr(response, exp) != NULL)
      {
        answer = 1;
      }
    }
    // Waits for the asnwer with time out
  }
  while ((answer == 0) && ((millis() - previous) < timeout));

  return answer;
}

unsigned char sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout)
{

  unsigned char x = 0,  answer = 0;
  unsigned long previous;

  delay(100);

  Serial.flush();    // Clean the input buffer
  memset(response, 0, sizeof(response));
  Serial.println(ATcommand);    // Send the AT command
  previous = millis();

  // this loop waits for the answer
  do {

    if (Serial.available() != 0) {
      response[x] = Serial.read();
      //     Serial.print(response[x]);
      x++;
      // check if the desired answer is in the response of the module
      if (strstr(response, expected_answer1) != NULL)
      {
        answer = 1;
      }
    }
    // Waits for the asnwer with time out
  }
  while ((answer == 0) && ((millis() - previous) < timeout));

  return answer;
}