Can GSM sim900 and GPS neo 6m work together with arduino uno

I'm tring to make a project where i senscor can detect alcool then send GPS location via message.
the problem I have is that i use GSM sim900 and GPS neo 6m. two software serials with arduino uno.
Gsm work and send me a message but GPS don't and I got 0 latitude and 0 longitude.
please if someone can help me. I need this project tomorrow in my school and I'm still a biginner working on this code for so long time and can't work.

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
float gpslat, gpslon;

static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

#define Sober 120   // Define max value that we consider sober
#define Drunk 400   // Define min value that we consider drunk
#define MQ3pin 0

float sensorValue;  //variable to store sensor value

int buzzer = 6 ;
int arret =0; 
int left=0;
int test=0;

// The serial connection to the GPS device
SoftwareSerial ss(4,3);
SoftwareSerial mySerial(7, 8); //SIM900 Tx & Rx is connected to Arduino #7 & #8
void setup()
{
  Serial.begin(115200);
  ss.begin(GPSBaud);
  ss.listen();
  Serial.println(TinyGPSPlus::libraryVersion());
  mySerial.begin(9600);
  pinMode (buzzer, OUTPUT);
  mySerial.println("AT"); //Handshaking with SIM900
  updateSerial();
  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  Serial.println();
}

void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  while (ss.available() > 0)
    if (gps.encode(ss.read()))
    {
      displayInfo();
      Alcool();
    }

  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    while(true);
  }
}


void displayInfo()
{
  Serial.print(F("Location: ")); 
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}


void Alcool()
{
  unsigned char i ;
  sensorValue = analogRead(MQ3pin); // read analog input pin 0
  // This sketch displays information every time a new sentence is correctly encoded.
 
  if (test==1 && sensorValue < Sober && left==0){
    Serial.print("Sensor Value: ");
    Serial.print(sensorValue);
    Serial.println("  |  Status: Stone Cold Sober");
    digitalWrite (buzzer, LOW);
  }else if (test==1 && sensorValue >= Sober && sensorValue < Drunk && left==0){
    Serial.print("Sensor Value: ");
    Serial.print(sensorValue);
    Serial.println("  |  Status: Drinking but within legal limits");
    digitalWrite (buzzer,LOW);
    delay (2000);
  }else if (test==1 && sensorValue > Drunk && arret ==0){
    left=1;
    Serial.print("Sensor Value: ");
    Serial.print(sensorValue);
    Serial.println("  |  Status: DRUNK");
     for (i = 0; i <80; i++) // When a frequency sound
    {
      digitalWrite (buzzer, HIGH) ; //send tone
      delay (1) ;
      digitalWrite (buzzer, LOW) ; //no tone
      delay (1) ;
    }
    arret=1;
    sentmessage();
}
}

void sentmessage(){
  while(gps.location.isValid()){
  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CMGS=\"+212629401666\"");//change ZZ with country code and xxxxxxxxxxx with phone number to sms
  updateSerial();
  mySerial.print("https://www.google.com/maps/?q="); //text content
  mySerial.print(gps.location.lat(), 6);
  mySerial.print(gps.location.lng(), 6);
  updateSerial();
  mySerial.write(26);
  }
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

Trying to use 2 instances of SoftwareSerial on an Uno is an uphill battle. We have seen this over and over and it rarely turns out well. You are much better off choosing an Arduino board multiple hardware serial ports.

That said, the SoftwareSerial Two Port Receive example shows how to switch between software serial ports.

