How to upload an image (200KB) from SDcard to FTP server using sim800/sim900

I have a proyect to upload an imagen stored into a SDcard to a FTP server using a GPRS modem like sim800 or sim900.

I made a code that can upload files and I did some test and my experience is as follows:

  • A "text1.txt" (47 bytes) file with a single line of simple characters: It Works (same size) :sunglasses:
  • A "text2.txt" (2061 bytes) file with a many lines of simple characters: It works (same size) :sunglasses:
  • A "text3.text" (57 bytes) file with a single line of symbols characters: It works (same size) :sunglasses:
  • A "word.doc" (12649 bytes) file with a single line of simple characters: Corrupt file into FTP server (same size) :sob:
  • A "flower.jpg" (4643 bytes) file with a single line of simple characters: Corrupt file into FTP server (same size) :sob:

The code that I use is as follows:

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

char* file_name1 = "text1.txt";
char char_buffer;
String string_buffer = "";
int buffer_space = 1000;
File File1;

void setup() {
Serial.begin(19200);
Serial3.begin(19200);
pinMode(53, OUTPUT);

if (!SD.begin(53)) {
Serial.println("Initialization failed!");
return;
while(true);
}else {
Serial.println("Initialization done.");
}

File1 = SD.open(file_name1);
if (File1) {
Serial.println("Opening the file: " + String(file_name1) + " done.");
}else {
Serial.println("Error opening " + String(file_name1));
while(true);
}

Serial.println("Starting...");
pinMode(7,OUTPUT); //Reset pin of a sim800L
digitalWrite(7, HIGH);

Serial.println("Starting...");
gprs_modem_function ();
Serial.println("The end...");
}

void loop() {
// put your main code here, to run repeatedly:
}

