Jump to content

Banner.jpg.b83b14cd4142fe10848741bb2a14c66b.jpg

Simple GPS 'NMEA server' on an Arduino for INDI?


AstroPhil

Recommended Posts

Hello all,

I've been playing around with a few spare 'bits and bobs' and sucessfully made a little GPS receiver using a NEO-8M chip and a spare Arduino I had (plus an ethernet shield). I was just going to use it to set the time on my astroberry / stellarmate when not connected to the network, but then I came across this very interesting driver in the INDI library: https://www.indilib.org/devices/auxiliary/gps-nmea.html

This seems to do a lot of the hard work for me.... but I cannot fathom how to actually send the data from the GPS chip (it's a serial connection / multi-line 'string' as it were) to generate a web server for the INDI to connect to as client. 

So, this is just a shout out to the collective to see if anyone has already tried and come up with a solution, before I spend another day googling! I suspect I have simply miss-understood the syntax/formatting... but so far the detail of how to fix this has eluded me....

I know there are a few folks here who are far better coders than I am - so, any words of wisdom would be great! (arduno sketch below)

Phil

#include <TinyGPS++.h>
#include <SPI.h>
#include <Ethernet.h>

// The TinyGPS++ object
TinyGPSPlus gps;

// set up the simple web server
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 128);
EthernetServer server(80);

void setup() {
  // Open serial communications and wait for port to open:
  Serial1.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Ethernet WebServer");

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }
  // start the server
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 2");  // refresh the page automatically every 2 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");

// Below is the raw output of the GPS chip (NMEA format)... But it doesn't work when added directly to the web server code.
// Formatting/syntax issues? But I wonder what format the GPS NMEA server needs anyway?
//
//while (Serial1.available() > 0){
//Serial.write(Serial1.read());
//}
            client.print(F(" Hour=")); // but this is fine... but just goes to the web browser... not the INDI client.
            client.print(gps.time.hour());
            client.print(F(" Minute="));
            client.print(gps.time.minute());
            client.print(F(" Second="));
            client.println(gps.time.second());
            
          client.println("<br />");
          
            client.print(F("Fix-Age="));
            client.print(gps.location.age());
            client.print(F(" Lat="));
            client.print(gps.location.lat(), 6);
            client.print(F(" Long="));
            client.println(gps.location.lng(), 6);
          
          client.println("<br />");
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }

// This is the raw output of NMEA ...  
//while (Serial1.available() > 0){
//Serial.write(Serial1.read());
//}

// This is the parsed data, using TinyGPS++ to see if it's working - it's fine, in the arduino serial monitor...
//
// Dispatch incoming characters
  while (Serial1.available() > 0)
    gps.encode(Serial1.read());
  if (gps.location.isUpdated())
  {
    Serial.print(F("LOCATION   Fix Age="));
    Serial.print(gps.location.age());
    Serial.print(F(" Lat="));
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(" Long="));
    Serial.println(gps.location.lng(), 6);
  }
  else if (gps.date.isUpdated())
  {
    Serial.print(F("DATE       Fix Age="));
    Serial.print(gps.date.age());
    Serial.print(F("ms Raw="));
    Serial.print(gps.date.value());
    Serial.print(F(" Year="));
    Serial.print(gps.date.year());
    Serial.print(F(" Month="));
    Serial.print(gps.date.month());
    Serial.print(F(" Day="));
    Serial.println(gps.date.day());
  }
  else if (gps.time.isUpdated())
  {
    Serial.print(F("TIME       Fix Age="));
    Serial.print(gps.time.age());
    Serial.print(F("ms Raw="));
    Serial.print(gps.time.value());
    Serial.print(F(" Hour="));
    Serial.print(gps.time.hour());
    Serial.print(F(" Minute="));
    Serial.print(gps.time.minute());
    Serial.print(F(" Second="));
    Serial.print(gps.time.second());
    Serial.print(F(" Hundredths="));
    Serial.println(gps.time.centisecond()); 
  }
  else if (gps.altitude.isUpdated())
  {
    Serial.print(F("ALTITUDE   Fix Age="));
    Serial.print(gps.altitude.age());
    Serial.print(F("ms Raw="));
    Serial.print(gps.altitude.value());
    Serial.print(F(" Meters="));
    Serial.println(gps.altitude.meters());
  }
  else if (gps.satellites.isUpdated())
  {
    Serial.print(F("SATELLITES Fix Age="));
    Serial.print(gps.satellites.age());
    Serial.print(F("ms Value="));
    Serial.println(gps.satellites.value());
  }


// the final loop void loop close  
}

 

Link to comment
Share on other sites

Sucess!

Took a weekend of googling but turned out my code was entirely 'barking up the wrong tree' as it were. Here's the final design and code, in case anyone else is interested. This uses an arduino MKR1010 and a MKR Ethernet shield (which I had spare: see photo), coupled to an NEO-8m GPS chip from AZ-Delivery. My motivation here was to provide my (new portable!) rig with a method to import location and time across the network to the two Raspberry Pi's I have mounted. Works a treat with the Ekos NMEA driver: all of this is a local network, so completely independent of the home network - hooked up to a laptop using a single ethernet cable.

P.

 

#include <Ethernet.h>
#define LF          0x0A
char data[200];
int idx;

byte mac[] = {0x54, 0x52, 0x49, 0x41, 0x44, 0x00};
// byte ip[] = {192, 168, 1, 128}; // for house network
byte ip[] = {169, 254, 95, 128}; // for closed network
EthernetServer server(50000);
EthernetClient client;

void setup() {
  Serial1.begin(9600);
  idx = 0;   
//Serial.println("Ethernet WebServer");
  // Start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  // Check for Ethernet hardware present:
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
      }
  server.begin();
  client = server.available();
  }
}

void loop() {
//Serial.print("server active at ");
//Serial.println(Ethernet.localIP());
  while (!client){
      if (Serial1.available() > 0){
      data[idx] = Serial1.read();
        if (data[idx] == LF) {
          data[idx-1] = 0;
//Serial.println(data);
          delay(10);
          server.println(data);
          idx = -1;
          }
      idx++;
      }
    }
}

 

2021-01-03 21.35.14.jpg

Screen Shot 2021-01-03 at 9.57.16 PM.png

 

Edited by AstroPhil
typo
  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. By using this site, you agree to our Terms of Use.