Go Down

Topic: Issues with GPRS code (Read 649 times) previous topic - next topic

ibbernik

Hi all.

I have made a setup where I have an Arduino, a Seeedstudio gprs v. 2.0 shield, and a CO2-sensor. It all seems to work except that data transmission suddenly stops. On my last test, the application continued for about three days sending messages via http (POST requests), and stopped. When I look at the web server log, I can see that these on minute intervals happens until the last post. The last post comes after five minutes, and then I get no further registrations on the web server log.

I have tried all kinds of error checking (among others printing back to the console via serial). I'm a little lost here, and the only thing I can think of right now, is that I might have some memory leak in my code. So, I have put my code up here, and hoping someone will do a quick review, maybe pinpointing issues in the code.

Code: [Select]

#include <SoftwareSerial.h>

#define         MG_PIN                       (0)
#define         READ_SAMPLE_INTERVAL         (50)    //define how many samples you are going to take in normal operation
#define         READ_SAMPLE_TIMES            (5)     //define the time interval(in milisecond) between each samples in normal operation

String RESOURCEID="some_long_value";
SoftwareSerial GPRS(7,8);
long previousMillis = 0;        // will store last time data was updated
long interval = 60000;          // interval at which to upload data (milliseconds)
char inData[20]; // Allocate some space for the string
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character
boolean isConnected=false;
int codi=0;
unsigned long currentMillis=0;

void setup(){
  GPRS.begin(19200);
  pinMode(13, OUTPUT);
}

void loop(){
  if(!isConnected){
    if(GPRS.available()){
      while(GPRS.available()){
        inChar = GPRS.read();
        if(index < 19){
            inData[index] = inChar; // Store it
            index++; // Increment where to write next
        }
      }
      String te=inData;
      if(te.indexOf("Call Ready")>=0){
      connectGPRS();
      isConnected=true;
      }
      index=0;
    }
  }else{
    currentMillis = millis();
    if(currentMillis - previousMillis > interval) {
      codi = MGRead(MG_PIN);
     
      previousMillis = currentMillis;
      sendToDB();
    }
  }
}

