GSM code for sending GPS data

This is a sister project to the “GPS Logger, reading and Writing to and from SD” because it is connected, but then again a separate and stand alone device. For this project, I am currently using what I had on hand, and will be temporarily; a Arduino pro mini 168 Chinese copy, which is fine, until the two projects merge. Then I will be using a Nano 328.

This code is functional but limited, and is just a starting point. Both the pro mini 168 module and the GSM A6 module, are being powered by their USB ports, for now, that will also change when the projects merge. The virtual serial TX, RX are connected to pins (6,7) using<SoftwareSerial.h>, which will most likely change also.

The amount of characters that I’m able to send, over GSM, per text right now is 118. I’m hoping someone, with further knowledge can increase this amount per text. This code will also have to grab the data from the GPS module, then send a text message, every five minutes or so, automatically. This added after original posting I would also like to be able to upload a five character text (.) to reflect the sea level pressure to correctly adjust the altitude. End off added content
I had to piece the code together from copy pasting half at a time. I don’t know why the Arduino IDE would not allow me to copy paste all at once but the Sketch should work fine.

#include <SoftwareSerial.h>
char messageIn;

// If more than 118 characters into the String, you will get giberish in the serial monitor
//...AT+CMGS="+181386753giberish here ...Notice that the final 2 cell phone numbers are "gibberish" covered. 
// I used 120 characters to achieve the error
String coordinatesGPS = "-82.41273,28.07181,4433.00-82.41273,28.07181,4433.00-82.41273,28.07181,4433.00-82.41273,28.07181,4433.00testtesttestte";
SoftwareSerial mySerial(6, 7);

void setup()
{
  mySerial.begin(9600);   // Setting the baud rate of GSM Module
  Serial.begin(9600);    // Setting the baud rate of Serial Monitor (Arduino)
  delay(100);
  //would not send a text message unless I sent these AT commands first
  mySerial.println("AT");
  delay(1000);
  mySerial.println("ATD");
  mySerial.println("ATH");
  delay(100);
  //Send a text
  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"+18133477680\"\r"); // Replace jenny jennies number with mobile number
  delay(1000);
  mySerial.println("Zeppelin initialized");// The SMS text you want to send
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
}


void loop()
{
  // mySerial.println("s");
  //  delay(2000);
  if (Serial.available() > 0)
    switch (Serial.read())
    {
      case 's':
        SendMessage();
        break;
      case 'r':
        RecieveMessage();
        break;
    }

  if (mySerial.available() > 0)

    Serial.write(mySerial.read());
}


void SendMessage()
{

  mySerial.println("AT");
  delay(1000);
  mySerial.println("ATD");
  mySerial.println("ATH");
  delay(100);

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"+18138675309\"\r"); // Replace jenny jennies cell number with mobile number
  delay(1000);
  mySerial.println(coordinatesGPS);// The SMS text you want to send
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
}


void RecieveMessage()
{

  mySerial.println("AT+CNMI=2,2,0,0,0"); // AT Command to receive a live SMS
  delay(1000);


}

Made a few changes and upgrades to the sketch. Replaced SoftwareSerial library with the AltSoftSerial along with the tx/rx pins to (8,9). The buffer for AltSoftSerial was easily changed to expand it from 118 (softwareSerial) to 159 bytes. That seems to be the limit to the tx buffer, or is it? Therefore a second variable was created to send a text message containing Date/time and the information, in the sea level pressure variable, separately.
Deleted the code to manually receive text messages; it did nothing and text messages where printed to the serial monitor, automatically. Unfortunately text sent to the Arduino, while the Arduino serial monitor isn’t active, are never received. Still needed is a way to save the 5 character float, text message to a variable, in the Arduino.

#include <AltSoftSerial.h>
#define RX_BUFFER_SIZE 8   //90// default// receives messages even if set to 0
#define TX_BUFFER_SIZE 90    //58// default //99 tops for 159 characters
AltSoftSerial gpsPort; // must be on specific pins (8 & 9 for an UNO)

// storage for received 5 character text message, containing local sea level info.
char messageIn;

// If more than 159 characters are loaded into the String and are attempted to be sent,
//...none of the message will be texted.  Empty spaces count as a character in the String count.
String coordinatesGPS = "-182.41271,-28.07181,10,000.00 -182.41271,-28.07181,10,000.00 -182.41271,-28.07181,10,000.00 -182.41271,-28.07181,10,000.00 -1821.4127,-28.07181,10,000.00";
// most amount of characters possibly obtained from GPS and Altimeter

// date time year from GPS and the mercury at sea level being stored in variable
String dateTimeSeaLevel = "2017-06-21 19:25:53 SL=22.22";

