0

I am trying to make a ECG monitoring system using Arduino, GSM and ECG sensor which data should be sent to the private server in real time. Those data are then collected via Matlab on the remote computer and analysis should be executed in real time. When using delays in Arduino sketch GSM successfully sends data to the server but those data are sent in big delays (around 30 seconds) and the sketch doesn't send the data of the whole buffer for some reason (it should be 300 samples, but I had to try to lower that number in order to see any results). After removing delays in the loop where data should be continuously sent, GSM is not executing send data command - AT+CIPSEND. Can anybody help me fix the timer issue and explain why is not the whole buffer sent? Thanks in advance.

#include <SoftwareSerial.h>
#include <String.h>
#include "DHT.h"
int sensorPin = 0;    // set the input pin for the potentiometer
int sensorValue = 0;
#define DHTPIN A0
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

#define DHT11_PIN A0


SoftwareSerial gprsSerial(7,8);

float t; // temperature in celcius
float f; // temperature in fahrenheit
float h; // humidity

  int samplesPerBuffer = 60;
  char separator = ',';
  String buffer = "";
  int currentBufferPosition = 0;
  unsigned long startSamplingTime = 0;       
  const long sampleInterval = 50;       

  // gsm modem config
  String gsmBuffer = "";
  int gsmSendingState = 0; // 0 not sending, 1 preparing sending, 2 sending, 3 finishing sending
//  int gsmSendInterval = 1000;

  int gsmPreparingDelay = 200;
  int gsmSendingDelay = 1500;
  int gsmFinishingDelay = 100;
  unsigned long startRequestTime = 0;     

void setup() {
  // put your setup code here, to run once:
  gprsSerial.begin(9600);               // the GPRS baud rate   
  Serial.begin(9600);    // the GPRS baud rate 
  dht.begin();
  delay(1000);
  initModem();
}

float getSensorData() {
   t = dht.readTemperature();
  //Read humidity
  h = dht.readHumidity();

  // Compute temperature values in Celcius
  t = dht.computeHeatIndex(t,h,false);

  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {
    Serial.println("Failed to read temp from DHT sensor!");
    return 1;
  }

  return t;
}

void initModem() {
  // model init
  if (gprsSerial.available())
    Serial.write(gprsSerial.read());

  gprsSerial.println("AT");
  delay(1000);

  gprsSerial.println("AT+CPIN?");
  delay(1000);

  gprsSerial.println("AT+CREG?");
  delay(1000);

  gprsSerial.println("AT+CGATT?");
  delay(1000);

  gprsSerial.println("AT+CIPSHUT");
  delay(1000);

  gprsSerial.println("AT+CIPSTATUS");
  delay(2000);

  gprsSerial.println("AT+CIPMUX=0");
  delay(2000);

  ShowSerialData();

  gprsSerial.println("AT+CSTT=\"prepaidnet\"");//start task and setting the APN,
  delay(1000);

  ShowSerialData();

  gprsSerial.println("AT+CIICR");//bring up wireless connection
  delay(3000);

  ShowSerialData();

  gprsSerial.println("AT+CIFSR");//get local IP adress
  delay(2000);

  ShowSerialData();

  gprsSerial.println("AT+CIPSPRT=0");
  delay(3000);

  ShowSerialData();
}

void prepareSending() {
  gprsSerial.println("AT+CIPSTART=\"TCP\",\"website.com\",\"80\"");//start up the connection
  ShowSerialData();
}

void sendData() {
  int time = millis();
  gprsSerial.println("AT+CIPSEND");//begin send data to remote server
  String str="GET http://website.com/channel/" + gsmBuffer;
  Serial.println(str);
  gprsSerial.println(str);//begin send data to remote server
  gprsSerial.println((char)26);//sending
}

void finishSending() {
  gprsSerial.println("AT+CIPSHUT");//close the connection
}

