Accelerometer and GPS clash

Hello,
I am attempting to make my Arduino uno interact with both a Adafruit ultimate GPS and a sparkfun Breakout ADXL345 accelerometer.

individually both work like a charm (even when both are wired up). However when my program runs them together the GPS does not receive any data.

I'm not sure where the problem is coming from, any help would be great.

Thanks
John

Any code or schematic would be even better.

#include <SoftwareSerial.h>
#include <String.h>
#include <Adafruit_GPS.h>
#include <Wire.h>
#include <ADXL345.h>

const String APN = "giffgaff.com";
const String server = "blue.appspot.com/register";
int latitude;
int longitude;
boolean finished;

SoftwareSerial gprsSerial(7, 8);
SoftwareSerial gpsSerial(3, 2);
ADXL345 adxl;
Adafruit_GPS GPS(&gpsSerial);

//accelerometer varibales
  int x, y, z;
  int tempZ;

//gps stuff
#define GPSECHO  true
boolean usingInterrupt = true;
void useInterrupt(boolean);


void setup()
{
  Serial.begin(115200);
  //gps setup
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
  useInterrupt(true);
  delay(1000);
  
  //gprs setup
  gprsSerial.begin(19200);
  
  //accelerometer setup
  adxl.powerOn();
  delay(500);
  adxl.setActivityThreshold(75); //62.5mg per increment
  adxl.setInactivityThreshold(75); //62.5mg per increment
  adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?
 
  //look of activity movement on this axes - 1 == on; 0 == off 
  adxl.setActivityX(1);
  adxl.setActivityY(1);
  adxl.setActivityZ(0);
 
  //look of inactivity movement on this axes - 1 == on; 0 == off
  adxl.setInactivityX(1);
  adxl.setInactivityY(1);
  adxl.setInactivityZ(1);
 
  //look of tap movement on this axes - 1 == on; 0 == off
  adxl.setTapDetectionOnX(0);
  adxl.setTapDetectionOnY(0);
  adxl.setTapDetectionOnZ(1);
 
  //set values for what is a tap, and what is a double tap (0-255)
  adxl.setTapThreshold(50); //62.5mg per increment
  adxl.setTapDuration(15); //625?s per increment
  adxl.setDoubleTapLatency(80); //1.25ms per increment
  adxl.setDoubleTapWindow(200); //1.25ms per increment
 
  //set values for what is considered freefall (0-255)
  adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment
 
  //setting all interupts to take place on int pin 1
  //I had issues with int pin 2, was unable to reset it
  adxl.setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_DOUBLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_FREE_FALL_BIT,    ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_ACTIVITY_BIT,     ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN );
 
  //register interupt actions - 1 == on; 0 == off  
  adxl.setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_DOUBLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_FREE_FALL_BIT,  1);
  adxl.setInterrupt( ADXL345_INT_ACTIVITY_BIT,   1);
  adxl.setInterrupt( ADXL345_INT_INACTIVITY_BIT, 1);
}

SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
    // writing direct to UDR0 is much much faster than Serial.print 
    // but only one character can be written at a time. 
#endif
}
void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();

void loop()
{
  byte interruptss = adxl.getInterruptSource();
  
  if (adxl.triggered(interruptss, ADXL345_INACTIVITY)){
    Serial.println("nothing going on here");
    delay(1000);
    return;
  }
  
  if (adxl.triggered(interruptss, ADXL345_FREE_FALL) || adxl.triggered(interruptss, ADXL345_ACTIVITY) || adxl.triggered(interruptss, ADXL345_DOUBLE_TAP) || adxl.triggered(interruptss, ADXL345_SINGLE_TAP)){
    Serial.println("movement sensed");
    
    finished = false;
    getGpsCoordinates();
    while(!finished) {
     delay(1000); 
    }
    
    finished = false;
    submitHttpRequest();
        while(!finished) {
     delay(1000); 
    }
  }
  
  delay(2000);
}

void submitHttpRequest(){

  Serial.println("sending HTTP request");
  
gprsSerial.println("AT+CSQ");
  delay(100);
 
  ShowSerialData();// this code is to show the data from gprs shield, in order to easily see the process of how the gprs shield submit a http request, and the following is for this purpose too.
 
  gprsSerial.println("AT+CGATT?");
  delay(100);
 
  ShowSerialData();
 
  gprsSerial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");//setting the SAPBR, the connection type is using gprs
  delay(1000);
 
  ShowSerialData();
 
  gprsSerial.println("AT+SAPBR=3,1,\"APN\",\""+APN+"\"");//setting the APN, the second need you fill in your local apn server
  delay(4000);
 
  ShowSerialData();
 
  gprsSerial.println("AT+SAPBR=1,1");//setting the SAPBR, for detail you can refer to the AT command mamual
  delay(2000);
 
  ShowSerialData();
 
  gprsSerial.println("AT+HTTPINIT"); //init the HTTP request
 
  delay(2000); 
  ShowSerialData();
 
  gprsSerial.println("AT+HTTPPARA=\"URL\",\""+server+"?regId=123&serial=1\"");// setting the httppara, the second parameter is the website you want to access
  delay(2000);
 
  ShowSerialData();
 
  gprsSerial.println("AT+HTTPACTION=0");//submit the request 
  delay(10000);//the delay is very important, the delay time is base on the return from the website, if the return datas are very large, the time required longer.
  //while(!mySerial.available());
 
  ShowSerialData();
 
  gprsSerial.println("AT+HTTPREAD");// read the data from the website you access
  delay(300);
 
  ShowSerialData();
 
  gprsSerial.println("");
  delay(100);
  
  finished = true;
}
 