void setup()
{
  gpsPort.begin(9600);   // Setting the baud rate of GSM Module
  Serial.begin(9600);    // Setting the baud rate of Serial Monitor (Arduino)
  delay(100);
  //would not send a text message unless I sent these AT commands first
  gpsPort.println("AT");
  delay(1000);
  gpsPort.println("ATD");
  gpsPort.println("ATH");
  delay(100);
  //Send a text
  gpsPort.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  gpsPort.println("AT+CMGS=\"+18133477680\"\r"); // Replace jenny jennies number with mobile number
  delay(1000);
  gpsPort.println("Zeppelin initialized");// The SMS text you want to send
  delay(100);
  gpsPort.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
}


void loop()
{

  if (Serial.available() > 0)
    switch (Serial.read())
    {
      case 'l':
        SendMessage();
        break;
      case 't':
        SendMessage2();
        break;
    }

  if (gpsPort.available() > 0)

    Serial.write(gpsPort.read());
}


void SendMessage()
{

  gpsPort.println("AT");
  delay(1000);
  gpsPort.println("ATD");
  gpsPort.println("ATH");
  delay(100);

  gpsPort.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  gpsPort.println("AT+CMGS=\"+18133477680\"\r"); // Replace x with mobile number
  delay(1000);
  gpsPort.println(coordinatesGPS);// The SMS text you want to send
  delay(100);
  gpsPort.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
}


void SendMessage2()

{
  // the AltSoftSerial buffer has a limit, so this is to send a second text message,
  // with time date and whats in the seaLevel variable.
  gpsPort.println("AT");
  delay(1000);
  gpsPort.println("ATD");
  gpsPort.println("ATH");
  delay(100);

  gpsPort.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  gpsPort.println("AT+CMGS=\"+18133477680\"\r"); // Replace x with mobile number
  delay(1000);
  gpsPort.println(dateTimeSeaLevel);// The SMS text you want to send
  delay(100);
  gpsPort.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
}

Which modem are you using?
I have the SIM5320 chipsets, and using the +CMGSEX command to send multi-part SMS messages.
Or you could switch to GPRS data and send text strings that way if you have an IP based host somewhere.

Sorry for the delayed response: Its an A6 Quad-band GPRS/GSM Module Here is a link to the online manual Here as you can see I'm using AT commands because that is what I ran into first, while searching for example sketches for it.

Unfortunately that link isn't really a complete manual...
If you have a link to the AT command set they implement, it will help you figure out the available methods.

From a brief search of other resources, it looks like that modem doesn't support AT+CMGSEX, so you're stuck with PDU mode multi-part messages, or sending via GPRS data

Otherwise, the comments above stand.

Searching a little more and I found this HERE which at a quick glance seems to be more information than the prior link. I believe you are correct, on the deduction that the A6 doesn't support "AT+CMGSEX" since a Google search found only a few related links. Also the SIMM card being used by the A6 is a G3 GPRS, if that helps identify the possible libraries, code and AT commands to be used. Thanks for pointing at PDU mode, which was unknown, to me, until now.

AT+CMGF=1 limits your outbound TEXT messages to 140 chars total, but CMGF=0. requires you to pack the PDU data, for longer / multi-part (concatenated) messages.

OK, so it doesn't support AT+CMGSEX, that's not a showstopper, but YOU have to do a bit more work to send & receive, but you also have to lmaintain the message headers to identify a multi-part message.

There are a few examples of PDU message conversion online.

In the interest of keeping text cost as low as possible; was the motivation for having more characters per text. The limitation of my GSM provider being 160 and 500 text just will not due, in the long run. So settling for 160 characters or less, per text, at 4 minute intervals, will allow for the dev. period, until the sketch is working as desired. Obvious not to me previous to your link; then I will need an unlimited plan to transmit all that GPS data.

So the next big hurtle is to be able to receive a 5 character text and save it to a variable. This text would either have to be sent from a web based or from a cell phone. source. The number being transmitted is the mercury pressure at sea level, in the local the GPS device is in. Example

30.13

This number will only have to be sent after the unit has drastically traveled or weather conditions have changed significantly and suddenly. The sister tread containing information about the GPS logger and the "unit" is HERE.

ok, i had a look at your other thread, and a couple of things come to mind...

To receive serial strings, look at the same methods used for the GPS, except you'll need to concatenate chars before you can match a whole word.

In the GPS code this is happening within the library, so you either need to scratch around in there to see how they parse for (e.g.) specific NMEA prefixes.

