Go Down

Topic: Arduino stops sending info to server after a while (Read 1 time) previous topic - next topic

SeanHotRice

Hi,

I have a problem with my Arduino uno and my 3G + GPS shield.
After I launch the arduino, the program sometimes just suddenly stops,
or after sending the data to the server a few times, it stops.

The aim of my project is to send info to a server (here Cosm) on a
regular basis and to also send SMSs.

I'm using two libraries, one to send the SMSs and one to send data to
the server. (code below)

I put in some debug prints so I could see what was going on.
sometimes it would stop here, at the beginning of the connection: (once every two connections)
AT+CGSOCKCONT=1,"IP","gprs.swisscom.ch"

Then during the process of sending data at regular intervals, the arduino stops after a random
number of times. it stops at this:
AT+TCPWRITE=287


For these problems, I'm thinking the Arduino simply doesn't respond, but I don't know why...

here is the code for the libraries:
TCP_3G.cpp
Code: [Select]


#include "Arduino.h"
#include "TCP_3G.h"

TCP_3G::TCP_3G(){

}

void TCP_3G::begin(int led, int onModulePin){
_led = led;
_onModulePin = onModulePin;

x = 0;

   delay(2000);
   pinMode(_led, OUTPUT);
   pinMode(_onModulePin, OUTPUT);

char _server[] = "api.cosm.com";
char _port[] = "8081";

// Set PDP parameters
   Serial.println("AT+CGSOCKCONT=1,\"IP\",\"gprs.swisscom.ch\"");
//
//Blocks here every other time
//
Serial.flush();
Serial.print(Serial.read());
   while(Serial.available()==0 || Serial.read()!='K');
   
   // Set connection parameters
   Serial.print("AT+NETOPEN=\"TCP\","); Serial.println(_port);
   Serial.flush();
   x=0;
   do {
       while(Serial.available()==0);
       data[x]=Serial.read();
//if((data[x]!='\n') && (data[x]!='\r')) Serial.print(char(data[x]));
       x++;  
   } while(!(data[x-1]=='d'&&data[x-2]=='e'));       //waits for response "Network opened"

   while(Serial.available()==0 || Serial.read()!='K');


   // Connect to server
   Serial.print("AT+TCPCONNECT=\""); Serial.print(_server); Serial.print("\","); Serial.println(_port);
   Serial.flush();
   while(Serial.available()==0 || Serial.read()!='K');
}

void TCP_3G::switchModule(){
   digitalWrite(_onModulePin,HIGH);
   digitalWrite(_onModulePin,LOW);
   delay(2000);
}

void TCP_3G::sendInfo(int bottleN, float waterHeight, float derivative){

char COSM_API_KEY[] = "KrGtesAnlf8No0_C9_pLrVGt8biSAKhbViRKFks2eXJ1ez0g";
char COSM_FEED[] = "*****";

//Doing this for the size
char sbottle[6];
   itoa(bottleN,sbottle, 10);
   char scm[6];
   sprintf(scm,"%.0f",waterHeight);
   char sderiv[6];
   sprintf(sderiv,"%.0f",derivative);

   char feedStr[] = "{\"method\":\"put\",\"resource\":\"/feeds/12345\",\"params\":{},\"headers\":{\"X-PachubeApiKey\":\"KrGtesAnlf8No0_C9_pLrVGt8biSAKhbViRKFks2eXJ1ez0g\"},\"body\":{\"datastreams\":[{\"id\":\"0\",\"current_value\":\"\"},{\"id\":\"1\",\"current_value\":\"\"},{\"id\":\"2\",\"current_value\":\"\"}]},\"token\":\"0x12345\"}";

   Serial.print("AT+TCPWRITE="); Serial.println(sizeof(sbottle) + sizeof(scm) + sizeof(sderiv) + sizeof(feedStr));//
   //
//Blocks here after a while
//
Serial.flush();
Serial.print(Serial.read());
   while(Serial.available()==0 || Serial.read()!='>');

   Serial.print("{\"method\":\"put\",\"resource\":\"/feeds/");
   Serial.print(COSM_FEED);
   Serial.print("\",\"params\":{},\"headers\":{\"X-PachubeApiKey\":\"");
   Serial.print(COSM_API_KEY);
   Serial.print("\"},\"body\":{\"datastreams\":[{\"id\":\"0\",\"current_value\":\"");
   Serial.print(bottleN);  
   Serial.print("\"},{\"id\":\"1\",\"current_value\":\"");
   Serial.print(waterHeight);
   Serial.print("\"},{\"id\":\"2\",\"current_value\":\"");
   Serial.print(derivative);
   Serial.println("\"}]},\"token\":\"0x12345\"}");

   Serial.println("AT+NETCLOSE");
   Serial.flush();
   while(Serial.available()==0 || Serial.read()!='K');

}


SMS_3G.cpp
Code: [Select]

#include "Arduino.h"
#include "SMS_3G.h"

SMS_3G::SMS_3G()
{
 
}

