carrascoacd / ArduinoSIM800L

Arduino HTTP & FTP client for SIM800L/SIM800 boards to perform GET and POST requests to a JSON API as well as FTP uploads.
159 stars 58 forks source link

HardwareSerial and ESP32 #43

Open carrascoacd opened 4 years ago

carrascoacd commented 4 years ago

Following this https://github.com/carrascoacd/ArduinoSIM800L/issues/40#issuecomment-628606309

pcbtborges commented 4 years ago

Hi, Antonio, If I change //SoftwareSerial serialSIM800; HardwareSerial serialSIM800; unsigned int resetPin;

It fails to compile: exit status 1 Erro compilando para a placa ESP32 Wrover Module

Do I have to do anything on my sketch?

#define DEBUG_ESP              //comment out to deactivate debug console

#ifdef DEBUG_ESP
  #define pDBGln(x) Serial.println(x)
  #define pDBG(x)   Serial.print(x)
#else 
  #define pDBG(...)
  #define pDBGln(...)
#endif

#include <Ftp.h>
#include "FFat.h"
#include "../examples/utils/logger.h"

#define GSM_BAUD_RATE 9600

// 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

const char BEARER[]     PROGMEM = "claro.claro.com";
const char FTP_SERVER[] PROGMEM = "ftp.myserver.com";
const char FTP_USER[]   PROGMEM = "station@myserver.com";
const char FTP_PASS[]   PROGMEM = "mypass";

File dataFile;
int counter=1;

void setup() {
  // Init Serial Console
  Serial.begin(115200);

  // 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);  

  if(!FFat.begin(true)){
    pDBGln("Fat FS: Mount Failed");
    return;
  }else{
    pDBGln("Fat FS: Mount OK");
  } 
}

void loop() {
  pDBGln("Loop starting....");  
  String myFile = "image" + String(counter) + ".jpg";
  char charFileName[myFile.length()+1];
  myFile.toCharArray(charFileName,myFile.length()+1);
  uploadFile(charFileName);
  pDBGln("transfer Sucessfull");
  delay(20000);
  counter++;
}

void uploadFile(const char *FTPimageFile) {
  dataFile = FFat.open("/esp32pic.jpg");  
  pDBGln("File mount OK.");  
  if (dataFile) {
    FTP ftp(GSM_BAUD_RATE, MODEM_RX, MODEM_TX, MODEM_RST);
    pDBGln("Modem init OK");
    ftp.wakeUp();
    pDBGln("FTP wakeUp done.");
    pDBG("Configuring FTP. \nBearer: ");
    pDBG(BEARER);
    pDBG(", Image: ");
    pDBG(FTPimageFile);
    pDBG(", size: ");
    pDBG(dataFile.size());
    pDBG(",\nsrv: ");
    pDBG(FTP_SERVER);
    pDBG(",\nuser: ");
    pDBG(FTP_USER);
    pDBG(", pass: ");
    pDBGln(FTP_PASS);

    pDBGln("Starting ftp.putBegin ...");
    ftp.putBegin(BEARER, FTPimageFile, FTP_SERVER, FTP_USER, FTP_PASS);
    pDBGln("ftp.putBegin OK.");

    unsigned int i;
    unsigned int chunkSize = 512;
    unsigned int writes = ceil(dataFile.size() / chunkSize);
    char buff[chunkSize];

    while (dataFile.available()) {
      i = 0;
      while (i < chunkSize) {
        buff[i] = dataFile.read();
        ++i;
      }

      if (ftp.putWrite(buff, i) != SUCCESS){
        return;
      }
      writes --;

      info(F("Pending: "), false);
      info(writes, false);
      info(F("/"), false);
      info(ceil(dataFile.size() / chunkSize), true);
    }

    ftp.putEnd();
    ftp.sleep();
    dataFile.close();
  }else {
    info(F("FTP. File open failed: "));
    info(FTPimageFile);
  }
}
carrascoacd commented 4 years ago

Have you included HardwareSerial here?

Show me the error please

pcbtborges commented 4 years ago

Hi, I did include it now.

When I compile the sketch it returns: exit status 1 Erro compilando para a placa ESP32 Wrover Module

Sim800.h is as below with all changes you asked for:

