Error w/ Adafruit GPS Library & GSM Library together

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by adafruit_support_rick »

mldemarie wrote:Thanks to both of you. After removing the parentheses my code compiles without error.
Ah, but does it work?

mldemarie
 
Posts: 7
Joined: Fri Aug 16, 2013 11:25 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by mldemarie »

Hi Again,

So the solution to using both the GSM library and GPS library by utilizing AltSoftSerial seems to solve one problem. However it is causing me another problem. I believe the problem is pinpointed to the line where you associate the AltSoftSerial to the GPS object. It is pointed out and commented out in the code below. While this line is commented out, the code seems to work flawlessly. The basic idea is that i send a text to enable specific functions. When a text is received it gets converted into a String object so i can perform the convenient String operations. Here the text "+lightson" or "+lightsoff" make a digital output blink or remain LOW. Eventually i want to use a text command to enable the GPS.

The first section of the setup() just reads some values from the EEPROM and loads them into Strings, not important, then i set up the GSM connection. Setting the GPS area is commented out, but not needed yet.

The problem is as follows: When the line "Adafruit_GPS GPS(&mySerial);" is uncommented, the code doesn't work the same. I've been testing it for a coupe days, and a comment/uncomment to this line is the only change i make that causes the weird behavior. From what i can tell, after the AltSoftSerial is set to the GPS, the other Serial communications (Serial() for the Serial Monitor and the Software Serial for the GSM) seem to get screwed up. While i'm watching the Serial Monitor the text does not always appear and when i send a text it isn't always taken in correctly.

Code: Select all

// include libraries and definitions
#include <GSM.h>                  // include the GSM library
#include <EEPROM.h>               // include the Memory library
#define PINNUMBER ""              // PIN Number for the SIM
#include <Adafruit_GPS.h>         // GPS Library
#include <AltSoftSerial.h>
AltSoftSerial mySerial;
//Adafruit_GPS GPS(&mySerial);   <---PROBLEM LINE
// initialize the library instances
GSM gsmAccess;
GSMVoiceCall vcs;
GSM_SMS sms;
// initialize variables
char    c, charBuff[50];
int     i, j;
boolean blinkLED;
String  Msg, adminPW, userPW, senderNum, adminNum, userNum, cmd1, cmd2, cmd3;
//--------------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  pinMode(4, OUTPUT); digitalWrite(4, HIGH);   // LED control, Keep them off
  pinMode(5, OUTPUT); digitalWrite(5, LOW);    // GSM indicator LED
  // Load PW's and Numbers from eeprom
  for (i = 0; i < 20; i++)
    charBuff[i] = EEPROM.read(i + 00);
  adminPW = String(charBuff);
  for (i = 0; i < 20; i++)
    charBuff[i] = EEPROM.read(i + 20);
  userPW = String(charBuff);
  for (i = 0; i < 20; i++)
    charBuff[i] = EEPROM.read(i + 40);
  adminNum = String(charBuff);
  for (i = 0; i < 20; i++)
    charBuff[i] = EEPROM.read(i + 60);
  userNum = String(charBuff);
  //--------------------------------------------------
  Serial.println("--- Code ---");
  Serial.print("Admin PW    : ");  Serial.println(adminPW);
  Serial.print("User PW     : ");  Serial.println(userPW);
  Serial.print("Admin Number: ");  Serial.println(adminNum);
  Serial.print("User Number : ");  Serial.println(userNum);
  // GSM setup
  Serial.println("Please wait as we obtain GSM reception");
  boolean notConnected = true;                 // connection state
  while(notConnected) {                        // Start GSM connection
    if(gsmAccess.begin(PINNUMBER)==GSM_READY)  notConnected = false;
    else                                       Serial.println("Not connected");
    delay(1000);
  }
  Serial.println("GSM initialized");
  Serial.println("------------------------------");
  // GPS setup