byte gprs_modem_function (){
byte reply = 1;
int i = 0;
while (i < 10 && reply == 1){ //Try 10 times...
reply = sendATcommand("AT+CREG?","+CREG: 0,1","ERROR", 1000);
i++;
delay(1000);
}
if (reply == 0){
reply = sendATcommand("AT+SAPBR=3,1,"Contype","GPRS"","OK","ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+SAPBR=3,1,"APN","imovil.entelpcs.cl"", "OK", "ERROR", 1000);
if (reply == 0){
//reply = sendATcommand("AT+SAPBR=3,1,"USER","entelpcs"", "OK", "ERROR", 1000);
if (reply == 0){
//reply = sendATcommand("AT+SAPBR=3,1,"PWD","entelpcs"", "OK", "ERROR", 1000);
if (reply == 0){
reply = 2;
i = 0;
while (i < 3 && reply == 2){ //Try 3 times...
reply = sendATcommand("AT+SAPBR=1,1", "OK", "ERROR", 10000);
if (reply == 2){
sendATcommand("AT+SAPBR=0,1", "OK", "ERROR", 10000);
}
i++;
}
if (reply == 0){
reply = sendATcommand("AT+SAPBR=2,1", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPCID=1", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPSERV="ftp.xxx.com"", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPPORT=21", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPUN="monkey"", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPPW="banana"", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPPUTNAME="" + String(file_name1) + """, "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPPUTPATH="/"", "OK", "ERROR", 1000);
if (reply == 0){
unsigned int ptime = millis();
reply = sendATcommand("AT+FTPPUT=1", "+FTPPUT: 1,1", "+FTPPUT: 1,6", 60000);
Serial.println("Time: " + String(millis() - ptime));
if (reply == 0){
if (File1) {
int i = 0;
while (File1.available()>0) {
char_buffer = File1.read();
string_buffer.concat(char_buffer);
i++;
if (i == buffer_space) {
sendATcommand("AT+FTPPUT=2," + String(buffer_space), "AT+FTPPUT=2,10", "ERROR", 1000);
sendATcommand(string_buffer, "OK", "ERROR", 5000);
string_buffer = "";
i = 0;
}
}
if (string_buffer != ""){
sendATcommand("AT+FTPPUT=2," + String(i), "AT+FTPPUT=2,10", "ERROR", 1000);
sendATcommand(string_buffer, "OK", "ERROR", 5000);
sendATcommand("AT+FTPPUT=2,0", "OK", "ERROR", 1000);
}
File1.close();
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return reply;
}

byte sendATcommand(String ATcommand, String answer1, String answer2, unsigned int timeout){
byte reply = 1;
String content = "";
char character;

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

//Send the atcommand to the modem
Serial3.println(ATcommand);
delay(100);
unsigned int timeprevious = millis();
while((reply == 1) && ((millis() - timeprevious) < timeout)){
while(Serial3.available()>0) {
character = Serial3.read();
content.concat(character);
Serial.print(character);
delay(10);
}
//Stop reading conditions
if (content.indexOf(answer1) != -1){
reply = 0;
}else if(content.indexOf(answer2) != -1){
reply = 2;
}else{
//Nothing to do...
}
}
return reply;
}

I hope someone can help me...

char char_buffer;

A one element buffer. How useful is that?

Which Arduino are you using? Only a fool thinks that a 1000 character String and File will operate together on a Uno.

I'm using Arduino mega 2560.

Currently I solved my problem :slight_smile:

ctorregrosa:
I'm using Arduino mega 2560.

Currently I solved my problem :slight_smile:

What was the problem with the larger files? thanks!

Hello, I need Help please!! , I have the same situation here I am trying to send a e-mail with a jpg attachment, but the file arrives corrupt, How do you solve the problem? I am working on DUE.

I send a 992 byte picture as test test.jpg, but when i see the attachment apear with 158 bytes test(1).jpg

answer from sim800c:

AT+CGMI

SIMCOM_Ltd

OK
AT+CGMM

SIMCOM_SIM800C

OK
AT+CGMR

Revision:1418B03SIM800C24

OK
AT+CGSN

866104028015405

OK
AT+SAPBR=3,1,"Contype","GPRS"

+++++++
AT+SAPBR=3,1,"Contype","GPRS"

OK
+++++++
AT+SAPBR=3,1,"APN","wap.tmovil.cl"

+++++++
AT+SAPBR=3,1,"APN","wap.tmovil.cl"

OK
+++++++
AT+SAPBR=3,1,"USER","wap"

+++++++
AT+SAPBR=3,1,"USER","wap"

OK
+++++++
AT+SAPBR=3,1,"PWD","wap"

+++++++
AT+SAPBR=3,1,"PWD","wap"

OK
+++++++
AT+SAPBR=1,1

+++++++
AT+SAPBR=1,1

OK
+++++++
AT+SAPBR=2,1

+++++++
AT+SAPBR=2,1

+SAPBR:
+++++++
SET BearerEmail OK
AT+EMAILCID=1

+++++++
AT+EMAILCID=1

OK
+++++++
AT+EMAILTO=100

+++++++
AT+EMAILTO=100

OK
+++++++
AT+EMAILSSL=1

+++++++
AT+EMAILSSL=1

OK
+++++++
AT+SMTPSRV="smtp.gmail.com"
+++++++
AT+SMTPSRV="smtp.gmail.com"

OK
+++++++
AT+SMTPAUTH=1,"*****","****"

+++++++
AT+SMTPAUTH=1,"*****","****"

OK
+++++++
AT+SMTPFROM="*******","*****"

+++++++
AT+SMTPFROM="",""

OK
+++++++
AT+SMTPRCPT=0,0,"*****@hotmail.com","****"

+++++++
AT+SMTPRCPT=0,0,"*****@hotmail.com","****"

OK
+++++++
AT+SMTPSUB="PRUEBA ENVIO DESDE GMAIL"

+++++++
AT+SMTPSUB="PRUEBA ENVIO DESDE GMAIL"

OK
+++++++
AT+SMTPBODY=21

+++++++
AT+SMTPBODY=21

DOWNLOAD
+++++++
prueba de attachment.......??

+++++++

OK
+++++++
AT+SMTPFILE=2,"test.jpg",1

+++++++
AT+SMTPFILE=2,"test.jpg",1

OK
+++++++
AT+SMTPSEND

+++++++
AT+SMTPSEND

OK
+++++++
+++++++

+SMTPFT:
+++++++
AT+SMTPFT=992

+++++++
AT+SMTPFT=992

+SMTPFT: 2,
+++++++
+++++++

OK
+++++++
AT+SMTPFT=0

+++++++
AT+SMTPFT=0

OK
+++++++
+++++++

+SMTPSEND: 1
+++++++
AT+SAPBR=0,1

+++++++
AT+SAPBR=0,1

OK
+++++++
SET close bearer OK
setting ok


//uploading picture

//________PASO 14
if(paso==14)
{ delay(50);
answer=0;
//*envio imagen en buffer
dataFile=SD.open("test.jpg");
i=0;
if(dataFile)
{
while(dataFile.available())
{
data=dataFile.read();

//int buffer =dataFile.read();
Serial1.write(data);
//Serial1.write(dataFile.read());

/*
if(data<0x10) SerialUSB.print("0");
SerialUSB.print(data,HEX);
i++;
if((i%40)==0) SerialUSB.println();
*/

}
dataFile.close();
}
else
{
SerialUSB.println("error opening test.jpg");
}

answer=receiveATcommand("OK",10000); // tal vez hay que cerrar no mas

if(answer==0){
paso=15;
}
else{paso=15; retry=0;}

} //fin if paso

test.jpg

test (1).jpg|0x0

ctorregrosa, Why it's so difficult to say how you solved the problem?

Ok, I had the same problem with big files and ctorregrosa wouldn't share the solution with us. So I read in this Forum and with different input's from this forum I get to this solution who is working for me. I'm using a Mega 2560.

#include <SD.h>

#define csSD 5

bool debug = 1;
bool roaming = false;
char* file_name = /*"Filename"*/;
File dataFile;
File dataFileCopy;
const int Sim900PowerPin = 46;
String apn_name = /*"apn_name"*/;
String apn_username = ""; //not tested
String apn_password = ""; //not tested
String ftp = /*"ftp adress*/";
String ftp_user = /*"ftp username"*/;
String ftp_password = /*"ftp password*/";

void setup() {
  if (debug) {Serial.begin(19200);}
  Serial3.begin(19200);
  pinMode(csSD, OUTPUT);

  //init SD Card
  byte answer = 0;
  int i = 0;
  while (i < 5 && answer == 0) {
    if (!SD.begin(csSD)) {
      if (debug) {Serial.println("SD Card initialization failed!");}
      i++;
      delay(500);
    }
    else {
      if (debug) {Serial.println("SD Card initialization done.");}
      answer = 1;
    }
  }
  if (answer == 0) {/*Send SMS that init SD Card is failed*/}
  //done init SD card

  //check if file arivle
  else if(answer == 1) {answer = checkFile();}
  if (answer == 0) {/*Send SMS that file is not avriable*/}

  //GPRS part
  else if(answer == 1) {answer = powerUp_Sim900();}
  if (answer == 0) {/*Send SMS that powerUP is failed*/}
  else if (answer == 1) {delay(20000); answer = initSim900();} //Delay to let startuo the SIM900 Module
  if (debug) {Serial.println("--- Answer initSim900: " + String(answer));}
  if (answer == 0) {/*Send SMS that Sim900 init failed*/}
  else if (answer == 1) {answer = initSim900FTP();}
  if (debug) {Serial.println("--- Answer initSim900FTP: " + String(answer));}
  if (answer == 0) {/*Send SMS that Sim900FTP init failed*/}
  else if (answer == 1) {answer = Sim900FTPSend();}
  if (debug) {Serial.println("--- Answer Sim900FTPSend: " + String(answer));}
  if (answer == 0) {/*Send SMS that Sim900FTPSend failed*/}
}

void loop() {
  
}

byte initSim900() {
  byte answer = 0;
  int i = 0;
  while (i < 10 && answer == 0){
    answer = sendATcommand("AT+CREG?","+CREG: 0,1", 1000);
    i++;
    delay(1000);
  }
  if (roaming and answer == 0) {
    while (i < 20 && answer == 0){
      answer = sendATcommand("AT+CREG?","+CREG: 0,5", 1000);
      i++;
      delay(1000);
    }
  }
  if (answer == 1){answer = sendATcommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\"","OK", 1000);}
  String com = "AT+SAPBR=3,1,\"APN\",\"" + apn_name + "\"";
  if (answer == 1){answer = sendATcommand(string2char(com), "OK", 1000);}
  /*if (apn_username!= "") {
    com = "AT+SAPBR=3,1,\"USER\",\"" + apn_username + "\"";
    if (answer == 1){answer = sendATcommand(string2char(com), "OK", 1000);};
    if (apn_password != "") {
      com = "AT+SAPBR=3,1,\"PWD\",\"" + apn_password + "\"";
      if (answer == 1){answer = sendATcommand(string2char(com), "OK", 1000);}
    }
  }*/
  if (answer == 1){
    answer = 0;
    i = 0;
    while (i < 3 && answer == 0){
      answer = sendATcommand("AT+SAPBR=1,1", "OK", 10000);
      if (answer == 0){sendATcommand("AT+SAPBR=0,1", "OK", 10000);}
      i++;
    }
  }
  if (answer == 1){answer = sendATcommand("AT+SAPBR=2,1", "OK", 1000);}
  return answer;
}

byte initSim900FTP() {
  byte answer = 0;
  answer = sendATcommand("AT+FTPCID=1", "OK", 1000);
  String com = "AT+FTPSERV=\"" + ftp + "\"";
  if (answer == 1){answer = sendATcommand(string2char(com), "OK", 1000);}
  if (answer == 1){answer = sendATcommand("AT+FTPPORT=21", "OK", 1000);}
  com = "AT+FTPUN=\"" + ftp_user + "\"";
  if (answer == 1){answer = sendATcommand(string2char(com), "OK", 1000);}
  com = "AT+FTPPW=\"" + ftp_password + "\"";
  if (answer == 1){answer = sendATcommand(string2char(com), "OK", 1000);}
  com = "AT+FTPPUTNAME=\"" + String(file_name) + "\"";
  if (answer == 1){answer = sendATcommand(string2char(com), "OK", 1000);}
  if (answer == 1){answer = sendATcommand("AT+FTPPUTPATH=\"/\"", "OK", 1000);}
  return answer;
}

byte Sim900FTPSend (){
  byte answer = 0;
  if (answer = sendATcommand("AT+FTPPUT=1", "+FTPPUT:1,1,", 60000) == 1) {
    int data_size = 0;
    while(Serial3.available()==0);
    char aux = Serial3.read();
    do{
      data_size *= 10;
      data_size += (aux-0x30);
      while(Serial3.available()==0);
      aux = Serial3.read();       
    } while(aux != 0x0D);
    dataFile = SD.open(file_name);
    String XcomA = "";
    String XcomB = "";
    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()];
    char XxcomB[XcomB.length()];
       
    XcomA.toCharArray(XxcomA,XcomA.length());
    XcomB.toCharArray(XxcomB,XcomB.length());
       
    if (dataFile) {
      int archivosize = dataFile.size();
      while(dataFile.available() and answer == 1){
        while(archivosize >= data_size){
          if (answer = sendATcommand(XxcomA,XxcomB,3000) == 1) {
            for(int d = 0; d < data_size; d++){
              Serial3.write(dataFile.read());
              archivosize -= 1;
            }
          }
          else {answer = 0;}
        }
        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()];
        char 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++){
            Serial3.write(dataFile.read());
          }
        }
      }
      // close the file:
      dataFile.close();
    }
    delay(500);
    if (sendATcommand("AT+FTPPUT=2,0", "+FTPPUT:1,0", 30000)==1){
      if (debug) {Serial.println("File " + String(file_name) + " uploaded..." );}
    }          
  }
  else {answer = 0;}
  return answer;
}

unsigned char sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout) {
  unsigned char x = 0;
  unsigned char answer = 0;
  char response[100];
  unsigned long previous;
  memset(response, '\0', 100);
  delay(100);
  while( Serial3.available() > 0) Serial3.read();
  Serial3.println(ATcommand);
  x = 0;
  previous = millis();
  do{
    if(Serial3.available() != 0){   
      response[x] = Serial3.read();
      x++;
      if (strstr(response, expected_answer1) != NULL) {
        answer = 1;
      }
    }
  } while((answer == 0) && ((millis() - previous) < timeout));
  if (debug) {Serial.println(response);}
  return answer;
}

byte powerUp_Sim900() {
  byte answer = 0;
  int i = 0;
  powerSim900();
  while (i < 2 && answer == 0){
    answer = sendATcommand("AT+CREG?","+CREG:", 1000);
    i++;
    delay(500);
  }
  if (answer == 0) {powerSim900();}
  i = 0;
  while (i < 2 && answer == 0){
    answer = sendATcommand("AT+CREG?","+CREG:", 1000);
    i++;
    delay(500);
  }
  return answer; //send 1 if power up
}

byte powerDown_Sim900() {
  byte answer = 0;
  int i = 0;
  powerSim900();
  while (i < 2 && answer == 0){
    answer = sendATcommand("AT+CREG?","+CREG:", 1000);
    i++;
    delay(500);
  }
  if (answer == 1) {powerSim900();}
  i = 0;
  while (i < 2 && answer == 1){
    answer = sendATcommand("AT+CREG?","+CREG:", 1000);
    i++;
    delay(500);
  }
  return answer; //send 0 if power up
}

void powerSim900() {
  pinMode(Sim900PowerPin, OUTPUT);
  digitalWrite(Sim900PowerPin,LOW);
  delay(1000);
  digitalWrite(Sim900PowerPin,HIGH);
  delay(2000);
  digitalWrite(Sim900PowerPin,LOW);
  delay(5000);
}

char* string2char(String command){
  if(command.length() != 0){
    char *p = const_cast<char*>(command.c_str());
    return p;
  }
}

byte checkFile() {
  byte answer = 0;
  if(SD.exists(file_name)) {answer = 1;}
  return answer;
}

Isnagut

1 Like

Hey @isnaugut !!
Thanks for uploading a code that works
I'm a newbie to arduino!! My project involves storing temperature sensor values in a file on an SD card and uploading that file to the FTP server. But i have one issue, if i run your code in a loop, after the 1st run, the SD Card initialization keeps failing. How do i resolve this issue ?
Thanks

Hi,
i do allmost the same as you.
I'll store some data every five minute and write them to the sd card. One a day the data will uploaded to the FTP server.
So my code is not created to rum in a loop. I think you can initialize the SD card in the setup routine and then you do not have to to this every time.

Some code from my program

void setup() {
  byte answer = 0;
  if (debug) {Serial.begin(19200);}  //Start Serial port if we are in the debug modus
  Serial3.begin(19200);              //Start Serial port for Sim900 module
  //init SD Card
  int i = 0;
  while (i < 5 && answer == 0) {
    if (!SD.begin(csSD)) {
      if (debug) {Serial.println("SD Card initialization failed!");}
      i++;
      delay(500);
    }
    else {
      if (debug) {Serial.println("SD Card initialization done.");}
      answer = 1;
    }
  }
}
void loop() {
  askTouch();
  if (interuptFlag) {
    RtcDateTime now = Rtc.GetDateTime();
    if (int(now.Minute()) % measurementRate == 0) {
      writeSDCard();
      interuptFlag = false;
      DS3231AlarmFlag flag = Rtc.LatchAlarmsTriggeredFlags();
    }
    //Sync RTC once a Day
    if (int(now.Hour()) == syncTime[0] and int(now.Minute()) == syncTime[1]) {
      setRTCTime();
      interuptFlag = false;
      DS3231AlarmFlag flag = Rtc.LatchAlarmsTriggeredFlags();
    }
    //Send data to SQL once a day
    if (int(now.Hour()) == sendDataTime[0] and int(now.Minute()) == sendDataTime[1]) {
      sendDatatoSQL();
      interuptFlag = false;
      DS3231AlarmFlag flag = Rtc.LatchAlarmsTriggeredFlags();
    }
  }
}
void writeSDCard() {
  RtcDateTime now = Rtc.GetDateTime();
  char buffer[5];
  sprintf(buffer,"%04i",now.Year());
  String stringSDCard = String(buffer) + "-";
  sprintf(buffer,"%02i",now.Month());
  stringSDCard = stringSDCard + String(buffer) + "-";
  sprintf(buffer,"%02i",now.Day());
  stringSDCard = stringSDCard + String(buffer) + ";";
  sprintf(buffer,"%02i",now.Hour());
  stringSDCard = stringSDCard + String(buffer) + ":";
  sprintf(buffer,"%02i",now.Minute());
  stringSDCard = stringSDCard + String(buffer) + ";";
  //Get Sensor data
  sd_temp_in = temp_in.temp();
  sd_temp_out = htu.readTemperature();
  sd_hum = htu.readHumidity();
  //and now the data from the scale sensors
  //END Get Sensor data
  stringSDCard = stringSDCard + String(sd_temp_in) + ";" + String(sd_temp_out) + ";" + String(sd_hum) + ";" + String(h1) + ";" + String(h2) + ";" + String(h3) + ";" + String(h4) + ";" + String(h5) + ";" + String(h6) + ";" + String(h7) + ";" + String(h8) + ";" + String(h9) + ";" + String(h10) + ";" + String(h11) + ";" + String(h12);
  if (debug) {Serial.println(stringSDCard);}
  //Write data to SD Card
  dataFile = SD.open(file_name, FILE_WRITE);
  dataFile.println(stringSDCard);
  dataFile.close();
}

This code I tested over a week and it was working.

Now my next step would be to save some power while I will use this application outoor with a battery ans solarpanel. So that only a nacked arduino (desoldered everythind on the mega that's not importet) and the RTC is running

Isnagut

Hello isnagut!
thanks for this its great.
im trying to setup SIM800L with Nano. Im going to do similar stuff like youre doing. ill collect some sensor data and when they are triggered they will start recording and saving them to SD card. and GSM module will transmit data during the day at once or several times or via respond to an action call.

I`m not good coding at all so i try and fails miserably. if you can share your setup i can understand how i have to setup mine.

thanks in advance

MERT

isnagut:
Hi,
i do allmost the same as you.
I'll store some data every five minute and write them to the sd card. One a day the data will uploaded to the FTP server.
So my code is not created to rum in a loop. I think you can initialize the SD card in the setup routine and then you do not have to to this every time.

Some code from my program

void setup() {

byte answer = 0;
  if (debug) {Serial.begin(19200);}  //Start Serial port if we are in the debug modus
  Serial3.begin(19200);              //Start Serial port for Sim900 module
  //init SD Card
  int i = 0;
  while (i < 5 && answer == 0) {
    if (!SD.begin(csSD)) {
      if (debug) {Serial.println("SD Card initialization failed!");}
      i++;
      delay(500);
    }
    else {
      if (debug) {Serial.println("SD Card initialization done.");}
      answer = 1;
    }
  }
}






void loop() {
  askTouch();
  if (interuptFlag) {
    RtcDateTime now = Rtc.GetDateTime();
    if (int(now.Minute()) % measurementRate == 0) {
      writeSDCard();
      interuptFlag = false;
      DS3231AlarmFlag flag = Rtc.LatchAlarmsTriggeredFlags();
    }
    //Sync RTC once a Day
    if (int(now.Hour()) == syncTime[0] and int(now.Minute()) == syncTime[1]) {
      setRTCTime();
      interuptFlag = false;
      DS3231AlarmFlag flag = Rtc.LatchAlarmsTriggeredFlags();
    }
    //Send data to SQL once a day
    if (int(now.Hour()) == sendDataTime[0] and int(now.Minute()) == sendDataTime[1]) {
      sendDatatoSQL();
      interuptFlag = false;
      DS3231AlarmFlag flag = Rtc.LatchAlarmsTriggeredFlags();
    }
  }
}






void writeSDCard() {
  RtcDateTime now = Rtc.GetDateTime();
  char buffer[5];
  sprintf(buffer,"%04i",now.Year());
  String stringSDCard = String(buffer) + "-";
  sprintf(buffer,"%02i",now.Month());
  stringSDCard = stringSDCard + String(buffer) + "-";
  sprintf(buffer,"%02i",now.Day());
  stringSDCard = stringSDCard + String(buffer) + ";";
  sprintf(buffer,"%02i",now.Hour());
  stringSDCard = stringSDCard + String(buffer) + ":";
  sprintf(buffer,"%02i",now.Minute());
  stringSDCard = stringSDCard + String(buffer) + ";";
  //Get Sensor data
  sd_temp_in = temp_in.temp();
  sd_temp_out = htu.readTemperature();
  sd_hum = htu.readHumidity();
  //and now the data from the scale sensors
  //END Get Sensor data
  stringSDCard = stringSDCard + String(sd_temp_in) + ";" + String(sd_temp_out) + ";" + String(sd_hum) + ";" + String(h1) + ";" + String(h2) + ";" + String(h3) + ";" + String(h4) + ";" + String(h5) + ";" + String(h6) + ";" + String(h7) + ";" + String(h8) + ";" + String(h9) + ";" + String(h10) + ";" + String(h11) + ";" + String(h12);
  if (debug) {Serial.println(stringSDCard);}
  //Write data to SD Card
  dataFile = SD.open(file_name, FILE_WRITE);
  dataFile.println(stringSDCard);
  dataFile.close();
}





This code I tested over a week and it was working.

Now my next step would be to save some power while I will use this application outoor with a battery ans solarpanel. So that only a nacked arduino (desoldered everythind on the mega that's not importet) and the RTC is running

Isnagut

Hi,
here you will find my test code: code

The Setup is:

  • Arduino Mega
  • Sim900 link
  • HTU21D Temperature and Humidity Sensor Module link
  • DS3231 link
  • 3,2 zoll TFT Lcd-display-modul link
  • HX711 not implementet in this code link

Pin 19 from the Mega is Pulled up with a 4k7 Resistor to 5V

Isnagut

hi isnagut, the test code link it's not working.
thanks in advance

Plz Send Code pratham.bumb@gmail.com
Thank You

fixed the link.

but I don't use this code anymore. I changed for this project to a Particle Electron.

isnagut

Hi,
I used the code of ctorregrosa but I changed the buffer_space to 300.
It works also for a large file now, but it takes time to send the file.
Lily

When i send large files over SIM800L FTP via your code, sometimes my file gets corrupted too. What was the solution?

isnagut:
Ok, I had the same problem with big files and ctorregrosa wouldn't share the solution with us. So I read in this Forum and with different input's from this forum I get to this solution who is working for me. I'm using a Mega 2560.

byte Sim900FTPSend (){

byte answer = 0;
 if (answer = sendATcommand("AT+FTPPUT=1", "+FTPPUT:1,1,", 60000) == 1) {//Space required after :
   int data_size = 0;
   while(Serial3.available()==0);
   char aux = Serial3.read();
   do{
     data_size *= 10;
     data_size += (aux-0x30);
     while(Serial3.available()==0);
     aux = Serial3.read();      
   } while(aux != 0x0D);
   dataFile = SD.open(file_name);
   String XcomA = "";
   String XcomB = "";
   XcomA.concat("AT+FTPPUT=2,");
   XcomA.concat(data_size);
   XcomA.concat(""");
     
   XcomB.concat("+FTPPUT:2,");//Space required after :
   XcomB.concat(data_size);
   XcomB.concat(""");
     
   char XxcomA[XcomA.length()];
   char XxcomB[XcomB.length()];
     
   XcomA.toCharArray(XxcomA,XcomA.length());
   XcomB.toCharArray(XxcomB,XcomB.length());
     
   if (dataFile) {
     int archivosize = dataFile.size();
     while(dataFile.available() and answer == 1){
       while(archivosize >= data_size){
         if (answer = sendATcommand(XxcomA,XxcomB,3000) == 1) {
           for(int d = 0; d < data_size; d++){
             Serial3.write(dataFile.read());
             archivosize -= 1;
           }
         }
         else {answer = 0;}
       }
       String ScomA = "";
       String ScomB = "";
       ScomA.concat("AT+FTPPUT=2,");
       ScomA.concat(archivosize);
       ScomA.concat(""");
             
       ScomB.concat("+FTPPUT:2,");//Space required after :
       ScomB.concat(archivosize);
       ScomB.concat(""");
             
       char CcomA[ScomA.length()];
       char 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++){
           Serial3.write(dataFile.read());
         }
       }
     }
     // close the file:
     dataFile.close();
   }
   delay(500);
   if (sendATcommand("AT+FTPPUT=2,0", "+FTPPUT:1,0", 30000)==1){ //Space required after :
     if (debug) {Serial.println("File " + String(file_name) + " uploaded..." );}
   }          
 }
 else {answer = 0;}
 return answer;
}




Isnagut

I have fixed minor bugs in this code, and i have tested this code but still it gives error while sending large files. While sending command like AT+FTPPUT=2,1000 the response you get is +FTPPUT: 2,1000 there is a space after colon and same issue is there in other parts of code too which i have commented in the attached code. However, I have modified ctorregrosa's original code and i have tried different files like jpg,mp4,txt,xlsx,zip,rar with file size of 3mb and it uploads without any issue and it keeps on checking for error while uploading bytes and only initiates transfer when receives positive handshake signal, hence file does not get corrupt. If you face problem then do let me know. The code is uploaded in my next reply because of space issue.

#include <SPI.h>
#include <Wire.h>
#include <SD.h>
// TTGO T-Call pins
#define MODEM_RST            5
#define MODEM_PWKEY          4
#define MODEM_POWER_ON       23
#define MODEM_TX             27
#define MODEM_RX             26
#define I2C_SDA              21
#define I2C_SCL              22

// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT Serial1

#include "FS.h"
#include "SD.h"

#define IP5306_ADDR          0x75
#define IP5306_REG_SYS_CTL0  0x00

//char* file_name1 = "/basic.png";
//char* file_name1 = "/xl.xlsx";
//char* file_name1 = "/sample.jpg";
//char* file_name1 = "/bhupi.mp4";
//char* file_name1 = "/data2.txt";
//char* file_name1 = "/data2.rar";
char* file_name1 = "/data2.zip";
char char_buffer;//Change it to int
int buffer_space = 1000;
File File1;

SPIClass SPI1(HSPI);
#define MY_CS       33
#define MY_SCLK     18
#define MY_MISO     19
#define MY_MOSI     32

// I2C for SIM800 (to keep it running when powered from battery)
TwoWire I2CPower = TwoWire(0);

void setup() {
  SerialMon.begin(115200);

  // Start I2C communication
  I2CPower.begin(I2C_SDA, I2C_SCL, 400000);
  
  // Keep power when running from battery
  bool isOk = setPowerBoostKeepOn(1);
  SerialMon.println(String("IP5306 KeepOn ") + (isOk ? "OK" : "FAIL"));

 setupModem();

   // Set GSM module baud rate and UART pins
  SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
  delay(3000);
  
 setupSDCard();

  File1 = SD.open(file_name1);
  if (File1) {
    SerialMon.println("Opening the file: " + String(file_name1) + " done.");
  }else {
    SerialMon.println("Error opening " + String(file_name1));
    while(true);
  }  
  SerialMon.println("Starting...");
  int reply = gprs_modem_function ();
  SerialMon.println("The end... Response: " + String(reply));
}

void setupSDCard()
{
    SPI1.begin(MY_SCLK, MY_MISO, MY_MOSI, MY_CS);
    //Assuming use of SPI SD card
    if (!SD.begin(MY_CS, SPI1)) {
        SerialMon.println("Card Mount Failed");
    } else {
        SerialMon.println("SDCard Mount PASS");
        String size = String((uint32_t)(SD.cardSize() / 1024 / 1024)) + "MB";
        SerialMon.println(size);
    }
}

bool setPowerBoostKeepOn(int en){
  I2CPower.beginTransmission(IP5306_ADDR);
  I2CPower.write(IP5306_REG_SYS_CTL0);
  if (en) {
    I2CPower.write(0x37); // Set bit1: 1 enable 0 disable boost keep on
  } else {
    I2CPower.write(0x35); // 0x37 is default reg value
  }
  return I2CPower.endTransmission() == 0;
}

void setupModem()
{
    // Set modem reset, enable, power pins
  pinMode(MODEM_PWKEY, OUTPUT);
  pinMode(MODEM_RST, OUTPUT);
  pinMode(MODEM_POWER_ON, OUTPUT);
  digitalWrite(MODEM_PWKEY, LOW);
  digitalWrite(MODEM_RST, HIGH);
  digitalWrite(MODEM_POWER_ON, HIGH);
}

void loop() {
  // put your main code here, to run repeatedly:
}

byte gprs_modem_function (){
  byte reply = 1;
  int i = 0;
  while (i < 10 && reply == 1){ //Try 10 times...
    reply = sendATcommand("AT+CREG?","+CREG: 0,1","ERROR", 1000);
    i++;
    delay(1000);
  }
if (reply == 0){
reply = sendATcommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\"","OK","ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+SAPBR=3,1,\"APN\",\"airtelgprs.com\"", "OK", "ERROR", 1000);//Replace with your APN
if (reply == 0){
//reply = sendATcommand("AT+SAPBR=3,1,\"USER\",\"entelpcs\"", "OK", "ERROR", 1000);
if (reply == 0){
//reply = sendATcommand("AT+SAPBR=3,1,\"PWD\",\"entelpcs\"", "OK", "ERROR", 1000);
if (reply == 0){
reply = 2;
i = 0;
while (i < 3 && reply == 2){ //Try 3 times...
reply = sendATcommand("AT+SAPBR=1,1", "OK", "ERROR", 10000);
if (reply == 2){
sendATcommand("AT+SAPBR=0,1", "OK", "ERROR", 10000);
}
i++;
}
if (reply == 0){
reply = sendATcommand("AT+SAPBR=2,1", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPCID=1", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPSERV=\"ftp.sample.com\"", "OK", "ERROR", 1000);//replace ftp.sample.com with your server address
if (reply == 0){
reply = sendATcommand("AT+FTPPORT=21", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPUN=\"1234@sample.com\"", "OK", "ERROR", 1000);//Replace 1234@sample.com with your username
if (reply == 0){
reply = sendATcommand("AT+FTPPW=\"12345\"", "OK", "ERROR", 1000);//Replace 12345 with your password
if (reply == 0){
reply = sendATcommand("AT+FTPPUTNAME=\"" + String(file_name1) + "\"", "OK", "ERROR", 1000);
if (reply == 0){
reply = sendATcommand("AT+FTPPUTPATH=\"/\"", "OK", "ERROR", 1000);// Currently root director is where file will be uploaded "/"
if (reply == 0){
  unsigned int ptime = millis();
  reply = sendATcommand("AT+FTPPUT=1", "+FTPPUT: 1,1", "+FTPPUT: 1,6", 60000);
  SerialMon.println("Time: " + String(millis() - ptime));
  if (reply == 0){
    if (File1) {
      int i = 0;
      unsigned int ptime = millis();
    long archivosize = File1.size();
    while (File1.available()) {
    while(archivosize >= buffer_space){
    reply = sendATcommand("AT+FTPPUT=2," + String(buffer_space), "+FTPPUT: 2,1", "OK", 3000);
    if (reply == 0) { //This loop checks for positive reply to upload bytes and in case or error it retries to upload
    SerialMon.println("Remaining Characters: " + String(File1.available()));
      for(int d = 0; d < buffer_space; d++){
        SerialAT.write(File1.read());
        archivosize -= 1;
      }
    }          
    else {
      SerialMon.println("Error while sending data:");
      reply = 1;
      }
  }
  if (sendATcommand("AT+FTPPUT=2," + String(archivosize), "+FTPPUT: 2," + String(archivosize), "ERROR", 10000) == 0) {
  for(int t = 0; t < archivosize; t++){
    SerialAT.write(File1.read());                            
    }
  }        
      }
      File1.close();
      SerialMon.println("Time: " + String(millis() - ptime));
    }
  }
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return reply;
}

byte sendATcommand(String ATcommand, String answer1, String answer2, unsigned int timeout){
  byte reply = 1;
  String content = "";
  char character;
 
  //Clean the modem input buffer
  while(SerialAT.available()>0) SerialAT.read();

  //Send the atcommand to the modem
  SerialAT.println(ATcommand);
  delay(100);
  unsigned int timeprevious = millis();
  while((reply == 1) && ((millis() - timeprevious) < timeout)){
    while(SerialAT.available()>0) {
      character = SerialAT.read();
      content.concat(character);
      SerialMon.print(character);
      delay(10);
    }
    //Stop reading conditions
    if (content.indexOf(answer1) != -1){
      reply = 0;
    }else if(content.indexOf(answer2) != -1){
      reply = 2;
    }else{
      //Nothing to do...
    }
  }
  return reply;
}