void SMS_3G::begin(int led, int onModulePin)
{
_onModulePin = onModulePin;
_led = led;
  //Serial.begin(brate);                // UART baud rate
  delay(2000);

  pinMode(led, OUTPUT);
  pinMode(onModulePin, OUTPUT);
  switchModule();                    // switches the module ON

  for (int i=0;i<5;i++){
      delay(5000);
  }

  Serial.println("AT+CMGF=1");         // sets the SMS mode to text
  delay(100);
}

void SMS_3G::switchModule(){
   digitalWrite(_onModulePin,HIGH);
   delay(2000);
   digitalWrite(_onModulePin,LOW);
}

void SMS_3G::sendSMS(char phone_number[], char msg[])
{

delay(1500);
Serial.print("AT+CMGS=\""); // send the SMS number
Serial.print(phone_number);
Serial.println("\"");
delay(1500);  

Serial.print(msg);   // the SMS body

delay(500);
Serial.write(0x1A);       //sends ++
Serial.write(0x0D);
Serial.write(0x0A);

delay(5000);
}



Thanks a lot for your help!

SeanHotRice

and here is the ino file too:

Code: [Select]

#include <SMS_3G.h> //For sms, it's actually with cosm that it will be sent!
#include <TCP_3G.h>

SMS_3G sms;  //As there are no arguments, drop the brackets
TCP_3G info;
char phone_number[]="*********"; //is the number to which the SMS is going to bo sent
int once = 0; //used to send the only once an sms telling the user 22 bottles are filled

// Pin number of the sensor's output:
const int pingPin = 7;
const int iscoPin = 9;

// Time
unsigned int dtLoop = 10000;            // [ms]
double dtCstSampling = 60.0;           // [s]
double nextSampleTime = 0;             // [s]

// Sensor (height in [cm])
const int dhStormThr = 2;              // [cm/s] for Chambrone a good threasold would be 5-8 cm/jour
const double dhRecPercThr = 0.1;       // [%] recesion detcted when height 10% lower than peak height
float hBase = 0.0f;                    // The mean distance between the senseor and the water.
float cm = 0.0f, cmPeak = -10000.0f;   // The height of the water relative to 'hBase': cm = sensor value - hBase.

// Lowpass filter of the sensor data: alpha with dT_ech and dT_filtre
unsigned int dtFilter = 5000;          // [ms]
const float alpha = (dtLoop/1000.0f) / ((dtFilter/1000.0f)/(2.0f*3.14159f)+(dtLoop/1000.0f));

// Model parameters
double c = 1.0/5.0;                    // in [1/seconds]

// Sampler
unsigned const char nbBottles = 24;    // Total number of bottles in the sampler.
unsigned const char stockBottles = 2;  // Bottles that should remain after the flood.
unsigned char curBottle = 1;           // The current bottle waiting to be filled.

// State of the sensor, because we need to calibrate it (to initialize the hBase variable).
typedef enum {
 CALIGBRATING, SENSOR_READY}
SensorState;
SensorState sensorState;

// State of river
typedef enum {
 WAIT_STORM, WAIT_RECESSION, RECESSION, SAMPLER_FULL}
StormState;
StormState stormState;

// State of sampling
typedef enum {
 NOT_SAMPLING, CST_SAMPLING, PROG_SAMPLING}
SamplingState;
SamplingState samplingState;

void setup()
{
 // initialize serial communication.
 Serial.begin(115200);

 // initialize ISCO command pin
 pinMode(iscoPin, OUTPUT);
 digitalWrite(iscoPin, LOW);

 // initialize the SMS and the TCP connection
 // Don't call switchmodule twice!
 sms.begin(13, 2);
 info.begin(13 ,2);

 // initialize states.
 sensorState = CALIGBRATING;
 stormState = WAIT_STORM;
 samplingState = NOT_SAMPLING;
 //Serial.println("Calbrating");
}