//  GPS.begin(4800);            // GPS baud rate
//  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
//  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
//  GPS.sendCommand(PGCMD_ANTENNA);
//  Serial.println("GPS initialized");
  digitalWrite(5, HIGH);                    // Turn on a LED to show GSM initialized
}
//--------------------------------------------------------------------------------
void loop() {
  if (sms.available()) {                       // If there are any SMS's available 
    sms.remoteNumber(charBuff, 20);            // Get remote number
    senderNum = String(charBuff);
    if (sms.peek() != '+') {                   // If SMS doesn't begin with '+', toss it
      Serial.println("Message Ignored");
      cmd1 = String(""); cmd2 = String(""); cmd3 = String("");
    }
    else {                                     // If SMS begins with '+', read it
      Serial.print("Message received from: ");  Serial.println(senderNum);
      i = 0;
      while(c = sms.read()) {
        charBuff[i] = c;
        i++;
      }
      charBuff[i] = '\0';
      Msg = String(charBuff);                  // Put SMS received as characters
      Serial.println(Msg);                     //  into a string for easy comparisons
      cmd1 = Msg.substring(1,Msg.length());
      cmd2 = String("");  cmd3 = String("");
    }
    Serial.print("cmd1. ");  Serial.println(cmd1);
    Serial.print("cmd2. ");  Serial.println(cmd2);
    Serial.print("cmd3. ");  Serial.println(cmd3);
    sms.flush();                                            // Always flush SMS
    // Find and execute commands
    if (cmd1.equalsIgnoreCase("lightson")) {
      Serial.println("-c-");
      blinkLED = true;
      respond("Lights On");
    }
    else if (cmd1.equalsIgnoreCase("lightsoff")) {
      Serial.println("-d-");
      blinkLED = false;
      respond("Lights Off");
    }
  }
  //*****************************************************************************
  if (blinkLED) {                                    // If blinking should occur, do so
    if(digitalRead(4) == LOW)   digitalWrite(4, HIGH);
    else                        digitalWrite(4, LOW);
  }
  else                          digitalWrite(4, HIGH);
  //*****************************************************************************
  delay(1000);
}
//--------------------------------------------------------------------------------
void respond(String x) {                        // Return confirmation SMS on what
  senderNum.toCharArray(charBuff, 20);          //  has happened.
  sms.beginSMS(charBuff);
  sms.print(x);
  sms.endSMS();
  sms.flush();
}
//--------------------------------------------------------------------------------
I'm thinking that the problem may lie in the baud rates or these Serial communications, but not having much luck. I was using the information towards the bottom of this site http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html . Might anyone have a similar issue or thoughts? When using the AltSoftSerial for the GPS like this, what is the appropriate way to specify its baud rate? Thanks.
Last edited by mldemarie on Mon Aug 19, 2013 8:00 pm, edited 1 time in total.

mldemarie
 
Posts: 7
Joined: Fri Aug 16, 2013 11:25 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by mldemarie »

From the link i posted in the reply above it states that "To maintain full transmit speed, HardwareSerial's baud rate should be no greater than NewSoftSerial's" and "AltSoftSerial can tolerate almost 1 bit time latency, so its baud rate must be at least 10 times less than the baud rate used for NewSoftSerial."

If i am interpreting this correctly it is telling me that: (AS)x(10) < NS and HS < NS, where AS is AltSoftSerial, HS is HardwareSerial, and NS is NewSoftSerial (or just SoftwareSerial because i have the newest version). So AltSoftSerial should be the slowest, which is good because the GPS is relatively slow. I believe the Serial Monitor communicates with the HardwareSerial (pins 0 and 1 for Uno) and i can change that to 115200. So how do i change the NewSoftSerial because the GSM library seems to do that for me?

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by adafruit_support_rick »

You should not have any problem with running the GPS at 9600 and the serial console at 115200 (or any other baudrate). The problem with NewSoftSerial/SoftwareSerial is that they rely on software-based bit timing - i.e., an interrupt (as is caused by Hardware Serial or AltSoftSerial) can interfere with that timing.

So, the quote is telling you that *if* you are using software serial together with Hardware Serial, then HS must be no faster than SS. *If* you are using SS with AltSoftSerial, then AS must be running at 1/10 the speed. The reason for this is that HS generates one interrupt per character, but AS generates 10 interrupts per character (1 for each bit).