If it hasn't been said already, get used to working with C char arrays instead of Strings. Save memory and cycles.

Once you absorb all that, you might consider using GPRS data instead of SMS text.
Data can remain or reconnect as many times as you like in you billing period, and is only charged on throughput, not the number of individual messages.

SMS are charged per message as you know, and you use up the messages and allowance pretty quickly.... if you move across to data - even with a small 1GB mobile plan, that equates to ~seven MILLION text messages of 140 characters.

Carry on!

To receive serial strings, look at the same methods used for the GPS, except you’ll need to concatenate chars before you can match a whole word.

In the GPS code this is happening within the library, so you either need to scratch around in there to see how they parse for (e.g.) specific NMEA prefixes.

After looking at a few libraries A6lib seemed to suit the needs of the sketch best and supports an A6. If anybody has any suggestions of a better library for a GSM/GPRS A6, please post a link. The use of “unreadSMSNum = A6l.getUnreadSMSLocs(unreadSMSLocs, 30);” in the sms.ino example seems like a similar way as the

the same methods used for the GPS

to retrieve, and then be able to store, a received message; unless I’m mistaken. The biggest concern is, running out of space on the Arduino Nano 328, when the 2 sketches are combined, from the resources being taken up by the libraries and ram. But that issue, that can wait…

get used to working with C char arrays instead of Strings.

I had trouble getting char to send a text. I assume “C char” is different. Thanks, I new Strings ate up a lot of resources, but didn’t know what to do about it.

Once you absorb all that, you might consider using GPRS data instead of SMS text.

Any tutorials in particular you can point at. I will also search this forum, for using “GPRS data”, of course. Would using the “A6lib” library work with using GPRS data, instead of SMS text?

Unfortunately i'm not familiar with the A6 at all, but in general, all serial devices are treated roughly the same.

I was going to mention the limited RAM in the '328, but it doesn't need to be a problem if the program and storage are optimised (losing String will reduce RAM significantly). Make sure your RAM utilisation doesn't go above about 85-90% after compilation, or you may experience unexpected 'hiccups' when stack/heap space run out.

Many of the 'better' serial / sms / gps examples will be using char arrays properly - but definitely not all of them!

Program (FLASH) space /should/ be ok for your application - Just think & plan your strategy and use of RAM variables... sometimes values only need to be 'in scope' while they are being processed.

I was going to mention the limited RAM in the '328, but it doesn’t need to be a problem if the program and storage are optimized (losing String will reduce RAM significantly).

Lost the strings and got the chars working, but need to save as much space in dynamic ram as well as storage space to be able to combine it with the sister, GPS and SD logger sketch in this thread.

Tried a couple of libraries the GPS.h seemed bloated and the other one I could not get to function at all. If this code could be slimmed down; it would work fine for the purposes of this project, so any help would be appreciated immensely!
A couple obvious problems with the code…Converting from char ascii to float isn’t totally working (rounding off after the decimal point). I’m sure it could be fixed, but just started learning how to use it today…

Using a routine to keep the A6 awake and running, in the void setup, would be a major improvement. Right now sending a text at startup works well, but there has to be a better way.

#include <AltSoftSerial.h>
#define RX_BUFFER_SIZE 10   //90// default// recieves messages even if set to 0
#define TX_BUFFER_SIZE 90    //58// default //99 tops for 159 characters
AltSoftSerial GSMPort; // must be on specific pins (8 & 9 for an UNO)

// storage for recieved 6 character text nessage, containing local sea level info. and a single character to choose a message to be sent from the A6 device to a cell phone
char incomingMess[8] = ("abcdefg");
// 5 character default startup mecury at sea level variable, later to hold accurate sea level data recieved from a text message
char seaLevel[6] = ("30.12");
char j[1] = {'\0'}; // holds the sixth character sent in the incomingMess, to determent what data is to be texted from the A6 module to a cell phone
int i = 0; // if statement counter
// If more than 159 characters are loaded into the String and are attempted to be sent,
//...none of the message will be texted.  Empty spaces count as a character in the String count.
//"-182.41271,-28.07181,10,000.00 -182.41271,-28.07181,10,000.00 -182.41271,-28.07181,10,000.00 -182.41271,-28.07181,10,000.00 -1821.4127,-28.07181,10,000.00";
char coordinatesGPS[11] = "-182.41271,";
// most amount of characters possibly ubtained from GPS and Altimeter