void loop() {
 int time = millis();
 if (time - startSamplingTime >= sampleInterval) {
    if (buffer.length() == 0) {
      buffer = buffer + (String)getSensorData();
    }
    else {
      buffer = buffer + separator + (String)getSensorData();
    }
    currentBufferPosition++;
    startSamplingTime = time;
 }
 if (gsmSendingState == 0) {
   // copy buffer to gsmBuffer and triger preparing of the request
   if (currentBufferPosition == samplesPerBuffer) {
    Serial.println("GSM - Preparing sending");
    gsmBuffer = buffer;
    Serial.print("Buffer length: ");
    Serial.println(gsmBuffer.length());
    Serial.println(gsmBuffer);
    buffer = "";
    currentBufferPosition = 0;
    prepareSending();
   }

   // send data if we have something in gsmBuffer
   if (time - startRequestTime >= gsmPreparingDelay) {
    if (gsmBuffer.length() > 0) {
      Serial.println("GSM - Sending data");
      sendData();
      gsmBuffer = "";
      gsmSendingState = 1;
      startRequestTime= time;
    }
   }
 } else {
  if (gsmSendingState == 1) {
    if (time - startRequestTime >= gsmSendingDelay) {
      Serial.println("GSM - Finishing request");
      finishSending();
      gsmSendingState = 2;
      startRequestTime = time;
    }
  }
   else {
      if (gsmSendingState == 2) {
        if (time - startRequestTime >= gsmFinishingDelay) {
          Serial.println("GSM - Request finished");
          gsmSendingState = 0;
          startRequestTime = time;
        }
      }
   }
 }
}


void ShowSerialData()
{
  while(gprsSerial.available()!=0)
    Serial.write(gprsSerial.read());
    Serial.print("Temperature = ");
    Serial.println(t);
    Serial.print("Humidity = ");
    Serial.println(h);
    //delay(5000);  
}

float readTemp() {
  // Read temperature as Celsius
  t = dht.readTemperature();
  //Read humidity
  h = dht.readHumidity();

  // Compute temperature values in Celcius
  t = dht.computeHeatIndex(t,h,false);

  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {
    Serial.println("Failed to read temp from DHT sensor!");
    return 1;
  }

  return t;
}

First part of serial monitor output

Second part of serial monitor output

Third part of serial monitor output

I tried with flush but it didn't resolve the problem. What I read yesterday after so much research is that the GSM module (I am using SIM900) cannot transmit more than 64 bytes with GET method, so I decided to try with the POST method, but no luck - code is returning HTTP 411 error - The request has an invalid header name. I tried some variants of resolving that problem but it didn't work. Does anyone have an ide how to resolve this? I haven't found some working example on the Internet, just some explanations which were unclear to me. The new code is below, along with the output.

/**************************************************************
 *
 * This sketch connects to a website and downloads a page.
 * It can be used to perform HTTP/RESTful API calls.
 *
 * TinyGSM Getting Started guide:
 *   https://tiny.cc/tinygsm-readme
 *
 **************************************************************/

// Select your modem:
//#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
 #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_ESP8266

// Increase RX buffer if needed
//#define TINY_GSM_RX_BUFFER 512

#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>
#include <SoftwareSerial.h>
#include <String.h>
#include "DHT.h"
int sensorPin = 0;    // set the input pin for the potentiometer
int sensorValue = 0;
#define DHTPIN A0
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

//SoftwareSerial gprsSerial(7,8);

float t; // temperature in celcius
float h; // humidity
String headerValue = "";

int samplesPerBuffer = 60;
char separator = ',';
String buffer = "";
int currentBufferPosition = 0;
unsigned long startSamplingTime = 0;       
const long sampleInterval = 50;   
String gsmBuffer = "";
  int gsmSendingState = 0; // 0 not sending, 1 preparing sending, 2 sending, 3 finishing sending
//  int gsmSendInterval = 1000;

  int gsmPreparingDelay = 200;
  int gsmSendingDelay = 1500;
  int gsmFinishingDelay = 100;
  unsigned long startRequestTime = 0;    

// Uncomment this if you want to see all AT commands
//#define DUMP_AT_COMMANDS

// Uncomment this if you want to use SSL
//#define USE_SSL

// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial

// Use Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1

// or Software Serial on Uno, Nano
//#include <SoftwareSerial.h>
SoftwareSerial SerialAT(7, 8); // RX, TX


// Your GPRS credentials
// Leave empty, if missing user or pass
const char apn[]  = "prepaidnet";
const char user[] = "mts";
const char pass[] = "064";