But, you're not using software serial anymore, so the warning simply does not apply.

I tested AltSoftSerial with our standard example sketches, and it worked with GPS at 9600 and Serial at 115200. I think you did the same?

Regarding the actual problem you describe, I think that you are running into an SRAM issue. Please have a look at our new tutorial on Arduino memory for some tips on how to solve the problem!
http://learn.adafruit.com/memories-of-an-arduino

User avatar
paulstoffregen
 
Posts: 444
Joined: Sun Oct 11, 2009 11:23 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by paulstoffregen »

If you're running out of RAM, one of the contributors is AltSoftSerial. Internally, it allocates 2 buffers for transmit and receive. The defaults are 80 and 68 bytes:

Code: Select all

#define RX_BUFFER_SIZE 80
static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];

Code: Select all

#define TX_BUFFER_SIZE 68
static volatile uint8_t tx_buffer[RX_BUFFER_SIZE];
If you don't need this much buffering (if your code checks for incoming data pretty rapidly, or can tolerate waiting to transmit, which happens anyways with SoftwareSerial), then it's ok to reduce these buffer sizes to save RAM.

Now I'm going to make a shameless plug... you might consider using Teensy 3.0 (full disclosure: I'm the creator). It costs less than Arduino Uno, but has 8 times as much RAM. It has 3 hardware serial ports, and its copy of SoftwareSerial automatically uses the real serial port if you specify a pair of pins that correspond to a real port. When you use these types of libraries written for Uno with SoftwareSerial, all you have to do is set the pin numbers and you get the highly reliable and CPU efficient use of real hardware serial ports! The first of its 3 hardware serial ports ("Serial1") even has a built-in FIFO that makes it efficient for really fast baud rates, which is a feature no official Arduino board has. Teensy 3.0 is based on the more advanced ARM processor, which is substantially faster, and also places ordinary strings automatically in flash memory, not RAM as they are by default on Arduino Uno. You can get that on Uno by editing the strings with F(), one at a time, but on Teensy3 none of them eat away at the RAM.

Of course, there are some differences with Teensy 3.0, the main one being 3.3 volt signals instead of 5 volts. It's also off the well-traveled path of Arduino Uno, so some libraries are written originally for only Uno and need to be modified. If you give it a try anyway and run into any library that doesn't work, just let me know and I'll take a look. I can usually come up with a fix pretty quickly.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by adafruit_support_rick »

I would certainly start by F("")-ing all the literal string - you've got a lot of them. But something that isn't mentioned in the Arduino Memories guide is the string library. You've got several objects types as "String", and it is my understanding that the String data-type is quite the SRAM hog. The String methods are convenient, but if you can get away with regular C strings and C library tring functions, you can probably save yourself a significant amount of RAM.

I don't know - you may not have even realized that there was a difference between "String" and "char*", but there is. The String library is a C++ class, and the actual string representation is more complex than a simple char str[] = "Hello World".

The Memory tutorial talks about heap fragmentation - you do a lot of this sort of thing: cmd3 = String("");, adminPW = String(charBuff);, etc. Each one of those represents a dynamic allocation from the heap, so your heap will fragment pretty quickly.

Looks like the only thing you really do with the strings is comparisons to other strings, and finding substrings. The equivalent C library functions would be strncmp and strstr.
Last edited by adafruit_support_rick on Tue Aug 20, 2013 1:49 pm, edited 1 time in total.
Reason: typo

User avatar
paulstoffregen
 
Posts: 444
Joined: Sun Oct 11, 2009 11:23 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by paulstoffregen »

I put a reserve() function in String, but sadly the Arduino folks never published any info about it on their reference page. Yes, Tom and I exchanged many messages about it (years ago), even several drafts of text to published, but sadly it was all in vain. None of that made it onto the Arduino website. Nobody seems to know about String reserve().

The idea is you can prevent String from fragmenting the heap by using reserve(num) to pre-allocate memory for a String that grows. With the memory already allocated, String doesn't need to call realloc() as you add more stuff onto the string or make other changes that increase its length. In most usages, lots of other little String objects are used temporarily as you do stuff, which would cause growing a previously created String to move to fresh new memory, leaving a big hole where the previous one was (memory fragmentation). Usually all you need to do is use reserve() on any long-lived String objects that you know will be increasing in length as you process text.