/*
 * Sim800.h
 * A library for SeeedStudio seeeduino GPRS shield
 *
 * Original work Copyright (c) 2013 seeed technology inc. [lawliet zou]
 * Modified work Copyright 2018 Antonio Carrasco
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef __SIM800_H__
#define __SIM800_H__

#include <Arduino.h>
//#include <SoftwareSerial.h>
#include <HardwareSerial.h>

#define TRUE 1
#define FALSE 0
#define DEFAULT_TIMEOUT 5000

// Comment or uncomment this to debug the library
#define DEBUG true

/** SIM800 class.
 *  Used for SIM800 communication. attention that SIM800 module communicate with MCU in serial protocol
 */

class SIM800
{

public:
    /** Create SIM800 Instance
     *  @param baudRate baud rate of uart communication
     *  @param rxPin uart receive pin to communicate with SIM800
     *  @param txPin uart transmit pin to communicate with SIM800
     */
    SIM800(unsigned int baudRate,
           unsigned int rxPin,
           unsigned int txPin,
           //unsigned int rstPin) : serialSIM800(txPin, rxPin)
           unsigned int rstPin) : serialSIM800(1)
    {
        //serialSIM800.begin(baudRate);
        serialSIM800.begin(baudRate, SERIAL_8N1, txPin, rxPin);
        resetPin = rstPin;
    };

    /** Power on SIM800
     */
    int preInit(void);

    /** Check if SIM800 readable
     */
    int checkReadable(void);

    /** read from SIM800 module and save to buffer array
     *  @param  buffer  buffer array to save what read from SIM800 module
     *  @param  count   the maximal bytes number read from SIM800 module
     *  @param  timeOut time to wait for reading from SIM800 module
     *  @returns
     *      TRUE on success
     *      ERROR on error
     */
    int readBuffer(char *buffer, int count, unsigned int timeOut = DEFAULT_TIMEOUT);

    /** clean Buffer
     *  @param buffer   buffer to clean
     *  @param count    number of bytes to clean
     */
    void cleanBuffer(char *buffer, int count);

    /** send AT command to SIM800 module
     *  @param cmd  command array which will be send to GPRS module
     *  @param delayBeforeSend  integer indicating the sime to wait before sending a command
     */
    void sendCmd(const char *cmd, unsigned int delayBeforeSend = 10);

    /**send "AT" to SIM800 module
     */
    int sendATTest(void);

    /**send '0x1A' to SIM800 Module
     */
    void sendEndMark(void);

    /** check SIM800 module response before time out
     *  @param  *resp   correct response which SIM800 module will return. A 'X' char
     *  can be used to allow any char matching character, example:
     *  '200' and '201' matches with '20X'
     *  @param  *timeout    waiting seconds till timeout
     *  @returns
     *      TRUE on success
     *      ERROR on error
     */
    int waitForResp(const char *resp, unsigned timeout);

    /** send AT command to GPRS module and wait for correct response
     *  @param  *cmd    AT command which will be send to GPRS module
     *  @param  *resp   correct response which GPRS module will return
     *  @param  *timeout    waiting seconds till timeout
     *  @returns
     *      TRUE on success
     *      ERROR on error
     */
    int sendCmdAndWaitForResp(const char *cmd, const char *resp, unsigned timeout);

    /** 
     *  The sendCmdAndWaitForResp_P() function is similar to sendCmdAndWaitForResp() 
     *  except that cmd and resp are pointers to a string in program space.
     */
    int sendCmdAndWaitForResp_P(const char *cmd, const char *resp, unsigned timeout);

    /** used for serial debug, you can specify tx and rx pin and then communicate with GPRS module with common AT commands
     */
    void serialDebug(void);

    void purgeSerial();

    void write(const char *data);
    void write(const char *data, unsigned int size);

    void sleep(bool force = FALSE);
    void wakeUp();

protected:
    //SoftwareSerial serialSIM800;
    HardwareSerial serialSIM800;
    unsigned int resetPin;
};

#endif
pcbtborges commented 4 years ago

Antonio, this is the compiler's log. May be it can tell you something. Thanks

AVISO: a biblioteca ArduinoSIM800L-master alega rodar em arquitetura(s) avr e pode ser incompatível com sua placa atual, que roda em arquitetura(s) esp32.
In file included from C:\Users\pctbo\OneDrive\Documents\Arduino\TestUploadGPRS_Teste\TestUploadGPRS_Teste.ino:13:0:

