Arduino GPS, issue with dgps.update()


#1

Hi, I’m working with my nephew to connect his go-kart to the internet. Fun project!
Here are config details:
Arduino Mega v3
Winc1500 wifi breakout board (which connects to a mobile phone hotspot)
Dexter GPS shield - for speed and location
Temp sensor for engine oil temp.
The solution is powered by a 12v battery that is plugged into the power jack of the Arduino Mega. (Most of my testing is done with AC power though)
So, GPS is powered via pins on shield
wifi is powered via other open 5v pins on Mega
temp sensor takes power from breadboard fed from mega.
All data is being published to the dashboard at adafruit.io, which relies on mqtt for the data transfer protocol from the client device to the cloud.

This Dexter GPS and accompanying libraries are awesome! The GPS works great using Dexter provided sample code. However, once integrated into the larger code base for this project, we have a GPS issue: The call to dgps.update() does not return data. I get an accurate initial reading of velocity based on initialization of the GPS but that value never changes thereafter. But, this works fine on the same board if I’m just running GPS sample code alone. (My current code is just using dummy values for lat long until I get the update issue figured out)

dgps.update() is being called in loop() while the wifi is running and wifi is pushing data to mqtt / adafruit. Possibly this is some timing issues or power issue?
Am I calling dgps.Update correctly? My call is as follows: dgps.update(Maple_Valley[0],Maple_Valley[1]). This call works when I use it in the Dexter sample but does not work in the context of my code pasted below.

I’ve been stumped on this for days. I’ve also tried different GPSs which exhibit similar behavior, which makes me think it is my board setup or code.
I was hoping to have this issue figured out days ago. My nephew and I are supposed to wrap this up this weekend (for an upcoming school project deadline) and I am at my wits end ! :slight_smile:
Here is the entire code in the sketch if that helps.
I would GREATLY appreciate any sage advice from anyone on the forum!
Thanks in advance (and thanks for a cool product Dexter)!
Jonathan

#include “allheaders.h” //GPS and other headers all go in this file
#include “config.h”

/************************* WiFI Setup *****************************/
//alt mega config
#define WINC_CS 17
#define WINC_IRQ 15 //moved from 18…put GPS on 18 and 19
#define WINC_RST 20 //moved from 19

//#define WINC_CS 8
//#define WINC_IRQ 7
//#define WINC_RST 4
//#define WINC_EN 2 // EN tied directly to 5v. Put it on 2 to control it from arduino, which we don’t need

Adafruit_WINC1500 WiFi(WINC_CS, WINC_IRQ, WINC_RST);
int status = WL_IDLE_STATUS;

/************ Global State (you don’t need to change this!) ******************/
//Set up the wifi client
Adafruit_WINC1500Client client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

// define halt
#define halt(s) { Serial.println(F( s )); while(1); }

/****************************** Feeds ***************************************/
Adafruit_MQTT_Publish temp = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME “/feeds/temp”);
Adafruit_MQTT_Publish vel = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME “/feeds/vel”);
Adafruit_MQTT_Publish loc = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME “/feeds/loc”);

// ‘onoff’ feed for subscribing to changes.
Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME “/feeds/onoff”);

/Temp Sensor setup******/
int DS18S20_Pin = 39; //DS18S20 Signal pin
OneWire ds(DS18S20_Pin);

/*************GPS Pins and default location config *****************************/
// Software serial TX & RX Pins for the GPS module
// Initiate the software serial connection
int ledPin = 13; // LED test pin
dGPS dgps = dGPS(); // Construct dGPS class
float Maple_Valley[]={47.42402, -122.0279}; //need a location to for gps “update” command

/*************************** Sketch Code ************************************/

//#define LEDPIN 13 //try without this

void setup() {
#ifdef WINC_EN
pinMode(WINC_EN, OUTPUT);
digitalWrite(WINC_EN, HIGH);
#endif

//setup LEDs
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT);
SetState(0);

while (!Serial);
Serial.begin(115200);

Serial.println(F(“Connect Go Kart To the Cloud”));
Serial.println("");

// Initialise the Client

Serial.print(F("\nStart WiFi …"));
SetState(1); //light LED
// check for the presence of the breakout
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println(“WINC1500 wifi device not present”);
// don’t continue:
while (true);
}
Serial.println(“Wifi started!”);

//pinMode(LEDPIN, OUTPUT); /try without this
mqtt.subscribe(&onoffbutton);

//gps pin
pinMode(ledPin, OUTPUT); // Initialize LED pin. Do I really need this?

//Initialize GPS
SetState(2); //light LED
Serial.println(“Starting GPS.”);
dgps.init(); // Initialize dGPS.
delay(1000);
Serial.println(“GPS started!”);
}

void loop() {
// Reset watchdog every loop
Watchdog.reset();
//Reset LED state
SetState(0);
//Connect / reconnect to mqtt if needed. see function def below
MQTT_connect();

// this is our ‘wait for incoming subscription packets’ busy subloop
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(5000))) {
if (subscription == &onoffbutton) {
Serial.print(F("Got: "));
Serial.println((char *)onoffbutton.lastread);

  if (0 == strcmp((char *)onoffbutton.lastread, "OFF")) {
    digitalWrite(buzzerPin, LOW);
  }
  if (0 == strcmp((char *)onoffbutton.lastread, "ON")) {
    digitalWrite(buzzerPin, HIGH);
  }
}

}