// date time year from GPS and the mecury at sea level being stored in variable
//String dateTimeSeaLevel = "2017-06-21 19:25:53 SL=22.22";
char dateTimeSeaLevel[] = "-182.41271,-28.07181,10,000.00 -182.41271,-28.07181,10,000.00 -182.41271,-28.07181,10,000.00 -182.41271,-28.07181,10,000.00 -1821.4127,-28.07181,10,000.00";
// for conversion from char ascii to int
float  n = 30.12;
char buffer[5];

void setup()
{
  GSMPort.begin(9600);   // Setting the baud rate of GSM Module
  Serial.begin(9600);    // Setting the baud rate of Serial Monitor (Arduino)
  delay(100);


  //would not send a text message unless I sent these AT commands first
  GSMPort.println("AT");
  delay(1000);
  GSMPort.println("ATD");
  GSMPort.println("ATH");
  delay(100);
  //Send a text
  GSMPort.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  GSMPort.println("AT+CMGS=\"+18133477680\"\r"); // Replace jenny jennies number with mobile number
  delay(1000);
  GSMPort.println("Zeppelin initialized");// The SMS text you want to send
  delay(100);
  GSMPort.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

}


void loop()
{
  delay(100);
  //Ready serial for input and output
  if (Serial.available() > 0)
    switch (Serial.read())
    {
    }

  //to receive and store text message of 6 characters
  if ((GSMPort.available() > 0) && (i <= 7))
  {
    incomingMess[i] = GSMPort.read();

    i++;
    delay(5);

    //  Serial.print("incomingMess = ");
    //  Serial.println(incomingMess);
    delay(5);

  }

  else
  {
    //reset counter above to 0
    i = 0;
    // j is where the sixth character that holds the send command letter
    strncpy(j, (incomingMess) + 5, 1);
    delay(5);
    Serial.print("sea level n = ");
    Serial.println(n);
    delay(5);
    Serial.print("j = ");
    Serial.println(j);
    delay(5);
  }
  //parse incomming text message (incomingMess),and return requested information 't' via text
  if  ((j[0] == 't') && (i < 1))
  {
    strncpy(seaLevel, incomingMess, 5);
    delay(5);
    strncpy(j, (incomingMess) + 0, 1);
    delay(5);
    SendMessage2();
    delay(500);

    //convert incomming text from an ascii in a char to float(doesn't work right) rounds off after decimal point

    buffer[0] = seaLevel[0];
    buffer[1] = seaLevel[1];
    buffer[2] = seaLevel[2];
    buffer[3] = seaLevel[3];
    buffer[4] = seaLevel[4];
    buffer[5] = '\0';
    n = atoi(buffer);
    i++;
  }
  // same as above but parsed for 'l' to text back different request but also uploads sea level data also

  if  ((j[0] == 'l') && (i < 1))
  {
    strncpy(seaLevel, incomingMess, 5);
    delay(5);
    strncpy(j, (incomingMess) + 0, 1);

    //convert incomming text from an ascii in a char to float (doesn't work right) rounds off after decimal point

    buffer[0] = seaLevel[0];
    buffer[1] = seaLevel[1];
    buffer[2] = seaLevel[2];
    buffer[3] = seaLevel[3];
    buffer[4] = seaLevel[4];
    buffer[5] = '\0';
    n = atoi(buffer);

    Serial.print("sea level = ");
    Serial.println(seaLevel);
    delay(5);
    Serial.print("j = ");
    Serial.println(j);
    delay(5);
    SendMessage();
    delay(500);

    i++;
  }
  else
  {
    // clear what is in variable j
    /* could not get this to work; the sketch would stop running
          for( i = 0; i < sizeof(j);  ++i )
      j[i] = (char)0;
    */
    strncpy(j, (incomingMess) + 5, 1);


  }
}

void SendMessage()
{
  // message to text back if 'l' is chosen

  GSMPort.println("AT");
  delay(1000);
  GSMPort.println("ATD");
  GSMPort.println("ATH");
  delay(100);

  GSMPort.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  GSMPort.println("AT+CMGS=\"+18133477680\"\r"); // Replace x with mobile number
  delay(1000);
  GSMPort.println("Sea level pressure is now set to ");
  delay(100);
  GSMPort.println(n);// The SMS text you want to send //default char byte coordinatesGPS[4]
  delay(100);
  GSMPort.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
}


void SendMessage2()

{
  // message to text back if 't' is chosen

  GSMPort.println("AT");
  delay(1000);
  GSMPort.println("ATD");
  GSMPort.println("ATH");
  delay(100);
  GSMPort.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  GSMPort.println("AT+CMGS=\"+18133477680\"\r"); // Replace x with mobile number
  delay(1000);
  GSMPort.println(dateTimeSeaLevel);// The SMS text you want to send
  delay(100);
  GSMPort.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

}