void ShowSerialData()
{
  while(gprsSerial.available()!=0)
    Serial.write(gprsSerial.read());
}

void getGpsCoordinates(){
  while(!finished){
    // in case you are not using the interrupt above, you'll
    // need to 'hand query' the GPS, not suggested :(
    if (! usingInterrupt) {
      // read data from the GPS in the 'main loop'
      char c = GPS.read();
      // if you want to debug, this is a good time to do it!
      if (GPSECHO)
        if (c) Serial.print(c);
    }
    // if a sentence is received, we can check the checksum, parse it...
    if (GPS.newNMEAreceived()) {
      // a tricky thing here is if we print the NMEA sentence, or data
      // we end up not listening and catching other sentences! 
      // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
      //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
    
      if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
        return;  // we can fail to parse a sentence in which case we should just wait for another
    }
  
    // if millis() or timer wraps around, we'll just reset it
    if (timer > millis())  timer = millis();
  
    // approximately every 2 seconds or so, print out the current stats
    if (millis() - timer > 2000) { 
      timer = millis(); // reset the timer
      if (GPS.fix){
        latitude = GPS.latitude;
        longitude = GPS.longitude;
        Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
        Serial.print(", "); 
        Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
        Serial.print(GPS.hour, DEC); Serial.print(':');
        Serial.print(GPS.minute, DEC); Serial.print(':');
        Serial.print(GPS.seconds, DEC); Serial.print('.');
        finished = true;
      }
    }
  }
}

Sorry about the messy code, There are three tutorials put together. each one works great alone but I can't get them to work together.

Mmmm, sticking tutorials together leaves a lot of room for problems.

My first idea is that Wire is using the same timer and/or interrupts as software serial. You may have better luck at lower baud rate.

If not get rid of the two commands sent to the GPS unit, and then connect the RX of the arduino to the tx of the GPS and copy the data from Serial in (now the GPS) to serial out. But you must drop the baud rate to 9600.

Mark

Hello Holmes,

Thanks for your reply.
As suggested I lowered the baud rate of the Serial but sadly this has not worked.
I would like to try your other solution but I do not understand it fully.
if you could rephrase in layman's terms I would very much appreciate it.

I have joined the tutorials for the wiring I have used.
The only addition is that I have wired the SD0 port on the accelerometer to ground. (not sure why but this is the only way I could get it to work)

Also I am using a gsm sheild v2 seedstudio to send the GPS coordinates to my server.

You have a cell modem and a GPS both on software serial. You are not switching between the two so you will only listen to one of them, not both.

Read limitations:

Then read listen().

Still, I worry you can't do both together, if you intend to receive from both. Go get a mega2560. ShowSerialData() is going to block the GPS software serial so you can't get both. Just go get a mega2560.

Big thank you to Liudr and Holmes for their help.
I am really amazed at the enthusiasm and reactivity of this community.

I have overcome the GPS no data problem by switching between software serial for the GSM shield and GPS.

I am however slightly puzzled at the GPS readings I'm getting. When the GPS is on the window sill it can pick up a signal and find my location, but when I place the device inside the room it still reports seeing multiple satellites and receiving data. I think I need a way of clearing cached GPS info between GPS searches.

here is my latest code a lot neater than earlier.

#include <SoftwareSerial.h>
#include <String.h>
#include <Adafruit_GPS.h>
#include <ADXL345.h>
#include <Wire.h>

//GSM Shield vars
const String APN = "giffgaff.com";
const String server = "blue.appspot.com/updateArduinoCoords";
boolean sent;
SoftwareSerial gprsSerial(7, 8);

//accelerometer
ADXL345 adxl;

//GPS variables
boolean isSignal;
int latitude;
int longitude;
String time;
SoftwareSerial gpsSerial(3, 2);
Adafruit_GPS GPS(&gpsSerial);