//set temp
float temperatureC = getTemp(); //will take about 750ms to run. there is a delay() call in getTemp()
float temperatureF = temperatureC*1.8 + 32;

//set speed
dgps.update(Maple_Valley[0],Maple_Valley[1]); //call update for any location
float veldata = dgps.Vel();
Serial.println(“Speed.”);
Serial.println(veldata);

//set location - update this with real code
char locdata[] = “1, -47.42, -122.03, 1”; //for location

// Now we can publish stuff!
SetState(3);
Serial.print(F("\nSending temperature value “));
Serial.print(temperatureF);
Serial.print(”…");
if (! temp.publish(temperatureF)) {
Serial.println(F(“Failed”));
} else {
Serial.println(F(“OK!”));
}

Serial.print(F("\nSending speed/velocity “));
Serial.print(veldata);
Serial.print(”…");
if (! vel.publish(veldata)) {
Serial.println(F(“Failed”));
} else {
Serial.println(F(“OK!”));
}
Serial.print(F("\nSending location “));
Serial.print(locdata);
Serial.print(”…");
if (! loc.publish(locdata)) {
Serial.println(F(“Failed”));
} else {
Serial.println(F(“OK!”));
}
SetState(4); //light final LED, showing last data point in loop has been sent
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;

// attempt to connect to Wifi network:
while (WiFi.status() != WL_CONNECTED) {
Serial.print("Connect wifi to: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);

// wait 10 seconds for connection:
uint8_t timeout = 10;
while (timeout && (WiFi.status() != WL_CONNECTED)) {
  timeout--;
  delay(1000);
}

}

// Stop if already connected.
if (mqtt.connected()) {
return;
}

Serial.print("Connect to Adafruit.io … ");

while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println(“Retrying adafruit.io connection in 5 seconds…”);
mqtt.disconnect();
delay(5000); // wait 5 seconds
}
Serial.println(“Connected!”);
}

float getTemp(){
//returns the temperature from one DS18S20 in DEG Celsius

byte data[12];
byte addr[8];

if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}

if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println(“CRC is not valid!”);
return -1000;
}

if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print(“Device is not recognized”);
return -1000;
}

ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end

delay(750); // Wait for temperature conversion to complete

byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad

for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}

ds.reset_search();

byte MSB = data[1];
byte LSB = data[0];

float tempRead = ((MSB << 8) | LSB); //using two’s compliment
float TemperatureSum = tempRead / 16;

return TemperatureSum;
}

//function for controlling LEDs
void SetState(int state){
switch(state){
//note power LED is lit directly from bboard
case 0: //wifi connected
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
digitalWrite(ledPin4, LOW);
break;
case 1: //wifi connected
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
digitalWrite(ledPin4, LOW);
break;
case 2: //adafruit connected
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, HIGH);
digitalWrite(ledPin3, LOW);
digitalWrite(ledPin4, LOW);
break;
case 3: //gps initialized
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, HIGH);
digitalWrite(ledPin4, LOW);
break;
case 4: //data published
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
digitalWrite(ledPin4, HIGH);
break;
}
}


#2

@jonsm,
Have you tried adding a delay after the update and see if that helps. It is a bit hard to find the error from here, however another thing that you can do is to add debug statements in the update function in the library itself, in the lines here: https://github.com/DexterInd/DI_Arduino/blob/master/GPS_Shield/dGPS_Example_1/dGPS.cpp#L149-L273 and check what the update function does and where it is failing.


#3

Hi Karan,
Thanks for the suggestions! I THINK I tried a delay after update but I will try again, just in case.
If that doesn’t work I’ll try adding debug statements as you suggest and let you know how it goes.
Thanks for the input!
Jonathan


#4

Hi again Karan,
It’s working! (for now anyway :).
I tried a one second delay after dgps.update() and that didn’t make a difference. So, I added Serial.print() comments in the dgps.cpp file as suggested.
dgps.update(), getVel, getLat, getLon all completed. But, they were returning stale data. Since the calls are completing but the data is stale, I assume the GPS hardware is not able to get data during the update process? I assume that could be either due to a power issue or maybe an interference issue?
Here’s what I did:
I retested the GPS on a Mega all by itself and it worked.
I rewired my solution to make it as simple as possible - just the mega + GPS shield and wifi on a breadboard(no temp sensor, LEDs, etc to reduce power draw from those devices).
I moved the wifi to the opposite side of the Mega, because it was easier to wire that way (not because I assumed that would make a difference)
The solution is housed in a polycarbonate box with a lid. I opened the lid on the box while testing and pushed excess wire/cable to the corners of the box, away from the GPS.
I don’t know what of the above made a difference but now it is working!

Questions - would any of the following hinder GPS signal?
the 12v battery in the same box as GPS?
wire from the battery to mega?
wifi signal? (and would having it in a different location make a difference? Should I keep wifi and GPS as far apart in the box as possible?
temp sensor wire?
polycarbonate lid?
Also, might power draw from a few LEDs and a temp sensor be enough to starve the GPS of power?

I ask all of this because I need to add a few components back to the solution (like the temp sensor), and I want to have a sense of anything I should avoid/watch out for :).
Thanks for your help!!
Jonathan


#5

Hi @jonsm,
The wires shouldn;t be a problem.

The problems might be the battery or the box. Maybe the batteries are old and don;t have enough juice to power the GPS for extended duration. Can you try a different set of batteries and see if the things change.

The GPS usually needs an unobstructed view of the sky for good performance, however small obstacles are fine too. Not sure how thick the box is. So it can be the problem too.