Help with a GSM-GPS and I2C interfacing.

I'm an absolute beginner is using arduino. I'm creating this device which uses multiprocessor mode. The master in the I2C has a GSM modem hooked up to it. The slave has a GPS as well as an HCSR04 sensor connected. HCSR04 senses the distance of the obstacles around and when the distance is within a defines limit, it powers up the LED. Now The master sends the request to slave every 1 minute, and then slave activates the GPS and then sends the co-ordinates to the master. Now I encountered following problems-

  1. After 1 minute after powering up the circuit, the led glowing stops and that stops forever. The stopping of the led operation probably indicates the slave is busy taking the coordinates. But it seems like it's caught in a loop.
  2. I'm getting the whole co-ordinates in the garbage form. The specific data is repeating. For example I get data like 020202020202020 or 198198198198........ like this. I've used the GPS code that I found on arduino.cc itself and it was for seperating the co-ordinates and writing them in sorted fashion but nothing is happening.
  3. The Master doesn't seem to receive the data, as the message isn't getting sent.

I'm using two arduino UNOs and I'm giving a 9V supply to them. The supply and other stuff isn't a problem as it seems to work just fine. I'm attaching a copy of the code.

Here's the code for MASTER-

#include <Wire.h>
#include<ctype.h>
//#include<Wire.h>
unsigned long t1, time;//variables for delay generation
int i = 0;
int data[100];// Stores the data of GPS received from slave
char msg[100];// Stores the ASCII converted message
void setup() {
  // initialize serial communication
  Serial.begin(9600);
  Wire.begin();
  Serial.print("\r");
  delay(1000);
  Serial.print("AT+CMGF=0\r");
  delay(1000);

}
void loop()//This loop uses the millis function and creates the delay of 1 minute
{
  t1 = millis() / 1000;
  while (((millis() / 1000) - t1) < 60);
  time++;

  if (time == 1) {
    message();
    time = 0;
  }
}




void message()// It requests data and sends the message using GSM modem
{
  Wire.requestFrom(8,100);// Master requests the data from the slave
  while (Wire.available()){}//check if message is available
  
    for (i = 0; i < 100; i++)
    {
      data[i] = Wire.read();// Read the data
      msg[i]=data[i]+48;//Convert to ASCII for sending to GSM
    }

  
  Serial.print("AT+CMGS=\"+918275256645\"\r");    //Number to which you want to send the sms
  delay(1000);
   for(i=0;i<100;i++)
   {
   Serial.print(msg[i]);//The text of the message to be sent
   }
  Serial.print("");
  delay(1000);
  Serial.write(0x1A);
  delay(1000); 
}

And the SLAVE code-

#include<Wire.h>
#include<string.h>
#include<ctype.h>
int gps=-1;//the variable where we store a single byte of GPS data
int i=0;
char cmd[7]="$GPRMC";
char buf[100];// To store the GPS data.
int ind=10;
int cont=0;
int cont1=0;
int cont2=0;
int data;
int indices[13];
char dat[100];
const int trigPin = 13;//The trigger of HCSR04
int echoPin = 12;//The echo of HCSR04
int motor=7;// Motor or LED is connected to Pin no.7
void setup() {
  // put your setup code here, to run once:
pinMode(ind,INPUT);
Wire.begin(8);
Wire.onRequest(gpsfun);
// pinMode(led,OUTPUT);
Serial.begin(4800);
for(int i=0;i<100;i++){
  buf[i]=' ';
}
}

void loop() {
  // put your main code here, to run repeatedly:
 long duration;
 long duration1;
  long cm;
  long cm1;
  //left code 
 // gpsfun();
  pinMode(trigPin, OUTPUT);
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(trigPin, LOW);
  pinMode(echoPin, INPUT);
  duration = pulseIn(echoPin, HIGH);
  cm = (duration/2)/29.1;
 microsecondsToCentimeters(duration);
 if(cm>20)//The distance distinction
 {
  
    digitalWrite(motor,LOW);
    delay(2000);
    digitalWrite(motor,HIGH);
   delay(2000);
  
  }
  else
  {
    digitalWrite(motor,LOW);
    delay(500);
    digitalWrite(motor,HIGH);
    delay(500);
    }
}


void gpsfun(){
while(1)
{
  

  gps=Serial.read();
if(gps==-1)
  delay(100);
else
{
  
  while(cont<100){
  buf[cont1]=gps;
  dat[cont1]=buf[cont1];
  cont1++;
  
   if(gps==13){
    cont1=0;
    cont2=0;
    for(int i=1;i<7;i++){
      buf[i]=cmd[i-1];
      cont2++;
    }
  }
  if(cont2==6){
    for(int i=0;i<300;i++){
      if(buf[i]==','){
        indices[cont1]=i;
        cont1++;
      }
      if(buf[i]=='*'){
        indices[12]=i;
        cont1++;
      }
    }
    Serial.write("");
    Serial.write("");
    Serial.write("-----------");
    for(int i=0;i<12;i++){
      switch(i)
      {
             case 0 :Serial.print("Time in UTC (HhMmSs): ");break;
             case 1 :Serial.print("Status (A=OK,V=KO): ");break;
             case 2 :Serial.print("Latitude: ");break;
             case 3 :Serial.print("Direction (N/S): ");break;
             case 4 :Serial.print("Longitude: ");break;
             case 5 :Serial.print("Direction (E/W): ");break;
             case 6 :Serial.print("Velocity in knots: ");break;
             case 7 :Serial.print("Heading in degrees: ");break;
             case 8 :Serial.print("Date UTC (DdMmAa): ");break;
             case 9 :Serial.print("Magnetic degrees: ");break;
             case 10 :Serial.print("(E/W): ");break;
             case 11 :Serial.print("Mode: ");break;
             case 12 :Serial.print("Checksum: ");break;
      }
      for(int j=indices[i];j<(indices[i-1]-1);j++){
        Serial.print(buf[j+1]);
      }
      Serial.write("");
    }
    Serial.write("-----------");
  }
  cont2=0;
  for(int i=0;i<300;i++){
    buf[i]=' ';
  }
      }
 
  }

  
  while(dat[i]){
  Wire.write(dat[i]);//Send the data using the I2C
  i++;
}
}
}
long microsecondsToCentimeters(long microseconds)//Converts the microsecnds processed by processor into centimeters.
{
   return microseconds / 58.2;

    }

