LowPowerLab Forum

Hardware support => Moteino => Topic started by: dave_sausages on November 07, 2015, 01:35:14 AM

Title: Using GPS over software serial causes Moteino to lock up
Post by: dave_sausages on November 07, 2015, 01:35:14 AM
I'm currently working on a project to send GPS data over a pair of LoRa Moteino modules, and I'm also a moderate beginner at Arduino (Although I've previously made a gps controlled sunset clock that outputs the time till sunset to an LCD).

Anyway, I can't get my head around how to run an instance of Tinygps++ to read data from my ublox neo-6m gps module without it causing my program to lock up. For the moment I'm just using the example program to send 'Hello world!" to the other Moteino, and that all works fine. But whenever I enable the reading of GPS infomation, it causes the program to lock up. I've looked at many different examples of a moteino using a GPS, and they all seem to use rather complex timing loops to avoid conflicts, and I'm not at that level with my programming yet.

Can anyone give me some clues on how to achieve this? My example program is below:

//// rf95_client.pde
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messageing client
// with the RH_RF95 class. RH_RF95 class does not provide for addressing or
// reliability, so you should only use RH_RF95 if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example rf95_server
// Tested with Anarduino MiniWirelessLoRa

#include <SPI.h>
#include <RH_RF95.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

// Singleton instance of the radio driver
RH_RF95 rf95;

static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

void setup()
{
  Serial.begin(9600);
  if (!rf95.init())
    Serial.println("init failed");
  else Serial.println("init OK - 915mhz");
 
  // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
  rf95.setFrequency(915);
}

void loop()
{
  Serial.println("Sending to rf95_server");
  // Send a message to rf95_server

 
  byte data[] = "hello world!";
  rf95.send(data, sizeof(data));
 
  rf95.waitPacketSent();
  // Now wait for a reply
  uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  if (rf95.waitAvailableTimeout(3000))
  {
    // Should be a reply message for us now   
    if (rf95.recv(buf, &len))
   {
      Serial.print("got reply: ");
      Serial.println((char*)buf);
      Serial.print("RSSI: ");
      Serial.println(rf95.lastRssi(), DEC);   
    }
    else
    {
      Serial.println("recv failed");
    }
  }
  else
  {
    Serial.println("No reply, is rf95_server running?");
  }
 

/*
// This sketch displays information every time a new sentence is correctly encoded.
while (ss.available() > 0)
   if (gps.encode(ss.read()))
      displayInfo();

  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    while(true);
  }
*/
}


void displayInfo()
{
  Serial.print(F("Location: "));
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}


This sketch runs fine, but if I enable the commented out section above 'void displayInfo()' then the serial monitor crashes after two send routines showing this:
SS pin:10
int pin:2
int number:0
init OK - 915mhz
Sending to rf95_server
No reply, is rf95_server running?
Sending to rf95_server
No reply, is rf95_server running?
No GPS detected: check wiring.



Oh and here's one of the examples I've been trying to butcher into my project, but the 'char gpsLocate()' section confuses me. So far I've only used setup and void loops, and the odd section that is called and passes data, but I don't understand how this char section works.

**can't insert code, makes post too long***

https://github.com/ptamike/UKHASnetGPS_sensor_node/blob/master/hasnetSensorGPS.ino (https://github.com/ptamike/UKHASnetGPS_sensor_node/blob/master/hasnetSensorGPS.ino)

So once again, if anyone can help it's greatly appreciated. And as I'll probably require a lot of annotating so I can learn from this problem and move forward, I'm prepared to pay for someone's services if it's required.

P.S. I'm aware I've also got a current thread running about this project, but as the two topics are about different problems I thought it would help future newbies by having separate topics.

Many thanks

Dave
Title: Re: Using GPS over software serial causes Moteino to lock up
Post by: TomWS on November 07, 2015, 09:38:21 AM
ss.read() only reads a single byte.  I think you want to readUntil() into a buffer before calling the GPS function.

Out of curiosity (I don't want to hijack the thread) what GPS receiver are you using?

Tom
Title: Re: Using GPS over software serial causes Moteino to lock up
Post by: dave_sausages on November 10, 2015, 05:19:31 PM
I can't see an example of the TinyGPS library using readuntil() online, even the HasnetGPS example linked to my first post uses read()

static void smartDelay(unsigned long ms) //+++ Delay function to feed the gps object
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}


I'm still trying to understand how best to use these modules. I guess my question boils down to:

Do the send and receive functions have to take the whole 'focus' of the program while they are running? For example if I were to send a message that took 0.2 seconds, can I do anything else in that 0.2 seconds? Or do I have to just start the 'send' and then wait for it to finish sending before doing anything else?

And is it the same for the receive function? How do I make sure that my Moteino isn't doing something else when it's being sent a message?

At the moment all I want to do is get gps lat/long data, send it to the other Moteino, and have the other Moteino do the same in reverse.

I can currently either get GPS data, or use the LoRa radio link, but when I try to do both at the same time, I get no GPS data (LoRa link appears to interrupt the parsing of NMEA strings).

I'm currently in the process of converting over to the NEOgps library as this allows the detection of 'quiet time' between gps sentences and the ability to run code in that time gap. I suspect there's a clever way of doing it with tinygps++, but I can't work it out myself.

Any help that explains the theory of a solution so that I can learn from it is greatly appreciated.

Dave
Title: Re: Using GPS over software serial causes Moteino to lock up
Post by: TomWS on November 10, 2015, 11:01:07 PM
Quote from: TomWS on November 07, 2015, 09:38:21 AM
ss.read() only reads a single byte.  I think you want to readUntil() into a buffer before calling the GPS function.
Sorry, I should have said Serial.readBytesUntil().  This would give you a full sentence to decode rather than the single byte from Serial.read().
See https://www.arduino.cc/en/Serial/ReadBytesUntil

Tom
Title: Re: Using GPS over software serial causes Moteino to lock up
Post by: dave_sausages on November 13, 2015, 11:37:20 AM
I've changed over to the Neogps library and am now using its 'quiet time' function to do the LoRa work. Basically it waits until the last sentence has been received from the gps and then exits the gps loop and runs whatever you want it to.

I'm still wondering though, it it possible to do anything else while LoRa packets are being sent or received? Now I've passed this first hurdle I'm keen to add a keypad to interface with. The problem is: as far as I can tell, if I'm sending a packet or receiving a packet, I can't read the state of my keypad and could miss a keypress. Are there any tricks to being able to do this?