void connectGPRS(){
  boolean res=false;
  while(!res){
    boolean error=false;
    GPRS.println("AT+CGATT=0");
    delay(1000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CGATT=1"); // Attach from GPRS serivce
    delay(6000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CIPMUX=0");
    delay(3000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CSTT=\"internet\""); // Start task and set APN
    delay(4000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CIICR"); // Bring up wireless connection with GPRS
    delay(4000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CIFSR"); // Get local IP address
    delay(2000);
    if(Response()==false)
      error=true;
     
      if(!error)
        res=true;
  }
}

void sendToDB(){
  digitalWrite(13,HIGH);
  GPRS.println("AT+CIPSTART=\"TCP\",\"www.myhost.com\",\"80\"");
  delay(5000);
  GPRS.println("AT+CIPSEND");
  delay(2000);
  GPRS.println("GET /test/house/cohouse.php?value="+ String(codi) +"&resource="+ RESOURCEID +" HTTP/1.1");
  GPRS.println("Host:www.myhost.com");
  GPRS.println("Connection: close");
  GPRS.println("");
  GPRS.println((char)26);
  delay(4000);
}

boolean Response(){
  char data[70];
  byte ind=0;
  boolean b=true;
 
  while(!GPRS.available());
 
  while(GPRS.available()){
    data[ind]=GPRS.read();
    ind++;
  }
    String t=data;
    if(t.indexOf("ERROR")>=0)
      b=false;
     
     return b;
}

int MGRead(int mg_pin){
    int i;
    float v=0;

    for (i=0;i<READ_SAMPLE_TIMES;i++) {
        v += analogRead(mg_pin);
        delay(READ_SAMPLE_INTERVAL);
    }
    v = (((v/READ_SAMPLE_TIMES) *5/1024)*1000);
    return (int)v; 
}


I'm wondering if the problem could be related to the String attribute in the Response function? I haven't been able to find aany concrete answer
to, wether the String object has gotten an internal destructor or not (I haven't looked into the sourcecode yet).

Best regards

Lasse Vestergaard

johnwasser

I bet your problem is storing millisecond times in "long" variables instead of "unsigned long" variables.  Every variable and constant used for millis() storage, calculations, and comparisons should be unsigned long.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

ibbernik

Hi John.

Thanks for your reply. You are definitely right that I should use unsigned instead of signed long. Despite of that, I don't think that's the problem. A long can contain values up to 2,147,483,647 (http://arduino.cc/en/Reference/Long) and if I calculate a little on that:

2,147,483,647/1000 =2,147,483.647 seconds
2,147,483.647 / 60 = 35791 minutes
35791 / 60 = 596,5 hours
596,5 / 24 = 24,8 days

To my understanding this means that the program should be able to run for 24,8 days before crashing, and in my case there only went 3 days.


Regards

Lasse Vestergaard

el_supremo

The problem is almost certainly your use of String in the loop() and Response() functions. You collect the string in a C-style char array but then convert it to String to look for "Call Ready" or "ERROR". You should do the whole thing with C-style null-terminated strings and then you won't run into garbage collection problems with the use of the String class.

Pete

ibbernik

Hi Pete.

That was exactly my thoughts. I ended up removing the String object and use the strstr function instead. I have now deploy my sensor, and crosses my fingers that it works.

I had some problems concatenating strings (char arrays) and int's. So I ended up converting my int to a String (so I still have issues around the String object). I read somewhere that it's not a problem using the String object if it's inside a function, because it will be deallocated after the function ends. Can anyone verify that?

Here is the code I have right now:

Code: [Select]

#include <SoftwareSerial.h>

#define         MG_PIN                       (0)
#define         READ_SAMPLE_INTERVAL         (50)    //define how many samples you are going to take in normal operation
#define         READ_SAMPLE_TIMES            (5)     //define the time interval(in milisecond) between each samples in normal operation

char RESOURCEID[]="some_long_value";
SoftwareSerial GPRS(7,8);
unsigned long previousMillis = 0;        // will store last time data was updated
unsigned long interval = 60000;          // interval at which to upload data (milliseconds)
char inData[40]; // Allocate some space for the string
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character
boolean isConnected=false;
int codi=0;
unsigned long currentMillis=0;

void setup(){
  GPRS.begin(19200);
  pinMode(13, OUTPUT);
}

void loop(){
  if(!isConnected){
    if(GPRS.available()){
      while(GPRS.available()){
        inChar = GPRS.read();
        if(index < 19){
            inData[index] = inChar; // Store it
            index++; // Increment where to write next
        }
      }
      if(strstr(inData,"Call Ready")!=NULL){
      connectGPRS();
      isConnected=true;
      }
      index=0;
    }
  }else{
    currentMillis = millis();
    if(currentMillis - previousMillis > interval) {
      codi = MGRead(MG_PIN);
     
      previousMillis = currentMillis;
      sendToDB();
    }
  }
}

void connectGPRS(){
  boolean res=false;
  while(!res){
    boolean error=false;
    GPRS.println("AT+CGATT=0");
    delay(1000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CGATT=1"); // Attach from GPRS serivce
    delay(6000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CIPMUX=0");
    delay(3000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CSTT=\"internet\""); // Start task and set APN
    delay(4000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CIICR"); // Bring up wireless connection with GPRS
    delay(4000);
    if(Response()==false)
      error=true;
    GPRS.println("AT+CIFSR"); // Get local IP address
    delay(2000);
    if(Response()==false)
      error=true;
     
      if(!error)
        res=true;
  }
}

void sendToDB(){
  digitalWrite(13,HIGH);
  GPRS.println("AT+CIPSTART=\"TCP\",\"www.myhost.com\",\"80\"");
  delay(5000);
  GPRS.println("AT+CIPSEND");
  delay(2000);
  GPRS.println("GET /test/tree/house.php?value="+ String(codi) +"&resource="+ RESOURCEID +" HTTP/1.1");  // STRING OBJECT ISSUE
  GPRS.println("Host:www.myhost.com");
  GPRS.println("Connection: close");
  GPRS.println("");
  GPRS.println((char)26);
  delay(4000);
}

boolean Response(){
  char data[70];
  byte ind=0;
  boolean b=true;
 
  while(!GPRS.available());
 
  while(GPRS.available()){
    data[ind]=GPRS.read();
    ind++;
  }
    if(strstr(data,"ERROR")!=NULL)
      b=false;
     
     return b;
}

int MGRead(int mg_pin){
    int i;
    float v=0;

    for (i=0;i<READ_SAMPLE_TIMES;i++) {
        v += analogRead(mg_pin);
        delay(READ_SAMPLE_INTERVAL);
    }
    v = (((v/READ_SAMPLE_TIMES) *5/1024)*1000);
    return (int)v; 
}


/Lasse

el_supremo

You allocated String objects in the loop() and Response() functions and that caused problems. Allocating one inside a different function is not going to improve things. You have to get rid of them altogether.

Quote
I had some problems concatenating strings (char arrays) and int's.

You can use sprintf to create a string from strings and integers. E.g.

Code: [Select]

  char result[32];
  int i = 42;
  char answer = "The answer";

  sprintf(result,"%s is %d",answer,i);

Will generate "The answer is 42".

Pete

Go Up