Welcome to the Forum. It's great to start with such an ambitious project, but you are paying the price for skipping the experience of hitting your head on simpler problems first.

The code you have written has no comments. It is hard to read and understand things like:

void loop()
{
  t1 = millis() / 1000;
  while (((millis() / 1000) - t1) < 60);
  time++;

  if (time == 1) {
  //  digitalWrite(ind,HIGH);
    message();
    time = 0;
  }
}

without any explanation of what's going on. I looked at it, but I want you to explain it. If you're going to do that, you might as well do it in the code.

Please read the two posts

How to use this forum - please read.
and
Read this before posting a programming question ...

at the top of this Forum on guidelines for posting here, especially the use of code tags which make the code look

like this

when posting source code files. It makes it easier to read, and can be copied with a single mouse click. Also, if you don't do it, some of the character sequences in the code can be misinterpred by the forum code as italics or funny emoticons.

Many questions can be answered by simply reading the documentation which is provided with the IDE, available under the help tab, or online here.

If you have already posted without using code tags, open your message and select "modify" from the pull down menu labelled, "More", at the lower left corner of the message. Highlight your code by selecting it (it turns blue), and then click on the "</>" icon at the upper left hand corner. Click on the "Save" button.

There are many other things that programmers do to make their code understandable. Please do them, as a courtesy to the members who volunteer their time to help you here. One is to use a standard indentation to clearly show the code blocks. Never put more than one statement per line. Place any brackets by themselves on a separate line. Before posting the code, use Ctrl-T in the IDE to reformat the code in a standard format, which makes it easier for us to read. Another is to give things descriptive names. You can name numerical constants, pin numbers, variables and many other things in this way. For example, you can refer to a pin and an output level by number, like digitalWrite(3,0). But such a statement doesn't reveal anything about the purpose. digitalWrite(hornRelayPin, LOW) does. You can do that by declaring const byte hornRelayPin = 3; before setup() in your program. Many such names are already defined for you by the compiler and the Arduino IDE. Here are some:

#define HIGH 0x1
#define LOW  0x0
#define PI 3.1415926535897932384626433832795

Use them. There are many more. Use compiler math to compute values so you can see where they came from (or at least document them). For example, if you see the number 73, you would be hard put to explain the significance of it. But if you see "daysPerYear/5", it is obvious. One more thing. When you work on program continuously, you become familiar with it. So many things seem obvious even if they are not spelled out explicitly. But try looking at your own code six months later. It will be as if a stranger wrote it. So write for strangers, not yourself.

Thank you and extremely sorry for everyone's inconvenience! I've re-uploaded the code with the necessary comments. I'm still not understanding the GPS part completely, so I didn't write any comments about that. If anything's missing, let me know!

aditya7196:
Thank you and extremely sorry for everyone's inconvenience! I've re-uploaded the code with the necessary comments. I'm still not understanding the GPS part completely, so I didn't write any comments about that. If anything's missing, let me know!

Please post them inline, using code tags as explained in the links. Nobody should be forced to download such small sketches. It's inconvenient.

So here's a short example of what I'm talking about:

int data[100];// Stores the data of GPS received from slave

So, fine. If that's what it is, why not name it appropriately? For example:

int GPSdata[100];//  GPS data received from slave

Data is just data. Actually, data is all you will find in any array.

As far as I can tell, this is all your loop does:

void loop()//This loop uses the delay() function and creates the delay of 1 minute
{
  delay(60L * 1000);
    message();
}

Alright! I inlin'ed' the code. I now ned to know whether the I2C is correctly working or not and the GPS too..

I now ned to know whether the I2C is correctly working or not and the GPS too..

You can NOT read the GPS data in an interrupt handler, which is what onRequest() is.

Your loop() function, on the slave, needs to be reading the data. The onRequest() function needs to return the latest data that loop() found, if it found any good data.

PaulS:
You can NOT read the GPS data in an interrupt handler, which is what onRequest() is.

Your loop() function, on the slave, needs to be reading the data. The onRequest() function needs to return the latest data that loop() found, if it found any good data.

Okay But I need to run both the distance sensing and GPS reception on one ATMEGA only. I can't use any other thing on the MASTER because the GSM operation is going to take considerable amount of time. Can I write the GPS data in a function outside loop() and call it periodically through loop?