void loop()
{
 long duration = getDistancePulseDuration();             // get the datat from the Ultrasound sensor.
 float sensorCM = microsecondsToCentimeters(duration);   // convert the time into a distance
 if(sensorState == CALIGBRATING) { // Calibrate the sensor -> the base height is the current height.
   calibrateSensor(sensorCM);
   return;
 }

 float cmCur, cmDerivative, dhRecThr;
 cmCur = hBase - sensorCM;
 cmDerivative = cm; // store prev_val here to save the number of variables
 cm = alpha*cmCur + (1.0f-alpha)*cm;
 cmDerivative = (cm - cmDerivative) / float(dtLoop / 1000.f);

 // Storm state management
 // (WAIT_STORM -> WAIT_RECESSION (10% of height peak) -> RECESSION -> WAIT_STORM).
 switch(stormState) {

 case WAIT_STORM: // Waiting for the flood.
   if(cmDerivative > dhStormThr) { // The flood is detected when slope of height curve overcome dhStormThr.
     stormState = WAIT_RECESSION;
     samplingState = CST_SAMPLING;
   }
   break;

 case WAIT_RECESSION: // Waiting that the height of water decrease.
   cmPeak = cm > cmPeak ? cm : cmPeak;
   dhRecThr = cmPeak * dhRecPercThr;
   if(cmPeak - cm > dhRecThr) { // Check if height of water is under dhRecPercThr [%] of the highest water height value.
     cmPeak = -10000.0f;
     stormState = RECESSION;
     samplingState = PROG_SAMPLING;
   }
   break;

 case RECESSION: // In recession, waiting that all the bottles are empty.
   if(curBottle > nbBottles-stockBottles) { // We preserve some bottles in case...
     if(once == 0){
//-----------------------------------------------------
       // send SMS to operator
       //-----------------------------------------------------
       sms.sendSMS(phone_number, "finished sampling, two bottles left in case");
       once++;
     }
     stormState = WAIT_STORM;
     samplingState = NOT_SAMPLING;
   }
   else if(cmDerivative > dhStormThr) { // A flood is detected during the recetion -> go back to constant sampling and wait for recession.
     stormState = WAIT_RECESSION;
     samplingState = CST_SAMPLING;
   }
   break;
 }

 // Sampling management.
 if(samplingState != NOT_SAMPLING) { // We are sampling.
   double remainingTime = nextSampleTime - double(millis())/1000.0;
   if(remainingTime < 0.0) { // next sample
     
     /*if(curBottle == 1) {
       // SMS sent to say the sampling has started
       //sms.sendSMS(phone_number, "Sampling started");
       //Serial.println("first SMS sent.");
     }*/
     curBottle++;
     if(curBottle >= nbBottles) { // sampler full -> send SMS
       //-----------------------------------------------------
       // send SMS to operator
       //-----------------------------------------------------
       samplingState = NOT_SAMPLING;
       stormState = SAMPLER_FULL;
       //sms.sendSMS(phone_number, "Sampler full, the prediction might have been wrong, or the sampling's totally finished");
       //Serial.println("SMS sent.");
     }
     else {
       //-----------------------------------------------------
       // send next sample cammand to ISCO Sampler
       digitalWrite(iscoPin, HIGH);
       delay(10);
       digitalWrite(iscoPin, LOW);
       //-----------------------------------------------------
       if(samplingState == CST_SAMPLING) {
         nextSampleTime = computeNextSampleCstTime(dtCstSampling);
       }
       else {
         nextSampleTime = computeNextSampleProgTime(curBottle, nbBottles, c);
       }
     }
   }
 }
 info.sendInfo(curBottle, cm, cmDerivative); //We send info every time

   delay(dtLoop);
}



void calibrateSensor(float height) {
 int dt = 100;
 const float a = (dt/1000.0f) / ((2000.0f/1000.0f)/(2.0f*3.14159f)+(dt/1000.0f));
 hBase = a*height + (1.0f-a)*hBase;
 delay(dt);
 if(millis() > 5000) // we calibrate sensor during 2s.
   sensorState = SENSOR_READY;
}


double computeNextSampleCstTime(double dtCstSampling) {
 return dtCstSampling + double(millis())/1000.0;
}


double computeNextSampleProgTime(unsigned char a, unsigned char RS, float c) {
 // The time between samples is computed such that each sampling interval correspond
 // to an equal volume of flow under the predicated hydrograph recession curve.
 double t_sample = (exp( 2.996*double(a) / double(RS)) - 1.0f) / double(c);
 t_sample += double(millis())/1000.0;
 return t_sample;
}


long getDistancePulseDuration()
{
 // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
 // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
 pinMode(pingPin, OUTPUT);
 digitalWrite(pingPin, LOW);
 delayMicroseconds(2);
 digitalWrite(pingPin, HIGH);
 delayMicroseconds(5);
 digitalWrite(pingPin, LOW);

 // The same pin is used to read the signal from the PING))): a HIGH pulse whose duration is the
 // time (in microseconds) from the sending of the ping to the reception of its echo off of an object.
 pinMode(pingPin, INPUT);
 return pulseIn(pingPin, HIGH);
}


float microsecondsToCentimeters(long microseconds)
{
 // The speed of sound is 343.2 m/s or 29.1375 microseconds per centimeter.
 // The ping travels out and back, so to find the distance of the object we take half of the distance travelled.
 return microseconds / 2.0f / 29.1375f;
}

michinyon

Chinese government hackers are interfering with your device.

spatula

You seem to have very many strings, likely to fill the Uno's RAM which is only 2K. Unfortunately, each debug statement you add can only worsen the situation. One solution is to use the F() macro for messages that never change. For example, instead of
Code: [Select]

Serial.println("AT+NETCLOSE");

you may write
Code: [Select]

Serial.println(F("AT+NETCLOSE"));


The F() macro stores the string in program memory, not ram. You cannot use it for string that change during the execution of the sketch.

I cannot say whether this will solve your problems, but there are other potential issues. If you get an error on AT+CGSOCKCONT=1,"IP","gprs.swisscom.ch", it's a connection error with your APN and you shouldn't ignore it. It may happen sometimes and your program should be able to manage it (e.g., by retrying after a certain time). I also notice that you never check for the value of return messages from the modem: you assume they are OK (check for Serial.read()!='K'), but what if you got an ERROR response?

michinyon

Are you sure that the arduino is the problem ?

If it cannot communicate to the 3G device,   perhaps the 3G device is "hanging up" ( in one or other meaning of the expression ) ?.

Go Up