void setup(){
//  Serial.begin(115200);    // remove commenting to get print trace
  
  //GSM 
  gprsSerial.begin(19200);
  
  //GPS
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
  delay(500);
  
  //Accelerometer
  adxl.powerOn();
  delay(500);
  adxl.setActivityThreshold(75); //62.5mg per increment
  adxl.setInactivityThreshold(75); //62.5mg per increment
  adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?
  //look of inactivity movement on this axes - 1 == on; 0 == off
  adxl.setInactivityX(1);
  adxl.setInactivityY(1);
  adxl.setInactivityZ(1);
  //look of tap movement on this axes - 1 == on; 0 == off
  adxl.setTapDetectionOnX(0);
  adxl.setTapDetectionOnY(0);
  adxl.setTapDetectionOnZ(1);
  //set values for what is a tap (0-255)
  adxl.setTapThreshold(50); //62.5mg per increment
  adxl.setTapDuration(15); //625?s per increment
  //setting all interupts to take place on int pin 1
  //I had issues with int pin 2, was unable to reset it
  adxl.setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN );
  //register interupt actions - 1 == on; 0 == off  
  adxl.setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_INACTIVITY_BIT, 1);
}

void loop(){
  byte interrup = adxl.getInterruptSource();
  
  if (adxl.triggered(interrup, ADXL345_INACTIVITY)){
//    Serial.println("nothing going on here");
    delay(1000);
    return;
  }

  if (adxl.triggered(interrup, ADXL345_SINGLE_TAP)){
//    Serial.println("movement detected");
    gpsSerial.listen();
    isSignal = false;
    getCoordinates();
    while(!isSignal){
      delay(1000);
    }
    powerUp();
    gprsSerial.listen();
    sent = false;
    sendCoordinates();
    while(!sent){
      delay(1000);
    }
  }
}


void getCoordinates(){
  while(!isSignal){
    char c = GPS.read();
    if (GPS.newNMEAreceived()) {
//      Serial.println("new NMEA");
      if (!GPS.parse(GPS.lastNMEA())){
//        Serial.println("parse failed");
      }
      else{
        if(GPS.fix){
          
          longitude = GPS.longitude;
          latitude = GPS.latitude;
          time = ""+(GPS.hour, DEC)+':'+(GPS.minute, DEC)+':'+(GPS.seconds, DEC);
          
//          Serial.println(GPS.latitude, 6); Serial.print(GPS.lat);
//          Serial.print(", "); 
//          Serial.print(GPS.longitude, 6); Serial.println(GPS.lon);
//          Serial.print(GPS.hour, DEC); Serial.print(':');
//          Serial.print(GPS.minute, DEC); Serial.print(':');
//          Serial.print(GPS.seconds, DEC); Serial.print('.');
//          Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
//          Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
//          Serial.println("\n");
          delay(500);
          isSignal = true;
        }
      }
    }
  }
}

void sendCoordinates(){

//  Serial.println("sending HTTP request"); 
  gprsSerial.println("AT+CSQ");
  delay(100);
  ShowSerialData();// this code is to show the data from gprs shield, in order to easily see the process of how the gprs shield submit a http request, and the following is for this purpose too.
 
  gprsSerial.println("AT+CGATT?");
  delay(100);
  ShowSerialData();
 
  gprsSerial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");//setting the SAPBR, the connection type is using gprs
  delay(1000);
  ShowSerialData();
 
  gprsSerial.println("AT+SAPBR=3,1,\"APN\",\""+APN+"\"");//setting the APN, the second need you fill in your local apn server
  delay(4000);
  ShowSerialData();
 
  gprsSerial.println("AT+SAPBR=1,1");//setting the SAPBR, for detail you can refer to the AT command mamual
  delay(2000);
  ShowSerialData();
 
  gprsSerial.println("AT+HTTPINIT"); //init the HTTP request
  delay(2000); 
  ShowSerialData();
 
  gprsSerial.println("AT+HTTPPARA=\"URL\",\""+server+"?serial=1&lat="+latitude+"&lng="+longitude+"&timestamp="+time+"\"");// setting the httppara, the second parameter is the website you want to access
  delay(2000);
  ShowSerialData();
 
  gprsSerial.println("AT+HTTPACTION=0");//submit the request 
  delay(10000);//the delay is very important, the delay time is base on the return from the website, if the return datas are very large, the time required longer.
  ShowSerialData();
 
  gprsSerial.println("AT+HTTPREAD");// read the data from the website you access
  delay(300);
  ShowSerialData();
 
  gprsSerial.println("");
  delay(100);
  
  powerDown();
  sent = true;
}

void ShowSerialData()
{
//  while(gprsSerial.available()!=0)
//    Serial.write(gprsSerial.read());
}

/*
turn on the GPRS Shield
*/
void powerUp()
{
 pinMode(9, OUTPUT); 
 digitalWrite(9,LOW);
 delay(1000);
 digitalWrite(9,HIGH);
 delay(2000);
 digitalWrite(9,LOW);
 delay(3000);
}
/*
turn off the GPRS Shield
*/
void powerDown()
{
 pinMode(9, OUTPUT); 
 digitalWrite(9,LOW);
 delay(1000);
 digitalWrite(9,HIGH);
 delay(2000);
 digitalWrite(9,LOW);
 delay(3000);
}

You are welcome! The gps library could be caching last known locations. Look into the library.