This looks like a problem:

 while(gps.location.isValid()){

Once you have a location, I suspect that the GPS will never be read again, unless perhaps there's a timeout.

looks that I should change my arduino
can you please tell me which arduino gonna work for my case? should I change the code to make it suitable for a different arduino?

With multiple SoftwareSerial ports, you need to call the listen() function before you can read from the port.

1 Like

Can you please show me where I should call it in the code?

you could make it work in your special case

the code would monitor the Sensor and listen to the GPS at the same time and keep in memory the last valid fix.

when the sensor is triggered, you end the GPS software serial instance and start the one for the GPRS and send the SMS and then end it and revert to the GPS (use listen for that, SoftwareSerial doesn't support .end() )

➜ so only 1 Software Serial line is really active

alternatively (if you don't catch communication errors) you could have on your uno the SoftwareSerial Rx connected to the Tx of the GPS (because you never talk to the GPS anyway) and the SoftwareSerial Tx connected to the Rx of the sim900. This way you can send AT commands to the sim900 (but will never hear back if all went well or not, you are in the dark).

this way you need only 1 SoftwareSerial instance.

Of course you coud decide to not use the Serial monitor at all and use the Hardware Serial for that...

1 Like

I linked the two port receive example that shows how to use the listen() function in post #2.

1 Like

I tried to modify the code but I alwys get invalid location.
`

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
float gpslat, gpslon;

static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

#define Sober 120   // Define max value that we consider sober
#define Drunk 400   // Define min value that we consider drunk
#define MQ3pin 0

float sensorValue;  //variable to store sensor value

int buzzer = 6 ;
int arret =0; 
int left=0;
int test=0;

// The serial connection to the GPS device
SoftwareSerial ss(4,3);
SoftwareSerial mySerial(7, 8); //SIM900 Tx & Rx is connected to Arduino #7 & #8
void setup()
{
  Serial.begin(115200);
  pinMode (buzzer, OUTPUT);
  ss.begin(GPSBaud);
  ss.listen();
  Serial.println(TinyGPSPlus::libraryVersion());
  GGP();
  displayInfo();
  ss.end();
  mySerial.begin(9600);
  mySerial.println("AT"); //Handshaking with SIM900
  updateSerial();
  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  Serial.println();
}

void loop()
{
  unsigned char i ;
  sensorValue = analogRead(MQ3pin); // read analog input pin 0
  // This sketch displays information every time a new sentence is correctly encoded.
 
  if (test==1 && sensorValue < Sober && left==0){
    Serial.print("Sensor Value: ");
    Serial.print(sensorValue);
    Serial.println("  |  Status: Stone Cold Sober");
    digitalWrite (buzzer, LOW);
  }else if (test==1 && sensorValue >= Sober && sensorValue < Drunk && left==0){
    Serial.print("Sensor Value: ");
    Serial.print(sensorValue);
    Serial.println("  |  Status: Drinking but within legal limits");
    digitalWrite (buzzer,LOW);
    delay (2000);
  }else if (test==1 && sensorValue > Drunk && arret ==0){
    left=1;
    Serial.print("Sensor Value: ");
    Serial.print(sensorValue);
    Serial.println("  |  Status: DRUNK");
     for (i = 0; i <80; i++) // When a frequency sound
    {
      digitalWrite (buzzer, HIGH) ; //send tone
      delay (1) ;
      digitalWrite (buzzer, LOW) ; //no tone
      delay (1) ;
    }
    arret=1;
    sentmessage();
    
}
}

void GGP()
{
while (ss.available() > 0)
    if (gps.encode(ss.read()))
      displayInfo();
      
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    while(true);
  }
}


void displayInfo()
{
  Serial.print(F("Location: ")); 
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
    gpslat= gps.location.lat();
    gpslon= gps.location.lng();
  }
   else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}



void sentmessage(){
  while(gps.location.isValid()){
  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CMGS=\"+212629401666\"");//change ZZ with country code and xxxxxxxxxxx with phone number to sms
  updateSerial();
  mySerial.print("https://www.google.com/maps/?q="); //text content
  mySerial.print(gpslat, 6);
  mySerial.print(gpslon, 6);
  updateSerial();
  mySerial.write(26);
  }
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}`

That likely means that your GPS cannot get a lock. Is your GPS outdoors with a clear line of sight view of the sky? GPS unit will probably not work indoors.

1 Like

yes, i'm testing it outside with a clear sky view
i got the data when i test GPS alone but it doesn't work when i test it with gsm

these is what it gives

1.0.2
Location: INVALID  Date/Time: INVALID INVALID
AT

OK
AT+CMGF=1

OK
SoftwareSerial ss(4, 3);
ss.begin(GPSBaud);
ss.listen();
ss.end();
while (ss.available() > 0)
      if (gps.encode(ss.read()))

You open the ss port, set it to listen, close (end) the ss port, then check for bytes available in the ss port. Can you read form a closed (disabled) port?

See the Serial reference for the end function.

I suggest that you revisit post #7 and seriously consider the suggestions made by @J-M-L. If you use only one software serial port you could simplify your life.

Do less. You have too much code there for something that doesn't work. Try and write something that reads the GPS and once every so often sends a fixed SMS message perhaps.

Get rid of the delays. They guarantee that you will drop data from the GPS and find it hard or impossible to get a fix.

Reflect on the fact that you are listening to the GPS only and sending to the SMS. You don't actually need to listen to the SMS once you have it working. In consequence, one softwareSerial instance will do. If you're prepared to sacrifice debug output, you can actually just use the hardware serial port.

Really though, just spring for something with multiple hardware serial ports. Teensy perhaps.

To be honest, this is the first time writing an arduino code
I hardly can understand your advices
I will so thankful if you can rewrite the code for me. I'm trying for more than i week and i can't really understand

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.