SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
By Mee_n_Mac
#156129
You might also want to revisit your thinking on this line:

if ((speeding || buttonPressed) && (!(speeding && buttonPressed))) {

I have no idea why you're doing this :

... && (!(speeding && buttonPressed)) ...
By bobxcool
#156157
WethaGuy wrote:
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.
No, sir the led remains on even after I stop speeding. This is the case when I use a GSM module along with led.

But, if I remove the gsm part of the code ,and use just an led, it works properly. The light turns on and off according to the speed or button press.

The problem is when I include the gsm part of the code
By Mee_n_Mac
#156189
In addition to all the problems mentioned so far, I wonder if you aren't running out of RAM. When that happens all sorts of really odd behavior results. Your policelights() function has a few strings in it and I question whether those are putting you past the limit. Specifically I wonder where all your Vertex(x,y) data is being stored. Those arrays are in RAM I believe. Given they are constants they don't need to be.

http://playground.arduino.cc/Code/AvailableMemory
http://playground.arduino.cc/Main/Corru ... sAndMemory
http://arduino.cc/en/Tutorial/Memory
http://www.arduino.cc/en/Reference/PROGMEM
By bobxcool
#156223
Mee_n_Mac wrote:In addition to all the problems mentioned so far, I wonder if you aren't running out of RAM. When that happens all sorts of really odd behavior results. Your policelights() function has a few strings in it and I question whether those are putting you past the limit. Specifically I wonder where all your Vertex(x,y) data is being stored. Those arrays are in RAM I believe. Given they are constants they don't need to be.

http://playground.arduino.cc/Code/AvailableMemory
http://playground.arduino.cc/Main/Corru ... sAndMemory
http://arduino.cc/en/Tutorial/Memory
http://www.arduino.cc/en/Reference/PROGMEM
Sir, the size of the program with all those vertices is 12000 bytes.

What I thought of was to use an another arduino board, and burn the gsm code in it. So, whenver the condition is satisfied on 1st arduino, I would set a pin high on the 1st arduino. Whereas, in the 2nd arduino I would check for the status of a pin to go high (the pin connected to the pin that will be set high on 1st arduino), and as soon as it does, it should send a message.

What do you think??
By bobxcool
#156230
Mee_n_Mac wrote:In addition to all the problems mentioned so far, I wonder if you aren't running out of RAM. When that happens all sorts of really odd behavior results. Your policelights() function has a few strings in it and I question whether those are putting you past the limit. Specifically I wonder where all your Vertex(x,y) data is being stored. Those arrays are in RAM I believe. Given they are constants they don't need to be.

http://playground.arduino.cc/Code/AvailableMemory
http://playground.arduino.cc/Main/Corru ... sAndMemory
http://arduino.cc/en/Tutorial/Memory
http://www.arduino.cc/en/Reference/PROGMEM
So you think it is sram problem?

On the other hand, sir how do I check the sram usage for the current program on the arduino IDE?
By WethaGuy
#156257
The first step is to add debugging println's at the beginning and end of every logic break (loops, functions, etc...) and for the values of the variables involved. That will tell you what is happening. LED's being on and off don't tell you that. This should make it apparent exactly where your problem is.

The gsm module is just another serial connection. I can't see it having anything to do with this at all unless you are powering the gsm with your primary power source or you have not connected all of your ground wires together.
By bobxcool
#156266
Mee_n_Mac wrote:http://playground.arduino.cc/Code/AvailableMemory

... or comment out those arrays that won't get used and see if your problem goes away.
Sir, I used this function for memory test (sram space left in bytes)
Code: Select all
int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

and call it anywhere in your program like that: Serial.println(freeRam());
But, it shows at various points that I defined in the code, that free space is 1388. So , I do not think it is an SRAM problem. What do you think??

These are the various points at which I used it.
Code: Select all
void policeLights() {
digitalWrite(blue, HIGH);
[size=150]Serial.println(freeRam())[/size]; 
cell.println("AT+CMGF=1"); // set SMS mode to text
cell.print("AT+CMGS=");  // now send message...[size=150][/size]
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();
[size=150]Serial.println(freeRam()); [/size]
delay(15000); // the SMS module needs time to return to OK status
[size=150]Serial.println(freeRam()); [/size]
}

Code: Select all
void setup() {
  Serial.begin(9600);
  setupSpeedZones();
  [size=150]Serial.println(freeRam()); [/size]
  blue = 12;
  pinMode(blue, OUTPUT);
  pinMode(TEST_BUTTON, INPUT);
  digitalWrite(TEST_BUTTON, HIGH);


Code: Select all
void setupSpeedZones() {
 [size=150]Serial.println(freeRam()); [/size]

speedZones[0] = &SpeedZone(10);
speedZones[0]->setVertices(10, (Vertex[10]){
Vertex(12.938231,77.533291),
Vertex(12.937279,77.533835),
Vertex(12.936665,77.534077),
Vertex(12.93524,77.536153),
Vertex(12.933635,77.538924),
Vertex(12.934012,77.53902),
Vertex(12.935515,77.536367),
Vertex(12.936756,77.534332),
Vertex(12.937342,77.53412),
Vertex(12.938456,77.533546)});
.
.
.
.
.
.
.
speedZones[4] = &SpeedZone(10);
speedZones[4]->setVertices(4, (Vertex[4]){
Vertex(12.935193,77.535496),
Vertex(12.933238,77.535635),
Vertex(12.933165,77.534283),
Vertex(12.935219,77.534155)});

[size=150]Serial.println(freeRam()); [/size]

for all these I got the same result of 1388 or similar.

I think it has got something to do with gsm program part, and arduino receiving a response from gsm. Please help.
By Mee_n_Mac
#156273
What do the other print statements I suggested back on page 1 show for the state or "speeding" or "buttonPressed" when the bad stuff happens ?

I don't have the GSM or GPS attached so I commented out the reads from the GPS. I added some prints to the loop() and I don't see any hangup on my Arduino. The loop runs and policelights() is called and returned from. I see the kind of cyclic behavior I would expect.
By Mee_n_Mac
#156274
This is "commented out" code I used. Button pressed was hard coded to be true.
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;
int loopctr = 0;



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() {
  loopctr++;
  Serial.print("Loop counter  = ");
  Serial.println(loopctr);
//  if (readGPS()) {
//    if (debugMode) {
//      debug();
//    }
//    speeding = isSpeeding();
//  }

//  if (digitalRead(TEST_BUTTON) == LOW) {
//    buttonPressed = true;
//  } 
//  else {
//    buttonPressed = false;
//  }
  buttonPressed = true;
  if ((speeding || buttonPressed) && (!(speeding && buttonPressed))) {
    Serial.println("going to PD lights");
    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() {
  Serial.println("In PD lights");
  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
  Serial.println("Exit PD lights");
  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());
}
And this is the looping behavior I see :
Loop counter = 1
going to PD lights
In PD lights
Exit PD lights
Loop counter = 2
going to PD lights
In PD lights
Exit PD lights
Loop counter = 3
going to PD lights
In PD lights
Exit PD lights
Loop counter = 4
going to PD lights
In PD lights
Exit PD lights
Loop counter = 5
going to PD lights
In PD lights
Exit PD lights
Loop counter = 6
going to PD lights
In PD lights
Exit PD lights
Loop counter = 7
going to PD lights
In PD lights
Exit PD lights
Loop counter = 8
going to PD lights
In PD lights
Exit PD lights
Loop counter = 9
going to PD lights
In PD lights
Exit PD lights
Loop counter = 10
going to PD lights
In PD lights
Exit PD lights
Loop counter = 11
going to PD lights
In PD lights
Exit PD lights
Loop counter = 12
going to PD lights
In PD lights
Exit PD lights
Loop counter = 13
going to PD lights
In PD lights
Exit PD lights
Loop counter = 14
going to PD lights
In PD lights
Exit PD lights
Loop counter = 15
going to PD lights
In PD lights
Exit PD lights
Loop counter = 16
going to PD lights
In PD lights
Exit PD lights
By bobxcool
#156327
Mee_n_Mac wrote:This is "commented out" code I used. Button pressed was hard coded to be true.
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;
int loopctr = 0;



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() {
  loopctr++;
  Serial.print("Loop counter  = ");
  Serial.println(loopctr);
//  if (readGPS()) {
//    if (debugMode) {
//      debug();
//    }
//    speeding = isSpeeding();
//  }

//  if (digitalRead(TEST_BUTTON) == LOW) {
//    buttonPressed = true;
//  } 
//  else {
//    buttonPressed = false;
//  }
  buttonPressed = true;
  if ((speeding || buttonPressed) && (!(speeding && buttonPressed))) {
    Serial.println("going to PD lights");
    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() {
  Serial.println("In PD lights");
  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
  Serial.println("Exit PD lights");
  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());
}
And this is the looping behavior I see :
Loop counter = 1
going to PD lights
In PD lights
Exit PD lights
Loop counter = 2
going to PD lights
In PD lights
Exit PD lights
Loop counter = 3
going to PD lights
In PD lights
Exit PD lights
Loop counter = 4
going to PD lights
In PD lights
Exit PD lights
Loop counter = 5
going to PD lights
In PD lights
Exit PD lights
Loop counter = 6
going to PD lights
In PD lights
Exit PD lights
Loop counter = 7
going to PD lights
In PD lights
Exit PD lights
Loop counter = 8
going to PD lights
In PD lights
Exit PD lights
Loop counter = 9
going to PD lights
In PD lights
Exit PD lights
Loop counter = 10
going to PD lights
In PD lights
Exit PD lights
Loop counter = 11
going to PD lights
In PD lights
Exit PD lights
Loop counter = 12
going to PD lights
In PD lights
Exit PD lights
Loop counter = 13
going to PD lights
In PD lights
Exit PD lights
Loop counter = 14
going to PD lights
In PD lights
Exit PD lights
Loop counter = 15
going to PD lights
In PD lights
Exit PD lights
Loop counter = 16
going to PD lights
In PD lights
Exit PD lights
This worked for me also, but with both the gsm and gps modules it fails. (the arduino cannot receive data simultaneously from gps and gsm I guess)

So, I used another arduino uno board for gsm module, such that a message is sent when a certain pin is activated on the second arduino, by a pin on the 1st arduino. This one worked properly without any hitches so far.

Now, I need to send the lat and long values of the place where the speeding condition has occurred, through the gsm module to a mobile phone.
Is it possible? How to do this?
This is because, the coordinates on the 1st arduino needs to be sent to 2nd arduino, and then to the mobile phone through gsm.
By WethaGuy
#156361
bobxcool wrote:...(the arduino cannot receive data simultaneously from gps and gsm I guess)...
These are just serial devices, no different than the connection to your computer through Serial. There is no software reason the gps and gsm cannot both be connected. If you power them both from your uno, you may run into problems with not providing enough power causing brownouts and reseting. If you don't connect the grounds from the power sources of all devices connected to you uno you may run into other interesting and potentially magic smoke releasing problems. But, the uno is quite capable of handling many serial connections.

Post the output of the debug printlns and describe how the gps and gsm are powered and connected to the uno and we'll help you get to a working project.
By Mee_n_Mac
#156363
WethaGuy wrote:
bobxcool wrote:...(the arduino cannot receive data simultaneously from gps and gsm I guess)...
These are just serial devices, no different than the connection to your computer through Serial. There is no software reason the gps and gsm cannot both be connected.
...
Post the output of the debug printlns and describe how the gps and gsm are powered and connected to the uno and we'll help you get to a working project.
FWIW : I see he's using software emulation of a UART to communicate with the GSM and GPS. From the page ...
http://arduino.cc/en/Reference/SoftwareSerial
Limitations
The library has the following known limitations:
* If using multiple software serial ports, only one can receive data at a time.


I hadn't seen where the GPS and GSM were both talking at the same time but I suppose the GPS is just spewing out NMEA messages constantly so overlap can happen. I believe you can tell most GPS's to stop transmission so that would be a preferable alternative to using another Uno. I don't know how to disable just one 'port' or it's interrupts, but that would be another way.

I'd still like to see the prints of what's happening with buttonPressed and speeding, then again maybe not. I've completely lost track of what the OP is running for code at this point. I did look briefly at the amount of variables involved at storing all the vertices and it's under 1k, so the reported SRAM usage seem right and not a problem. I will point out that the accuracy available (as previously noted) doesn't support the number of digits used.

http://arduino.cc/en/Reference/Float
Datatype for floating-point numbers, a number that has a decimal point. Floating-point numbers are often used to approximate analog and continuous values because they have greater resolution than integers. Floating-point numbers can be as large as 3.4028235E+38 and as low as -3.4028235E+38. They are stored as 32 bits (4 bytes) of information.

Floats have only 6-7 decimal digits of precision. That means the total number of digits, not the number to the right of the decimal point. Unlike other platforms, where you can get more precision by using a double (e.g. up to 15 digits), on the Arduino, double is the same size as float.
By Mee_n_Mac
#156365
bobxcool wrote:Now, I need to send the lat and long values of the place where the speeding condition has occurred, through the gsm module to a mobile phone.
Is it possible? How to do this?
This is because, the coordinates on the 1st arduino needs to be sent to 2nd arduino, and then to the mobile phone through gsm.
I don't understand. Isn't this why you have a serial link to the GSM ? I can't say I know much about it but I thought you could set up the GSM via some command codes and then just send the data. It would be ASCII text for for SMS and, I assume ( :o ) "raw data" for other modes. A cell.print and a cell.write respectively.
By bobxcool
#156371
Mee_n_Mac wrote:
WethaGuy wrote:
bobxcool wrote:...(the arduino cannot receive data simultaneously from gps and gsm I guess)...
These are just serial devices, no different than the connection to your computer through Serial. There is no software reason the gps and gsm cannot both be connected.
...
Post the output of the debug printlns and describe how the gps and gsm are powered and connected to the uno and we'll help you get to a working project.
FWIW : I see he's using software emulation of a UART to communicate with the GSM and GPS. From the page ...
http://arduino.cc/en/Reference/SoftwareSerial
Limitations
The library has the following known limitations:
* If using multiple software serial ports, only one can receive data at a time.


I hadn't seen where the GPS and GSM were both talking at the same time but I suppose the GPS is just spewing out NMEA messages constantly so overlap can happen. I believe you can tell most GPS's to stop transmission so that would be a preferable alternative to using another Uno. I don't know how to disable just one 'port' or it's interrupts, but that would be another way.

I'd still like to see the prints of what's happening with buttonPressed and speeding, then again maybe not. I've completely lost track of what the OP is running for code at this point. I did look briefly at the amount of variables involved at storing all the vertices and it's under 1k, so the reported SRAM usage seem right and not a problem. I will point out that the accuracy available (as previously noted) doesn't support the number of digits used.

http://arduino.cc/en/Reference/Float
Datatype for floating-point numbers, a number that has a decimal point. Floating-point numbers are often used to approximate analog and continuous values because they have greater resolution than integers. Floating-point numbers can be as large as 3.4028235E+38 and as low as -3.4028235E+38. They are stored as 32 bits (4 bytes) of information.

Floats have only 6-7 decimal digits of precision. That means the total number of digits, not the number to the right of the decimal point. Unlike other platforms, where you can get more precision by using a double (e.g. up to 15 digits), on the Arduino, double is the same size as float.
sir, I tried to stop gps data transmission when gsm is working and vice-versa. but still the problem persists.


Code: Select all

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

#define NUM_OFF 2
#define DELAY 50
#define DEFAULT_SPEED_LIMIT 50
#define NSPEEDZONES 5

boolean debugMode = true;

boolean speeding = false;
int blue;
int red;



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[] = "+919901999868";  // Replace xxxxxxxx with the recipient's mobile number



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


  // Allow EM-406a to power up
  delay(3000);

  // Establish serial connection to EM-406a
  nss.begin(9600);
}



void setupSpeedZones() {



speedZones[0] = &SpeedZone(10);
speedZones[0]->setVertices(10, (Vertex[10]){
Vertex(12.938231,77.533291),
Vertex(12.937279,77.533835),
Vertex(12.936665,77.534077),
Vertex(12.93524,77.536153),
Vertex(12.933635,77.538924),
Vertex(12.934012,77.53902),
Vertex(12.935515,77.536367),
Vertex(12.936756,77.534332),
Vertex(12.937342,77.53412),
Vertex(12.938456,77.533546)});
 
speedZones[1] = &SpeedZone(2);
speedZones[1]->setVertices(6,(Vertex[6]){
Vertex(12.933763,77.539398),
Vertex(12.93242,77.541209),
Vertex(12.931058,77.543014),
Vertex(12.930901,77.542864),
Vertex(12.932271,77.541037),
Vertex(12.933512,77.539211)});
      
 
speedZones[2] = &SpeedZone(45);
speedZones[2]->setVertices(6, (Vertex[6]){
Vertex(12.934357,77.539017),
Vertex(12.936576,77.539626),
Vertex(12.937802,77.539793),
Vertex(12.937797,77.539951),
Vertex(12.93656,77.539865),
Vertex(12.934346,77.539208)});
      

speedZones[3] = &SpeedZone(40);
speedZones[3]->setVertices(4, (Vertex[4]){
Vertex(12.942973,77.538151),
Vertex(12.942994,77.539524),
Vertex(12.940986,77.539675),
Vertex(12.941044,77.538242)});
		

speedZones[4] = &SpeedZone(1);
speedZones[4]->setVertices(4, (Vertex[4]){
Vertex(12.935193,77.535496),
Vertex(12.933238,77.535635),
Vertex(12.933165,77.534283),
Vertex(12.935219,77.534155)});
      
      


  if (debugMode) {
    printSpeedZones();
  }

}

/*
 * This is the point-in-polygon algorithm adapted from
 * http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
 */
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 (speeding ) {
    Serial.println("loop1");
    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) {
    return true;
  }
  return false;
}

void policeLights() {
nss.end();
cell.begin(9600);
delay(3500);
digitalWrite(blue, HIGH);
digitalWrite(red, HIGH);
Serial.println("before delay");
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
Serial.println("after delay");
  cell.end();
nss.begin(9600);
}






void allOff() {
    digitalWrite(blue,LOW);
    digitalWrite(red, 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,6);
      Serial.print(", ");
      Serial.print(s->vertices[v].lng,6);
      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,6);
  Serial.print("    lng: ");
  Serial.print(lng,6);
  Serial.print("    speed: ");
  Serial.println(gps.f_speed_kmph());
}