c:\users\pctbo\onedrive\documents\arduino\libraries\arduinosim800l-master\examples\utils\logger.h:44:8: warning: extra tokens at end of #endif directive [-Wendif-labels]

 #endif __LOGGER_H__

        ^

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-master\src\Sim800.cpp: In member function 'void SIM800::sendCmd(const char*, unsigned int)':

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-master\src\Sim800.cpp:104:18: error: 'class HardwareSerial' has no member named 'listen'

     serialSIM800.listen();

                  ^

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-master\src\Sim800.cpp: In member function 'void SIM800::write(const char*)':

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-master\src\Sim800.cpp:196:18: error: 'class HardwareSerial' has no member named 'listen'

     serialSIM800.listen();

                  ^

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-master\src\Sim800.cpp: In member function 'void SIM800::write(const char*, unsigned int)':

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-master\src\Sim800.cpp:202:18: error: 'class HardwareSerial' has no member named 'listen'

     serialSIM800.listen();

                  ^

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-master\src\Sim800.cpp:203:34: error: invalid conversion from 'const char*' to 'const uint8_t* {aka const unsigned char*}' [-fpermissive]

     serialSIM800.write(data, size);

                                  ^

In file included from C:\Users\pctbo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32/Arduino.h:154:0,

                 from C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-master\src\Sim800.h:32,

                 from C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-master\src\Sim800.cpp:29:

C:\Users\pctbo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32/HardwareSerial.h:67:12: note:   initializing argument 1 of 'virtual size_t HardwareSerial::write(const uint8_t*, size_t)'

     size_t write(const uint8_t *buffer, size_t size);

            ^

Foram encontradas múltiplas bibliotecas para "SD.h"
Usado: C:\Users\pctbo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\SD
Não usado: C:\Program Files (x86)\Arduino\libraries\SD
exit status 1
Erro compilando para a placa ESP32 Wrover Module
pcbtborges commented 4 years ago

Hi Antonio, I have never dealt with the internals of libraries but I am trying to figure out what may be wrong and I believe it is still something to do with the Serial port.

The compiler messages: error: 'class HardwareSerial' has no member named 'listen' serialSIM800.listen();

error: invalid conversion from 'const char' to 'const uint8_t {aka const unsigned char*}' [-fpermissive] serialSIM800.write(data, size);

Indicate the change to HardwareSerial may require more adjustments.

The FTP functionality will be added to a main sketch that already uses HardwareSerial for the SIM800 to post data to a SQL database so I understand it is desirable to keep HardwareSerial.

I will keep trying to understand what might be wrong but your help will be highly appreciated once I am not experienced enough to get this thing working by myself in any short time frame.

Thanks Paulo

carrascoacd commented 4 years ago

Hi, I've created this branch trying to fix your problems (sorry I don't have the same hardware) https://github.com/carrascoacd/ArduinoSIM800L/tree/add-compatibility-for-esp32

Download it and let me know if it works now, or we can iterate with the next problem

pcbtborges commented 4 years ago

Antonio, good morning.

What I did was to delete the folder holding the previous library and used sketch/include library/add .zip library. Then recompiled the same sketch as posted previously. The compiler log is as below. Thanks Paulo

WARNING: library ArduinoSIM800L-add-compatibility-for-esp32 claims to run on avr architecture(s) and may be incompatible with your current board which runs on esp32 architecture(s).
In file included from C:\Users\pctbo\OneDrive\Documents\Arduino\TestUploadGPRS_Teste\TestUploadGPRS_Teste.ino:13:0:

c:\users\pctbo\onedrive\documents\arduino\libraries\arduinosim800l-add-compatibility-for-esp32\examples\utils\logger.h:44:8: warning: extra tokens at end of #endif directive [-Wendif-labels]

 #endif __LOGGER_H__

        ^

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp: In member function 'void SIM800::sendCmd(const char*, unsigned int)':

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp:101:18: error: 'class HardwareSerial' has no member named 'listen'

     serialSIM800.listen();

                  ^

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp: In member function 'int SIM800::sendATTest()':

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp:110:39: error: 'AT' was not declared in this scope

     int ret = sendCmdAndWaitForResp_P(AT, AT_OK, DEFAULT_TIMEOUT);

                                       ^

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp: In member function 'void SIM800::write(const char*, unsigned int)':

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp:200:34: error: invalid conversion from 'const char*' to 'const uint8_t* {aka const unsigned char*}' [-fpermissive]

     serialSIM800.write(data, size);

                                  ^