// Server details
const char server[] = "ekg.velizarius.com";
const char resource[] = "/71F977B8DE73/";

#ifdef DUMP_AT_COMMANDS
  #include <StreamDebugger.h>
  StreamDebugger debugger(SerialAT, SerialMon);
  TinyGsm modem(debugger);
#else
  TinyGsm modem(SerialAT);
#endif

#ifdef USE_SSL
  TinyGsmClientSecure client(modem);
  const int  port = 443;
#else
  TinyGsmClient client(modem);
  const int  port = 80;
#endif

HttpClient http(client, server, port);

void setup() {
  // Set console baud rate
  SerialMon.begin(9600);
  delay(10);

  // Set GSM module baud rate
  SerialAT.begin(9600);
  delay(3000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println(F("Initializing modem..."));
  modem.restart();

  String modemInfo = modem.getModemInfo();
  SerialMon.print(F("Modem: "));
  SerialMon.println(modemInfo);

  // Unlock your SIM card with a PIN
  //modem.simUnlock("1234");
}

void loop() {
  SerialMon.print(F("Waiting for network..."));
  if (!modem.waitForNetwork()) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");

  SerialMon.print(F("Connecting to "));
  SerialMon.print(apn);
  if (!modem.gprsConnect(apn, user, pass)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");

  SerialMon.print(F("Connecting to "));
  SerialMon.print(server);
  if (!client.connect(server, port)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");

/*==================================================================================*/
  http.connectionKeepAlive();
  http.beginRequest();
  int codePost = http.post("/71F977B8DE73/");
//
//  DEBUG_MSG_LINE(F("Returned status after post = "));
//  DEBUG_MSG(codePost); 
  http.post("url");
  http.sendHeader(F("Content-Type"), F("text/html"));
  http.sendHeader(F("Content-Length"), String(t).length());
  client.println();
  http.beginBody();
  http.println(String(t)); 
  http.endRequest();
/*===============================================================================*/

  // Make a HTTP POST request:
  client.print(String("POST ") + resource + " HTTP/1.0\r\n");
  client.print(String("Host: ") + server + "\r\n");
  client.print(String(F("\r\nHeader: ")) + headerValue);
  client.print(String(F("\r\n\r\n")));
  client.print(String(t));
  client.print("Connection: close\r\n\r\n");

  unsigned long timeout = millis();
  while (client.connected() && millis() - timeout < 10000L) {
    // Print available data
    while (client.available()) {
      char c = client.read();
      SerialMon.print(c);
      timeout = millis();
    }
  }
  SerialMon.println();

  // Shutdown

  client.stop();
  SerialMon.println(F("Server disconnected"));

  modem.gprsDisconnect();
  SerialMon.println(F("GPRS disconnected"));

  // Do nothing forevermore
//  while (true) {
//    delay(1000);
//  }
}

float getSensorData() {
   t = dht.readTemperature();
  //Read humidity
  h = dht.readHumidity();

  // Compute temperature values in Celcius
  t = dht.computeHeatIndex(t,h,false);

  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {
    Serial.println("Failed to read temp from DHT sensor!");
    return 1;
  }
  return t;
}

http 411

  • Can it be, that the GSM module has a limitation on how long the URL can be? Big data chunk are normally send via the body of a POST request, not via the URL of a GET request. – chrisl Aug 23 at 11:34
  • Yeah, putting data in the URL of a GET request is a bad idea. You should refactor your server API to use RESTFul conventions (send a POST with the data in the body in JSON) – Duncan C Aug 23 at 12:33
  • Thanks for the answers. The URL of a GET request can contain up to 2400 characters, something like that, so I think that shouldn't be a problem. My code with the POST didn't work, GSM commands couldn't have been executed for some reason. – Miloš Mladenović Aug 23 at 12:37
  • Hook up the gsm serial port to your computer to see what the SoftSerial library is really sending to the GSM module. See if adding gprsSerial.flush() at end of sendData helps. See if switching to a different softwareserial library helps (for example AltSoftSerial). See if switching the hardware and software serial helps (use hardware serial, which is generally more reliable, for the GSM module). – Mikael Falkvidd Aug 24 at 7:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.