SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
By bobxcool
#155706
I need to send data when a condition is met from a gps module to mobile using gsm module.

I have used ports 3,4 for gps and pots 7,8 for gsm. I have used softwareserial.

I also tried 0,1 for gps and 7,8 for gsm; and vice versa.

The problem is that as soon as the condition is satisfied and msg is sent, the program gets stuck, it doesn't return back to the void loop.

So, I tried using goto statement, but am getting compile error



This is message sending function
Code: Select all

boolean policeLights() {

digitalWrite(blue, HIGH);
cell.println("AT+CMGF=1"); // set SMS mode to text
cell.print("AT+CMGS="); // now send message...
cell.write((byte)34); // ASCII equivalent of "
cell.print(mobilenumber);
cell.write((byte)34); // ASCII equivalent of "
cell.println();
delay(500); // give the module some thinking time
cell.print("hi bobby, the king of kings... :-)"); // our message to send
cell.write((byte)26); // ASCII equivalent of Ctrl-Z
cell.println();
delay(15000); // the SMS module needs time to return to OK status
do // do…while loop to send single sms..You don't want to send out multiple SMSs.... or do you?
{
delay(1);
}
while (1>0);
}


I tried using goto mand; at the end of this routine, and I tried to put the label "mand" in the beginning of the void loop function and also before, but I am getting compile errors
Code: Select all
void loop() {

if (readGPS()) {
if (debugMode) {
debug();
}
}

I am confused how to write this goto function. Could anyone help?

Are there any other alternatives?
By Mee_n_Mac
#155742
What did you intend to happen with this ?
Code: Select all
do // do…while loop to send single sms..You don't want to send out multiple SMSs.... or do you?
{
  delay(1);
}
while (1>0);
I ask because 1 is always > 0 and so once into that do loop the code will never exit. One call of your policeLights() function should send 1 message (assuming that part of the code is correct).
By bobxcool
#155757
Mee_n_Mac wrote:What did you intend to happen with this ?
Code: Select all
do // do…while loop to send single sms..You don't want to send out multiple SMSs.... or do you?
{
  delay(1);
}
while (1>0);
I ask because 1 is always > 0 and so once into that do loop the code will never exit. One call of your policeLights() function should send 1 message (assuming that part of the code is correct).
I used the do while loop so that only a single message is sent.

Also, I tried removing the do while loop, but still the same problem persists.

But, when I used an LED in place of the message sending gsm (led gets on if the condn is satisfied), it did not get stuck.
By WethaGuy
#155762
You should post all of your code. The problem may not be in the part you think it is.

I'm assuming you are calling the policeLights() function from another program. This other program is expecting a boolean return value because you have declared the function as such. But, there's no return value in policeLights(). So, either change it to void type or add logic to provide TRUE and FALSE return values. In either case, the do-while does nothing useful as it's currently written and should be removed. As written, the policeLights() function will execute exactly once for each time it is called.
By bobxcool
#155770
WethaGuy wrote:You should post all of your code. The problem may not be in the part you think it is.

I'm assuming you are calling the policeLights() function from another program. This other program is expecting a boolean return value because you have declared the function as such. But, there's no return value in policeLights(). So, either change it to void type or add logic to provide TRUE and FALSE return values. In either case, the do-while does nothing useful as it's currently written and should be removed. As written, the policeLights() function will execute exactly once for each time it is called.
I also tried using void, but it was of no use. policelights() was in the same program.
Code: Select all

#include <SoftwareSerial.h>
#include <TinyGPS.h>

#define NUM_OFF 2
#define DELAY 50
#define TEST_BUTTON 9
#define DEFAULT_SPEED_LIMIT 5
#define NSPEEDZONES 6

boolean debugMode = true;

boolean speeding = false;
int blue;



class Vertex {
public:
  Vertex(float llat, float llng) {
    lat = llat;
    lng = llng;
  }
  float lat;
  float lng;
};

class SpeedZone {
public:
  SpeedZone(int s) {
    speedLimit = s;
  }
  void setVertices(int n, Vertex *v) {
    nVertices = n;
    vertices = v;
  }
  int nVertices;
  Vertex *vertices;
  int speedLimit;
};


SpeedZone *speedZones[NSPEEDZONES];
TinyGPS gps;
SoftwareSerial nss(3, 4);
boolean buttonPressed = false;
SoftwareSerial cell(7,8);  // We need to create a serial port on D2/D3 to talk to the GSM module
char mobilenumber[] = "XXXXXXXXXXX";  


void setup() {
  Serial.begin(9600);
  setupSpeedZones();
  blue = 12;
  pinMode(blue, OUTPUT);
  pinMode(TEST_BUTTON, INPUT);
  digitalWrite(TEST_BUTTON, HIGH);
  cell.begin(4800);
  delay(3500); // give the GSM module time to initialise, locate network etc.


  
  delay(3000);

  
  nss.begin(9600);
}



void setupSpeedZones() {
  
  // 2nd main road
  speedZones[0] = &SpeedZone(25);
  speedZones[0]->setVertices(12, (Vertex[12]){
      Vertex(12.943427649396137, 77.53860712051392),
      Vertex(12.942570236686135, 77.53871440887451),
      Vertex(12.94140958795451,77.53876805305481),
      Vertex(12.940980878498074, 77.53875732421875),
      Vertex(12.940353497477103, 77.5388753414154),
      Vertex(12.939046448613755,77.5390899181366 ),
      Vertex(12.938021717514202,77.53932595252991 ),
      Vertex(12.937760305845364,77.53974437713623 ),
      Vertex(12.93687150412194,77.53973364830017 ),
      Vertex(12.935982699231385,77.53956198692322 ),
      Vertex(12.934142340214253,77.53906846046448),
      Vertex(12.933943664281175,77.538982629776 )});
  
  
  // 80 feet Double Road
  speedZones[1] = &SpeedZone(15);
  speedZones[1]->setVertices(9, (Vertex[9]){
      Vertex(12.941044923555157, 77.53885790705681),
      Vertex(12.941039695387857, 77.53906175494194),
      Vertex(12.941035774262303, 77.5392173230648),
      Vertex(12.941027932011004, 77.53935679793358),
      Vertex(12.940876315104193, 77.54202961921692),
      Vertex(12.94081357704682, 77.54283428192139),
      Vertex(12.940698557233977, 77.54501223564148),
      Vertex(12.94058353736807,77.54695415496826 ),
      Vertex(12.940520799237047, 77.54763007164001)});



  //  Block road
  speedZones[2] = &SpeedZone(10);
  speedZones[2]->setVertices(16, (Vertex[16]){
      Vertex(12.933547619021462,77.53549307584763),
      Vertex(12.93361689431027,77.53550313413143 ),
      Vertex(12.933661988591705,77.5354977697134),
      Vertex(12.933694012061984,77.53548838198185),
      Vertex(12.933777665189446,77.53545552492142),
      Vertex(12.933820798822312,77.5354354083538),
      Vertex(12.933860664749114,77.53541797399521),
      Vertex(12.934049537659947,77.53533147275448),
      Vertex(12.93419985163906,77.53525167703629),
      Vertex(12.934398527368137,77.53516852855682),
      Vertex(12.934513550086338,77.53511488437653),
      Vertex(12.934594588787776,77.53507733345032),
      Vertex(12.93473575291451,77.53501027822495),
      Vertex(12.934853389625761,77.53495931625366),
      Vertex(12.934952727249843,77.5349110364914),
      Vertex(12.934984097017653,77.53490567207336)});
      
		

  // towards  post office
  speedZones[3] = &SpeedZone(35);
  speedZones[3]->setVertices(20, (Vertex[20]){
      Vertex(12.93382341298164, 77.53911674022675),
      Vertex(12.933729303228546, 77.53927633166313),
      Vertex(12.933663949212452, 77.53939434885979),
      Vertex(12.933615587229529, 77.5394868850708),
      Vertex(12.933513634910476,77.53962635993958 ),
      Vertex(12.9334495879195, 77.5397376716137),
      Vertex(12.933313651394398, 77.53990530967712),
      Vertex(12.933197321040067, 77.54006892442703),
      Vertex(12.933090140216153, 77.54023790359497),
      Vertex(12.933005179774247, 77.54036530852318),
      Vertex(12.932905841374719, 77.54049941897392),
      Vertex(12.932785589574985,  77.54066303372383),
      Vertex(12.932637888915574, 77.54087224602699),
      Vertex(12.932517636986722, 77.54102379083633),
      Vertex(12.932401306261246, 77.54119008779526),
      Vertex(12.932307195971756, 77.54131078720093),
      Vertex(12.932219621087134, 77.54143953323364),
      Vertex(12.932149038321938, 77.54154548048973),
      Vertex(12.93218171553054, 77.54162460565567),
      Vertex(12.932209164382444, 77.54164338111877)});
		

  // ring road
  speedZones[4] = &SpeedZone(40);
  speedZones[4]->setVertices(11, (Vertex[11]){
      Vertex(12.933744988189858, 77.53884315490723),
      Vertex(12.93417371008398, 77.53815650939941),
      Vertex(12.934696540665088, 77.53731966018677),
      Vertex(12.935062521419919, 77.53671884536743),
      Vertex(12.935313479341485, 77.53631114959717),
      Vertex(12.935648089510861, 77.53558158874512),
      Vertex(12.936087264677003, 77.53476619720459),
      Vertex(12.936599634726921, 77.53420829772949),
      Vertex(12.937321133624925, 77.53389716148376),
      Vertex(12.937948522274533, 77.53362894058228),
      Vertex(12.938230846651972, 77.53344655036926)});
 

		
  // new road
  speedZones[5] = &SpeedZone(30);
  speedZones[5]->setVertices(11, (Vertex[11]){
      Vertex(12.943443333747508, 77.5386044383049),
      Vertex(12.943435491571943, 77.53841936588287),
      Vertex(12.943432877513375, 77.53809481859207),
      Vertex(12.943432877513375, 77.53791779279709),
      Vertex(12.943425035337478, 77.53762006759644),
      Vertex(12.943417193161341, 77.53743767738342),
      Vertex(12.943409350984949, 77.53721237182617),
      Vertex(12.943411965043772, 77.53708630800247),
      Vertex(12.943406736926102, 77.53692269325256),
      Vertex(12.94338582445431, 77.53680735826492),
      Vertex(12.943357069802731, 77.53675907850266)});


  if (debugMode) {
    printSpeedZones();
  }

}


boolean inSpeedZone(int speedZone, float lat, float lng) {
  SpeedZone *s = speedZones[speedZone];

  int i, j;
  boolean inside = false;
  for (i = 0, j = s->nVertices-1; i < s->nVertices; j = i++) {
    if ( ((s->vertices[i].lat > lat) != (s->vertices[j].lat > lat)) &&
         (lng < (s->vertices[j].lng - s->vertices[i].lng) * (lat - s->vertices[i].lat) / (s->vertices[j].lat - s->vertices[i].lat) + s->vertices[i].lng) )
       inside = !inside;
  }

  return inside;
}


boolean inSpeedZone(int speedZone) {
  float lat, lng;
  unsigned long  fix_age;

  // retrieves +/- lat/long in 100,000ths of a degree
  gps.f_get_position(&lat, &lng, &fix_age);

  return inSpeedZone(speedZone, lat, lng);
}

void loop() {

  if (readGPS()) {
    if (debugMode) {
      debug();
    }
    speeding = isSpeeding();
  }

  if (digitalRead(TEST_BUTTON) == LOW) {
    buttonPressed = true;
  } else {
    buttonPressed = false;
  }
  if ((speeding || buttonPressed) && (!(speeding && buttonPressed))) {
    policeLights();
  } else {
    allOff();
  }

}

bool readGPS() {
  while (nss.available()) {
    if (gps.encode(nss.read())) {
      return true;
    }
  }
  return false;
}

  
int getSpeedLimit() {
  boolean isInSpeedZone;

  for(int i=0;i<NSPEEDZONES;i++) {
    isInSpeedZone = inSpeedZone(i);
    if (isInSpeedZone) {
      return speedZones[i]->speedLimit;
    }
  }
  return DEFAULT_SPEED_LIMIT;
}

boolean isSpeeding() {
  int speed = (int)(gps.f_speed_kmph() + 0.5);
  int speedLimit = getSpeedLimit();

  if (speed > speedLimit) {
    delay (5000);
    if (speed > speedLimit)
    return true;
  }
  return false;
}

void policeLights() {

digitalWrite(blue, HIGH);
cell.println("AT+CMGF=1"); // set SMS mode to text
cell.print("AT+CMGS=");  // now send message...
cell.write((byte)34);  // ASCII equivalent of "
cell.print(mobilenumber);
cell.write((byte)34);   // ASCII equivalent of "
cell.println();
delay(500); // give the module some thinking time
cell.print("hi bobby, the king of kings... :-)");   // our message to send
cell.write((byte)26); // ASCII equivalent of Ctrl-Z
cell.println();
delay(15000); // the SMS module needs time to return to OK status
return;
}


void allOff() {
    digitalWrite(blue,LOW);
    }

void printSpeedZones() {

  for(int i=0;i<NSPEEDZONES;i++) {
    SpeedZone *s = speedZones[i];
    Serial.println(s->speedLimit);
    for(int v=0;v<s->nVertices;v++) {
      Serial.print("(");
      Serial.print(s->vertices[v].lat,15);
      Serial.print(", ");
      Serial.print(s->vertices[v].lng,15);
      Serial.println(")");
    }
  }
}

void debug() {
  float lat, lng;
  unsigned long fix_age, time, date, speed, course;

  // retrieves +/- lat/long in 100000ths of a degree
  gps.f.get_position(&lat, &lng, &fix_age);

  Serial.println(getSpeedLimit());

  Serial.print("lat: ");
  Serial.print(lat,15);
  Serial.print("    lng: ");
  Serial.print(lng,15);
  Serial.print("    speed: ");
  Serial.println(gps.f_speed_kmph());
}




i have removed do while...still problem persists.

This code checks for the current location (using gps module) and accesses the speed limit set in the speedzone defined in the program, and sends a message to the police if speedlimit of a road is exceeded.

I have used 15 digits after the decimal point in lat and long values defined in the program. Will arduino process so many digits??
I am using arduino uno.
By WethaGuy
#155787
Not sure this is causing a problem but in policeLights() you have:
Code: Select all
digitalWrite(blue, HIGH);
but no corresponding low. I'm assuming this is a transmit enable pin or something. It should be put back low when done.

You don't need a return in the policeLights() function. It will return on it's own on that line anyway. Are you sure it is locking up in the policeLights() function? It's helpful to add debugging printlns at every change in logic (entering and leaving loops or functions etc.). You should add printlns to your code to see where it is when it fails.

You have a delay of 15 seconds at the end of the policeLights() function. You understand that the arduino is doing nothing for 15 seconds duing this time, right? This would look like an endless loop until the end of the 15 second delay.

15 digits is about 9 digits of make believe. The average consumer GPS has an accuracy maximum of a meter or two. With 6 digits, decimal degrees is down to something like 100 cm. Going any further than that won't help. For your application, using 5 digits would be acceptable as it would be close to your GPS's accuracy.
By bobxcool
#155936
WethaGuy wrote:Not sure this is causing a problem but in policeLights() you have:
Code: Select all
digitalWrite(blue, HIGH);
but no corresponding low. I'm assuming this is a transmit enable pin or something. It should be put back low when done.

You don't need a return in the policeLights() function. It will return on it's own on that line anyway. Are you sure it is locking up in the policeLights() function? It's helpful to add debugging printlns at every change in logic (entering and leaving loops or functions etc.). You should add printlns to your code to see where it is when it fails.

You have a delay of 15 seconds at the end of the policeLights() function. You understand that the arduino is doing nothing for 15 seconds duing this time, right? This would look like an endless loop until the end of the 15 second delay.

15 digits is about 9 digits of make believe. The average consumer GPS has an accuracy maximum of a meter or two. With 6 digits, decimal degrees is down to something like 100 cm. Going any further than that won't help. For your application, using 5 digits would be acceptable as it would be close to your GPS's accuracy.
The digitalwrite function is used to switch on an led. I tried the program with only the led part (without gsm), it worked flawlessly. But, with the gsm code included, it gets stuck as soon as the speed limit is crossed.

I am sure that it is locking in the policelights function, because the led gets on and also a message is sent to the mobile phone. Immediately after the led gets on, the program gets stuck.
By Mee_n_Mac
#155971
How about this to be sure, put a ...
Serial.println("Entering policelights");
... at the top of policelights() and then a ...
Serial.println("Waiting 15 secs");
... prior to the long delay and a ...
Serial.println("Done policelights");
... at the bottom.

Place a few other such "prints" where you think the code is going off the tracks. Then you'll know for sure what's getting executed and what's not.
By bobxcool
#156102
Mee_n_Mac wrote:How about this to be sure, put a ...
Serial.println("Entering policelights");
... at the top of policelights() and then a ...
Serial.println("Waiting 15 secs");
... prior to the long delay and a ...
Serial.println("Done policelights");
... at the bottom.

Place a few other such "prints" where you think the code is going off the tracks. Then you'll know for sure what's getting executed and what's not.

I added the following.
Code: Select all
void policeLights() {

digitalWrite(blue, HIGH);
cell.println("AT+CMGF=1"); // set SMS mode to text
cell.print("AT+CMGS=");  // now send message...
cell.write((byte)34);  // ASCII equivalent of "
cell.print(mobilenumber);
cell.write((byte)34);   // ASCII equivalent of "
cell.println();
delay(500); // give the module some thinking time
cell.print("hi bobby, the king of kings... :-)");   // our message to send
cell.write((byte)26); // ASCII equivalent of Ctrl-Z
cell.println();
Serial.println("before delay");
delay(15000); // the SMS module needs time to return to OK status
Serial.println("after delay");
return;
}

What happens is that a message is sent and "before delay" is printed on the screen. after 15secs,"after delay" is printed....but again a few secs , "before delay" is printed, and message is sent...and the same process keeps on repeating.
By bobxcool
#156103
WethaGuy wrote:Not sure this is causing a problem but in policeLights() you have:
Code: Select all
digitalWrite(blue, HIGH);
but no corresponding low. I'm assuming this is a transmit enable pin or something. It should be put back low when done.

You don't need a return in the policeLights() function. It will return on it's own on that line anyway. Are you sure it is locking up in the policeLights() function? It's helpful to add debugging printlns at every change in logic (entering and leaving loops or functions etc.). You should add printlns to your code to see where it is when it fails.

You have a delay of 15 seconds at the end of the policeLights() function. You understand that the arduino is doing nothing for 15 seconds duing this time, right? This would look like an endless loop until the end of the 15 second delay.

15 digits is about 9 digits of make believe. The average consumer GPS has an accuracy maximum of a meter or two. With 6 digits, decimal degrees is down to something like 100 cm. Going any further than that won't help. For your application, using 5 digits would be acceptable as it would be close to your GPS's accuracy.
I added the following.
Code: Select all
void policeLights() {

digitalWrite(blue, HIGH);
cell.println("AT+CMGF=1"); // set SMS mode to text
cell.print("AT+CMGS=");  // now send message...
cell.write((byte)34);  // ASCII equivalent of "
cell.print(mobilenumber);
cell.write((byte)34);   // ASCII equivalent of "
cell.println();
delay(500); // give the module some thinking time
cell.print("hi bobby, the king of kings... :-)");   // our message to send
cell.write((byte)26); // ASCII equivalent of Ctrl-Z
cell.println();
Serial.println("before delay");
delay(15000); // the SMS module needs time to return to OK status
Serial.println("after delay");
return;
}




What happens is that a message is sent and "before delay" is printed on the screen. after 15secs,"after delay" is printed....but again a few secs , "before delay" is printed, and message is sent...and the same process keeps on repeating.
bobxcool
By n1ist
#156109
That tells me that policeLights() is being called over and over again. Time to look up a level in your code.
/mike
By WethaGuy
#156111
Code: Select all
void loop() {

  if (readGPS()) {
    if (debugMode) {
      debug();
    }
    speeding = isSpeeding();
  }

  if (digitalRead(TEST_BUTTON) == LOW) {
    buttonPressed = true;
  } else {
    buttonPressed = false;
  }
  if ((speeding || buttonPressed) && (!(speeding && buttonPressed))) {
    policeLights();
  } else {
    allOff();
  }

}
The behaviour you say it is doing is expected based on your code. After policeLights() is executed, you return to loop() which finds that you are speeding, delays 5 seconds and calls policeLights() again, etc. until you are NOT speeding any more or until buttonPressed() is true while you're speeding.
Code: Select all
if (speed > speedLimit) {
    delay (5000);
    if (speed > speedLimit)
    return true;
Also, this code makes no sense. There is a delay followed by testing of the same variables with the same values. The second if cannot ever be anything but true since it is testing the same variable values as the first if.
By bobxcool
#156116
if (speed > speedLimit) {
delay (5000);
if (speed > speedLimit)
return true;

I have already removed this part of the code...Ya I know, it makes no sense.

Still the problem persists.

The program gets stuck as soon as the speed limit is exceeded..it does not return to the loop. (light remains on and messages are sent one after)

But it worked flawlessly with a single led. Whenever, I include the gsm code, it gets stuck.

I have already mentioned about what is happening in the policelights function in my previous post (print statements) . pls see it.
By WethaGuy
#156125
bobxcool wrote:The program gets stuck as soon as the speed limit is exceeded..it does not return to the loop.
If you add a println "Inside loop()" at the beginning of the loop() function, I think you will see that you are leaving policeLights() and going through the loop() each time a message is sent. The only way to send a message is to call the policeLights function. The only call to policeLights function occurs in the loop function. Therefore, you have to be going back to loop() if you are sending a gsm message.

The led remains on because you are still speeding. Until you stop speeding xor press the button, you never get to the allOff function which turns off the led.

Also, since policeLights() is a void function, having any return is unnecessary and probably throws a caution on your compiler window. Remove "return" from it to avoid potential problems.
By Mee_n_Mac
#156126
Now add the following print statements. I think you'll see what's happening pretty quickly.
Code: Select all
void loop() {

  if (readGPS()) {
    if (debugMode) {
      debug();
    }
    speeding = isSpeeding();
  }

  if (digitalRead(TEST_BUTTON) == LOW) {
    buttonPressed = true;
    Serial.println("Button pressed");
  } 
  else {
    buttonPressed = false;
  }
  Serial.print("Speeding = ");
  Serial.println(speeding);
  if ((speeding || buttonPressed) && (!(speeding && buttonPressed))) {
    Serial.println("Going to policeLights");
    policeLights();
  } 
  else {
    allOff();
  }

}