In file included from C:\Users\pctbo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32/Arduino.h:154:0,

                 from C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.h:32,

                 from C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp:29:

C:\Users\pctbo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32/HardwareSerial.h:67:12: note:   initializing argument 1 of 'virtual size_t HardwareSerial::write(const uint8_t*, size_t)'

     size_t write(const uint8_t *buffer, size_t size);

            ^

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp: In member function 'void SIM800::sleep(bool)':

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp:211:65: error: return-statement with a value, in function returning 'void' [-fpermissive]

         return sendCmdAndWaitForResp_P(SLEEP_MODE_1, AT_OK, 2000);

                                                                 ^

C:\Users\pctbo\OneDrive\Documents\Arduino\libraries\ArduinoSIM800L-add-compatibility-for-esp32\src\Sim800.cpp:215:65: error: return-statement with a value, in function returning 'void' [-fpermissive]

         return sendCmdAndWaitForResp_P(SLEEP_MODE_2, AT_OK, 2000);

                                                                 ^

exit status 1
Error compiling for board ESP32 Wrover Module.
carrascoacd commented 4 years ago

Hi, please download it again from the same branch https://github.com/carrascoacd/ArduinoSIM800L/tree/add-compatibility-for-esp32, I fixed the compilation errors.

pcbtborges commented 4 years ago

Hi Antonio. Just tested, no more compilation errors, thanks. When run the sketch freezes as console display below:

Fat FS: Mount OK
Loop starting....
File mount OK.
Modem init OK
FTP wakeUp done.
Configuring FTP. 
Bearer: claro.claro.com, 
ftpImageName: image1.jpg, size: 6293,
srv: ftp.myftpserver.com,
user: station@myftpserver.com, pass: mypass
Starting ftp.putBegin ...

Sketch code as below:

#define DEBUG_ESP              //comment out to deactivate debug console

#ifdef DEBUG_ESP
  #define pDBGln(x) Serial.println(x)
  #define pDBG(x)   Serial.print(x)
#else 
  #define pDBG(...)
  #define pDBGln(...)
#endif

#include <Ftp.h>
#include "FFat.h"
#include "../examples/utils/logger.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 GSM_BAUD_RATE      9600

const char BEARER[]     PROGMEM = "claro.claro.com";
const char FTP_SERVER[] PROGMEM = "ftp.hidroflux.com";
const char FTP_USER[]   PROGMEM = "station@iot.hidroflux.com";
const char FTP_PASS[]   PROGMEM = "gen99ius";

File dataFile;
int counter=1;

void setup() {
  // Init Serial Console
  Serial.begin(115200);

  // 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);  

  if(!FFat.begin(true)){
    pDBGln("Fat FS: Mount Failed");
    return;
  }else{
    pDBGln("Fat FS: Mount OK");
  } 
}

void loop() {
  pDBGln("Loop starting....");  
  String myFile = "image" + String(counter) + ".jpg";
  char charFileName[myFile.length()+1];
  myFile.toCharArray(charFileName,myFile.length()+1);
  uploadFile(charFileName);
  pDBGln("transfer Sucessfull");
  delay(20000);
  counter++;
}