It's also a good idea with String create any ojbects that hold data only temporarily as local scope variables. Ideally, they should be inside the smallest area of curly braces where they're needed. When a String object goes out of scope, its memory is reclaimed, which prevents it from contributing to memory fragmentation if others are allocated.

You can do better with C strings, but if you just follow these guidelines for String objects, they work nearly as efficiently and using them is so much easier.

(Rick, feel free to add any parts of this to Adafruit's tutorial)

mldemarie
 
Posts: 7
Joined: Fri Aug 16, 2013 11:25 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by mldemarie »

Thanks guys. I've confirmed that running out of SRAM is my problem. I've read all your comments and think i should be able to find a solution. Thanks again.

User avatar
adafruit_support_bill
 
Posts: 88091
Joined: Sat Feb 07, 2009 10:11 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by adafruit_support_bill »

Thanks Paul, I'll add this information to the tutorial.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by adafruit_support_rick »

paulstoffregen wrote:(Rick, feel free to add any parts of this to Adafruit's tutorial)
Yes - I've been discussing this with Bill. String reserve() will definitely make it into the tutorial. I had absolutely no idea about that feature. Thanks for the tip - I may start using the library now...

mldemarie
 
Posts: 7
Joined: Fri Aug 16, 2013 11:25 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by mldemarie »

I've manage to save some SRAM, just enough to get what i have working, but i would like to add one more feature and may run out again. So i'm right at the edge of my limit.
So here is another shot in the dark. Would it be possible to avoid using the AltSoftSerial for the GPS and instead share the SoftwareSerial with the GSM ? One the main site for the SoftwarSerial notes it says "If using multiple software serial ports, only one can receive data at a time." implying you can setup multiple software serial connections and switch between them.
First, would this save a considerable amount of SRAM? I did testing betwen SoftSerial and AltSoftSerial and concluded that AltSoftSerial usesd about 100 Bytes more SRAM than SoftwareSerail. However if i got ride of AltSoftSerial altogether i imagine i could save a larger chunk of SRAM. I would try this myself via testing except i'm having difficulty figure out how to re-establish the GSM serial communication because it is done automatically in the GSM library for pins 2 and 3. If for example i was using two GPS or any two other components i could just define mySerial1 and mySerial2, then switch between them.
Also while i'm thinking of other options i found this board geogram board:
http://dsscircuits.com/geogram-one.html
It has the GPS, GSM and atmega328p all on on board. After some research it looks like they used the HardwareSerial communication for the GPS and SoftwareSerial for the GSM. Would it be possible to use the HardwareSerial communication? If i understand how this works, the HardwareSerial (pins 0 & 1) and used for the serial monitor communication. Is it possible to attach the GPS with the HardwareSerial also or would i have to give up using the serial monitor to do so? I would imagine that using Hardware communication would save me the most SRAM. In the end, i wont need the serial monitor since i'm just using it for debugging purposes, so i could possibly use the AltSoftSerial temporarily to communicate with the serial monitor and give the GPS the HardwareSerial.

I'm just blabbing out idea's, can anyone shine some light on any of them that may be plausible solutions?

Sorry for the trouble, but if possible i would prefer to keep using ATmega328 since i'm familiar with it, so i would like to double check if i have any other options before having to switch microcontrollers. Thank you all !

User avatar
adafruit_support_bill
 
Posts: 88091
Joined: Sat Feb 07, 2009 10:11 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by adafruit_support_bill »

Not familiar with AltSoftSerial, but Software Serial uses one receive buffer and you 'listen' on only one serial channel at a time. Incoming data on other channels is lost during that time. You can use hardware serial, but it makes debugging via serial monitor difficult to impossible.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by adafruit_support_rick »

mldemarie wrote:I would imagine that using Hardware communication would save me the most SRAM. In the end, i wont need the serial monitor since i'm just using it for debugging purposes, so i could possibly use the AltSoftSerial temporarily to communicate with the serial monitor and give the GPS the HardwareSerial.
That would be your best plan.
mldemarie wrote:Would it be possible to avoid using the AltSoftSerial for the GPS and instead share the SoftwareSerial with the GSM ? One the main site for the SoftwarSerial notes it says "If using multiple software serial ports, only one can receive data at a time." implying you can setup multiple software serial connections and switch between them.
Well, the original problem is that you can't "share" SoftwareSerial and GSMSoftwareSerial. But, even if you could work around that it wouldn't save you any SRAM. The drivers themselves reside in flash memory. What is taking up SRAM space are the transmit and receive buffers, and you would still need separate buffers for GSM and GPS.

One thing you can do is reduce the size of the transmit buffer in AltSoftSerial. Typically, you only transmit to the GPS at startup, and it's not a big deal if your GPS.print calls aren't buffered. They'll just take a little longer, is all.

If you look at AltSoftSerial.cpp, you'll find the definition of the transmit buffer size (and a bug!) at line 53:

Code: Select all

#define TX_BUFFER_SIZE 68
static volatile uint8_t tx_buffer[RX_BUFFER_SIZE];
I haven't really analyzed the logic, but a value of 2 should be safe for TX_BUFFER_SIZE (it can't be 0). Also note the typo in the next line - it should be TX_BUFFER_SIZE in the array declaration:

Code: Select all

#define TX_BUFFER_SIZE 2
static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
RX_BUFFER_SIZE is defined as 80, so by fixing the typo and setting the tx buffer to 2, you've saved 78 bytes of SRAM

If you're absolutely certain that your sketch can keep up, you can also reduce the size of the AltSoftSerial receive buffer. RMC sentences max out around 80 characters. It takes around 80ms to transfer 80 bytes at 9600bps. If your sketch can guarantee that it will be able to read out the entire receive buffer, say, every 40ms, then you theoretically only need a 40 byte input buffer. If you get desperate, you could try experimenting with squeezing a few bytes out of the receive buffer

munkee
 
Posts: 14
Joined: Tue Sep 03, 2013 4:34 pm

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by munkee »

Hi Guys,

I too have tried to follow the instructions but keep hitting problems. I have replaced the software serial references with altsoftserial as described earlier in the adafruit gps libraries.


I now hit one of two issues.

Code: Select all

//SoftwareSerial mySerial(2, 3); //Software serial setup on pin 2 and 3
AltSoftSerial mySerial;  // Arduino Uno        9         8         10
SoftwareSerial gprsSerial(2, 3); //Software serial setup on pin 9 and 10

Adafruit_GPS GPS(&mySerial);//Setup connection as gps
GSMClient client(&gprsSerial);
GPRS gprs(&gprsSerial);
GSM gsmAccess(&gprsSerial);
If I do the above I hit an error on "GPRS gprs(&gprsSerial);" which is:
GPS_Tracker_Edited_ino:33: error: no matching function for call to 'GSM3ShieldV1DataNetworkProvider::GSM3ShieldV1DataNetworkProvider(SoftwareSerial*)'

If I change this to GPRS gprs; I then get the following error:
GPS_Tracker_Edited_ino:229: error: request for member 'attachGPRS' in 'gprs', which is of non-class type 'GSM3ShieldV1DataNetworkProvider ()()'

On my line of code here:

Code: Select all

 if((gsmAccess.begin("")==GSM_READY) & (gprs.attachGPRS("giffgaff.com", "giffgaff", "password")==GPRS_READY))
The full code can be seen in the link below but there is quite a lot... The sketch will upload gps data to xivley.

http://BANNED.com/u0HgUVAt

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Error w/ Adafruit GPS Library & GSM Library together

Post by adafruit_support_rick »

Code: Select all

GSMClient client(&gprsSerial);
GPRS gprs(&gprsSerial);
GSM gsmAccess(&gprsSerial);
I don't know the gsm library, but I don't think you're supposed to pass a software serial port to the constructors.
I think you should just be doing this:

Code: Select all

GSMClient client;
GPRS gprs;
GSM gsmAccess;

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”