void uploadFile(const char *FTPimageFile) {
  dataFile = FFat.open("/esp32pic.jpg");  
  pDBGln("File mount OK.");  
  if (dataFile) {
    FTP ftp(GSM_BAUD_RATE, MODEM_RX, MODEM_TX, MODEM_RST);
    pDBGln("Modem init OK");
    ftp.wakeUp();
    pDBGln("FTP wakeUp done.");
    pDBG("Configuring FTP. \nBearer: ");
    pDBG(BEARER);
    pDBG(",\nftpImageName: ");
    pDBG(FTPimageFile);
    pDBG(", size: ");
    pDBG(dataFile.size());
    pDBG(",\nsrv: ");
    pDBG(FTP_SERVER);
    pDBG(",\nuser: ");
    pDBG(FTP_USER);
    pDBG(", pass: ");
    pDBGln(FTP_PASS);

    pDBGln("Starting ftp.putBegin ...");

    ftp.putBegin(BEARER, FTPimageFile, FTP_SERVER, FTP_USER, FTP_PASS);

    pDBGln("ftp.putBegin OK.");

    unsigned int i;
    unsigned int chunkSize = 512;
    unsigned int writes = ceil(dataFile.size() / chunkSize);
    char buff[chunkSize];

    while (dataFile.available()) {
      i = 0;
      while (i < chunkSize) {
        buff[i] = dataFile.read();
        ++i;
      }

      if (ftp.putWrite(buff, i) != SUCCESS){
        return;
      }
      writes --;

      info(F("Pending: "), false);
      info(writes, false);
      info(F("/"), false);
      info(ceil(dataFile.size() / chunkSize), true);
    }

    ftp.putEnd();
    ftp.sleep();
    dataFile.close();
  }else {
    info(F("FTP. File open failed: "));
    info(FTPimageFile);
  }
}

I tried to put some probes at ftp.cpp but it did not print. See fragment below:

#include "GPRS.h"
#include "Arduino.h"

Result FTP::putBegin(const char *apn,
                     const char *fileName,
                     const char *server,
                     const char *usr,
                     const char *pass,
                     const char *path)
{
  Result result = openGPRSContext(this, apn);

                Serial.println("putBegin has started...");

  char buffer[64];
  char tmp[24];
carrascoacd commented 4 years ago

It should be retrying to connect. Please, ensure you can see in your serial monitor the output from this line we need to see what is going on.

Try also this function ftp.serialDebug(); just after initializing the variable and send AT commands in the serial monitor input, to check if it is receiving anything.

pcbtborges commented 4 years ago

Hi, thanks. I did not get where I am to include the ftp.serialDebug(); but I made some other additions that might put some light on the reason for the problem.

The hardware and the SIM card are OK, I do have a test sketch to test the size of a file on my FTP server using AT only commands and it is working (see code and console display below).

The main sketch remains the same. Current SIM800.cpp code is as below: Added lines are marked as: <<<-----------------------------------XXXXX

/*
 * Sim800.cpp
 * A library for SeeedStudio seeeduino GPRS shield
 *
 * Original work Copyright (c) 2013 seeed technology inc. [lawliet zou]
 * Modified work Copyright 2019 Antonio Carrasco
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "Sim800.h"
#include <Arduino.h>               <<<-----------------------------------XXX
#define DEBUG                          <<<-----------------------------------XXX

const char SLEEP_MODE_2[] PROGMEM = "AT+CSCLK=2\r\n";
const char SLEEP_MODE_1[] PROGMEM = "AT+CSCLK=1\r\n";
const char SLEEP_MODE_0[] PROGMEM = "AT+CSCLK=0\r\n";
const char AT_OK[] PROGMEM = "OK";
const char AT[] PROGMEM = "AT\r\n";

int SIM800::preInit(void)
{
    pinMode(resetPin, OUTPUT);

    digitalWrite(resetPin, HIGH);
    delay(200);
    digitalWrite(resetPin, LOW);
    delay(2000);
    digitalWrite(resetPin, HIGH);
    delay(3000);

    purgeSerial();
    serialSIM800.flush();

    return TRUE;
}

int SIM800::checkReadable(void)
{
    return serialSIM800.available();
}

int SIM800::readBuffer(char *buffer, int count, unsigned int timeOut)
{
    int i = 0;
    unsigned long timerStart = millis();
    while (1)
    {
        while (serialSIM800.available())
        {
            char c = serialSIM800.read();
            buffer[i] = c;
            buffer[i + 1] = '\0';
            ++i;
            if (i > count - 1)
                break;
        }
        if (i > count - 1)
            break;

        unsigned long timerEnd = millis();
        if (timerEnd - timerStart > timeOut)
        {
            break;
        }
    }

    while (serialSIM800.available())
    {
        serialSIM800.read();
    }
    return TRUE;
}

void SIM800::cleanBuffer(char *buffer, int count)
{
    for (int i = 0; i < count; i++)
    {
        buffer[i] = '\0';
    }
}

void SIM800::sendCmd(const char *cmd, unsigned int delayBeforeSend)
{
    //serialSIM800.listen();
    serialSIM800.flush();
    delay(delayBeforeSend);
    write(cmd);
    serialSIM800.flush();
}

int SIM800::sendATTest(void)
{
    int ret = sendCmdAndWaitForResp_P(AT, AT_OK, DEFAULT_TIMEOUT);

    #ifdef DEBUG                                      <<<----From here-----------------XXX
       Serial.print(AT);
       Serial.print(", ");
       Serial.print(AT_OK);
       Serial.print(" Timeout: ");
       Serial.println(DEFAULT_TIMEOUT);   
    #endif                                        <<<-------Up to here--------------------XXX

    return ret;
}

int SIM800::waitForResp(const char *resp, unsigned int timeout)
{
    int len = strlen(resp);
    int sum = 0;
    unsigned long timerStart = millis();

    while (1)
    {
        if (serialSIM800.available())
        {
            char c = serialSIM800.read();

            #ifdef DEBUG
              Serial.print("*");                 <<<-----------------------------------XXXXX
              Serial.print(c);
            #endif

            sum = (c == resp[sum] || resp[sum] == 'X') ? sum + 1 : 0;
            if (sum == len)
                break;
        }
        unsigned long timerEnd = millis();
        if (timerEnd - timerStart > timeout)
        {
            return FALSE;
        }
    }

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

    return TRUE;
}

void SIM800::sendEndMark(void)
{
    serialSIM800.println((char)26);
}

int SIM800::sendCmdAndWaitForResp(const char *cmd, const char *resp, unsigned timeout)
{
    sendCmd(cmd);
    return waitForResp(resp, timeout);
}

int SIM800::sendCmdAndWaitForResp_P(const char *cmd, const char *resp, unsigned timeout)
{
    char cmdBuff[128];
    char respBuff[32];
    strcpy_P(cmdBuff, cmd);
    strcpy_P(respBuff, resp);

    return sendCmdAndWaitForResp(cmdBuff, respBuff, timeout);
}

void SIM800::serialDebug(void)
{
    while (1)
    {
        if (serialSIM800.available())
        {
            Serial.write(serialSIM800.read());
        }
        if (Serial.available())
        {
            serialSIM800.write(Serial.read());
        }
    }
}

void SIM800::purgeSerial()
{
    while (serialSIM800.available())
        serialSIM800.read();
}

void SIM800::write(const char *data)
{
    //serialSIM800.listen();
    serialSIM800.write(data);
}

void SIM800::write(const char *data, unsigned int size)
{
    //serialSIM800.listen();
    serialSIM800.write((const uint8_t*)data, size);
}

void SIM800::sleep(bool force)
{
    if (force)
    {
        sendCmdAndWaitForResp_P(SLEEP_MODE_1, AT_OK, 2000);
    }
    else
    {
        sendCmdAndWaitForResp_P(SLEEP_MODE_2, AT_OK, 2000);
    }
}

void SIM800::wakeUp()
{
    preInit();
    sendCmdAndWaitForResp_P(SLEEP_MODE_0, AT_OK, 2000);
}

Console output:

Fat FS: Mount OK
Loop starting....
File mount OK.
Modem init OK
***FTP wakeUp done.
Configuring FTP. 
Bearer: claro.claro.com,
ftpImageName: image1.jpg, size: 6293
srv: ftp.myftpserver.com,
user: station@myftpserver.com, pass: mypass
Starting ftp.putBegin ...
******AT
AT
, OK Timeout: 5000
**************************************************... goes on and on

The Test Sketch I am using to verify if GPRS is connecting is as below:

#define SerialAT Serial1
// 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

void setup() {
  Serial.begin(115200);
  // 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);

  // Set GSM module baud rate and UART pins
  SerialAT.begin(9600, SERIAL_8N1, MODEM_RX, MODEM_TX);
  delay(10000);
}

void loop() {
  Serial.println("Start modem...");
  sendCommand("at+cfun?");
  sendCommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\"");
  sendCommand("AT+SAPBR=3,1,\"apn\",\"claro.claro.com\"");
  sendCommand("at+sapbr=1,1");

  //FTP
  sendCommand("AT+FTPCID=1");
  sendCommand("AT+FTPSERV=\"ftp.myftpserver.com\"");
  sendCommand("AT+FTPPORT=21");
  sendCommand("AT+FTPUN=\"station@myftpserver.com\"");
  sendCommand("AT+FTPPW=\"mypass\"");
  sendCommand("AT+FTPGETNAME=\"myfile.jpg\"");
  sendCommand("AT+FTPGETPATH=\"/\"");
  sendCommand("AT+FTPSIZE");
  delay(15000);
}

byte sendCommand(String serialCommand){
  String content = "";
  char character;  
  byte chkStatus=99;
  SerialAT.println(serialCommand);
  Serial.print(serialCommand);
  Serial.println(": ");
  delay(200);
  while(SerialAT.available()>0) {
    character = SerialAT.read();
    content.concat(character);
    delay(30);
    //Stop reading conditions
    if (content.indexOf("ERROR") != -1){
      chkStatus = 0;
      break;
    }
  }
  Serial.print(content);
  delay(3000);
  return chkStatus;
}

Console output for this test sketch:

Start modem...
at+cfun?: 
+CFUN: 1

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

*PSUTTZ: 2020,5,19,12,15,9,"-12",0
DST: 0

OK
AT+SAPBR=3,1,"apn","claro.claro.com": 

OK
at+sapbr=1,1: 
AT+FTPCID=1: 

OK
OK
AT+FTPSERV="ftp.myftpserver.com": 

OK
AT+FTPPORT=21: 

OK
AT+FTPUN="station@myftpserver.com": 

OK
AT+FTPPW="mypass": 

OK
AT+FTPGETNAME="myfile.jpg":
OK
AT+FTPGETPATH="/": 

OK
AT+FTPSIZE: 

OK
Start modem...
at+cfun?: 

+FTPSIZE: 1,0,2324
pcbtborges commented 4 years ago

Antonio, I have been looking into the code and try to understand things I am not familiarized with and I believe the problem is still related with the proper connection between the code and the serial port.

The sketch I am using and I have published above is just a test platform to later move the concept to the main project that is much larger.

I tried to unify this main project with the test code I posted above but did not succeed.

The fact is that in my project's sketch the GPRS connection is established and used by first defining as follow: #define SerialAT Serial1

Then latter this SerialAT is used in all GPRS related operations.

In your suggested implementation you recently changed SIM800.cpp to make this "connection" using: HardwareSerial serialSIM800;

Is it possible to use the style I am using currently: SerialAT as above stated before setup(){}? Once the current test is working what will I have to do to make this adjustment?

Also, the following initialization is already present in the original setup() and used elsewhere:

  // Set GSM module baud rate and UART pins
  SerialAT.begin(9600, SERIAL_8N1, MODEM_RX, MODEM_TX);

Is it possible to just use this one?

Thanks Paulo

pcbtborges commented 4 years ago

Hi Antonio, I had some time to try it again today and went back to your suggestion to use serialDebug(); I tried it inside my sketch but it did not work then I made the following change at SIM800.cpp (please see fragment below):

void SIM800::sendCmd(const char *cmd, unsigned int delayBeforeSend)
{

Serial.println("Starting Manual Serial...");
serialDebug();

    //serialSIM800.listen();
    serialSIM800.flush();
    delay(delayBeforeSend);
    write(cmd);
    serialSIM800.flush();
}

The result is that it echoes every command I type on the Arduino serial terminal:

Fat FS: Mount OK
Loop starting....
File mount OK.
Modem init OK
Starting Manual Serial...
AT
AT
at
AT+CREG?

Regards Paulo

carrascoacd commented 4 years ago

If the serial debug is working it means that the connection with the changes you made to use HardwareSeral are properly working.

I ordered an ESP32 board to debug it. You need to see output when DEBUG is enabled, otherwise I can't help you right now. Try to check why is not showing anthing before.

On Fri 22 May 2020, 6:13 p.m. Paulo Borges notifications@github.com wrote:

Hi Antonio, I had some time to try it again today and went back to your suggestion to use serialDebug(); I tried it inside my sketch but it did not work then I made the following change at SIM800.cpp (please see fragment below):

void SIM800::sendCmd(const char *cmd, unsigned int delayBeforeSend) {

Serial.println("Starting Manual Serial..."); serialDebug();

//serialSIM800.listen();
serialSIM800.flush();
delay(delayBeforeSend);
write(cmd);
serialSIM800.flush();

}

The result is that it echoes every command I type on the Arduino serial terminal:

Fat FS: Mount OK Loop starting.... File mount OK. Modem init OK Starting Manual Serial... AT AT at AT+CREG?

Regards Paulo

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/carrascoacd/ArduinoSIM800L/issues/43#issuecomment-632773661, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBWFOFKOPVMBB7ECGDBSB3RS2QCJANCNFSM4NBTDT6Q .

pcbtborges commented 4 years ago

Hi Antonio, I have the following test sketch and it is similar to this manual serial control you suggested. I tried but could not figure out why one works and the other does not.

The following one works: That is why I believe the serial connection (software) is at fault, tried several things but no good.

If you can take a look in this code that works and propose some change based on that I will try my best to make experiments and try to fix it.

Thanks Paulo

#define SerialAT Serial1
// 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

void setup() {
  Serial.begin(115200);
  // 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);

  // Set GSM module baud rate and UART pins
  SerialAT.begin(9600, SERIAL_8N1, MODEM_RX, MODEM_TX);
}

void loop() {
  if (SerialAT.available()) {
    Serial.write(SerialAT.read());
  }
  if (Serial.available()) {
    SerialAT.write(Serial.read());
  }
}
pcbtborges commented 4 years ago

Antonio, good afternoon, I think I got something.

When I run my test sketch above that sends console commands from the serial console straight to the modem's serial port (Serial1 in the above test) it returns OK from the modem, except for the command: AT+FTPSIZE at the end of my test when also returns the file size.

When I use the serialDebug(void) from your library instead of returning OK it returns precisely what I type, whatever I type and only what I type. Please see below:

Fat FS: Mount OK
------------------>>> Starting!
Loop starting....
File mount OK.
Modem init OK
Starting Manual Serial...
AT
The name of my cat is Zig...             <<-------------<<

My conclusion is that the Modem Serial port is, somehow, "wired" to the console Serial port.

I have tried to modify Sim800.h on the following part:

protected:
    HardwareSerial serialSIM800;
    unsigned int resetPin;
};

#endif

So, my feeling is that HardwareSerial serialSIM800; is, somehow, interacting with the console. I tried to add an (1) or a (2) as in serialSIM800(2); to direct it away from the console but it does not compile.

What do you think? Is this something?

Thanks Paulo

carrascoacd commented 4 years ago

The serial debug mode is intended to read the input from the PC Serial (your serial monitor) and then read the output from your ESP module to print it.

What is happening is that you see what you type, it is normal. The problem is that ESP is not responding to your manual commands.

AT input should respond OK. You are having a connection problem, try to figure out why.

pcbtborges commented 4 years ago

Hi, I do not understand one thing. As you say: "The serial debug mode is intended to read the input from the PC Serial (your serial monitor) and then read the output from your ESP module to print it."

Correct but the serial debug function on Sim800.cpp has no provision to print on the console the command I just typed on the console.

The Sim800.cpp only has provision to print whatever comes from the serial port where Sim800 GSM modem is connected (Serial.write(serialSIM800.read());) How can the command I type be printed back to the console with the code that is currently at the function (void SIM800::serialDebug(void)) used at Sim800.cpp?

Also, I understand that the response OK comes from the modem right? My feeling is that the command I type does not reach the modem and is, somehow, been channeled back to the console for some reason I do not understand.

Thanks Paulo

bhupiister commented 3 years ago

@pcbtborges Did you manage to solve the problem? I am looking to send a large txt file of 10mb to my server. I am trying FTP right now and its working for small files, haven't tested for large files right now. Is FTP better or HTTP post ?

pcbtborges commented 3 years ago

Hi, the transfer works sometimes, the larger the file the more often it fails. But there is no error, the transfer runs to the end. Transfer always fail at the end, when one chunk fails to arrive all subsequent chunks will be missing. I had to stop trying as I had no ways to improve the design, I believe what is missing is some flow and error control. Haven't tried http for that purpose. If you find some way around this situation please inform. Thanks

bhupiister commented 3 years ago

@pcbtborges Came across this code today for large files, will test it. See if this works for you.

include

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(command.c_str()); return p; } }

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

pcbtborges commented 3 years ago

I am a bit busy with other things right now but will sure try this one a soon as I do have some spare time. Thanks