Tiny GPS + Ethernet Shield

anyone have an idea about sending data of a GPS from Arduino+Ethernet Shield to a web browser? I have parallax PMB-688 GPS module, Arduino UNO & Ethernet Shield. over serial the GPS works perfectly using Tiny GPS, but I need to send those GPS data to the web browser. is it gonna work?

Yes, but you have to use the newest Arduino 1.0.1 and start with the built-in examples.

Your GPS module : http://www.parallax.com/Store/Sensors/CompassGPS/tabid/173/CategoryID/48/List/0/SortField/0/Level/a/ProductID/645/Default.aspx

Use the examples to create a webserver with a webpage. Use the serial port (pin 0, pin 1) for the GPS. This is already in use for the usb-to-ttl, so the GPS should override those signals. Or you could use the SoftwareSerial library.

You have to check which pins are in use for the Ethernet shield, but it is only a few.

It is even possible to have your webpage (or a whole website) on the sd card. I have a website on my sd card, and in some pages I have the code $1 or $2, and that is where the Arduino places it's data. Pictures are very slow this way, but with HTML5 a lot is possible with small html-files.

edit: On second thoughts, you need the serial monitor to create the webserver. So you perhaps you should start with the SoftwareSerial library right away : http://arduino.cc/en/Reference/SoftwareSerial

exactly! I can't create the web server using the arduino, so how am i gonna be able to create the server using the serial monitor? any example is appreciated! thanks a lot!

Yes, you can.

Use the examples built-in the Arduino. Like this one: http://arduino.cc/en/Tutorial/WebServer

There one change, that would make it easier. If you omit the "ip" with the Ethernet.begin() function, it uses DHCP to retrieve a valid IP from your router. So use it like this:

Ethernet.begin(mac);

troyka_4484:
exactly!
I can’t create the web server using the arduino, so how am i gonna be able to create the server using the serial monitor?
any example is appreciated!
thanks a lot!

Some simple meta refresh server code from the past you can try to see if it works ion your lan.

// zoomkat meta refresh server test code
// arduino IDE 1.0
// for W5100 ethernet shield
// the IP address will be dependent on your local network/router
// port 80 is default for HTTP, but can be changed as needed
// use IP address like http://192.168.1.102:84 in your brouser
// or http://zoomkat.no-ip.com:84 with dynamic IP service
// use the \ slash to escape the " in the html
// meta refresh set for 2 seconds

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

int x=0; //set refresh counter to 0
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,102); // ip in lan
EthernetServer server(84); //server is using port 84

void setup()
{
  // start the server
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
     while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // see if HTTP request has ended with blank line
        if (c == '\n') {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          
          //meta-refresh page every 2 seconds
          x=x+1; //page upload counter
          client.println("<HTML>");
          client.print("<HEAD>");
          client.print("<meta http-equiv=\"refresh\" content=\"2\">");
          client.print("<TITLE />Zoomkat's meta-refresh test</title>");
          client.print("</head>");
          client.println("<BODY>");
          client.print("Zoomkat's meta-refresh test IDE 1.0");
          client.println("
");
                    
          client.print("page refresh number ");
          client.println(x); //current refresh count
          client.println("
");
          client.println("
");
          
          client.print("Zoomkat's arduino analog input values:");
          client.println("
");
          client.println("
");
          
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(analogRead(analogChannel));
            client.println("
");
            }
           break;
          client.println("</BODY>");
          client.println("</HTML>");
         }
        }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}

ok, I’ve already have some experience in sending data using a web server, and I’ve used the code you posted to send a tempreture sensor data to a web browser, but I have no idea how to write the GPS data, that uses the Tiny GPS library, into the web browser?
here’s the GPS code:

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

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
*/

TinyGPS gps;
SoftwareSerial nss(3, 4);

static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup()
{
  Serial.begin(115200);
  nss.begin(4800);
  
  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS));
  Serial.println();
  Serial.println("Sats HDOP Latitude Longitude Fix  Date       Time       Date Alt     Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)    (deg)     Age                        Age  (m)     --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("--------------------------------------------------------------------------------------------------------------------------------------");
}

void loop()
{
  bool newdata = false;
  unsigned long start = millis();
  
  // Every second we print an update
  while (millis() - start < 1000)
  {
    if (feedgps())
      newdata = true;
  }
  
  gpsdump(gps);
}

static void gpsdump(TinyGPS &gps)
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
  
  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);

  print_date(gps);

  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  feedgps();
}

static void print_float(float val, float invalid, int len, int prec)
{
  char sz[32];
  if (val == invalid)
  {
    strcpy(sz, "*******");
    sz[len] = 0;
        if (len > 0) 
          sz[len-1] = ' ';
    for (int i=7; i<len; ++i)
        sz[i] = ' ';
    Serial.print(sz);
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1);
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(" ");
  }
  feedgps();
}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("*******    *******    ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d   ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  feedgps();
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  feedgps();
}

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

I wanna see the same results I am getting on the serial monitor but this time on a web browser…
Here, we have serial.print used in a function not in the main loop, that’s why I am a little bit confused!

I would keep the Serial.print as they are for the GPS, and add printing to the webpage to it.

You have to know a little about HTML code. Can you try on your computer to make a html file that looks how you would like it ? You can test it in your browser.

In the webserver code, the "client.print()" is used to build the HTML code. You could add the GPS data at that point. So you would get something like this:

  Serial.print("Testing TinyGPS library v. "); 
  client.print("Testing TinyGPS library v. ");
  Serial.println(TinyGPS::library_version());
  client.print(TinyGPS::library_version());
  client.println("
");

The " " is a new line in HTML code (the browser will start a new line).

Your next problem is RAM overflow. So you might want to rewrite the code with Serial.print(F("...")); or use PSTR to move the strings to the code area.

Ok, Krodal, I’m good in HTML, I will try it as soon as I arrive home, and I’ll tell you about the results!
Anyways Thanks!

It works like a charm! thanks Krodal! I appreciate it!

Good job. I'm glad you have it working !

troyka_4484: It works like a charm! thanks Krodal! I appreciate it!

Hi guys, do you mind share the code? please!

Another GPS library.

WORKING!

Plot.ly gps data streaming.

https://plot.ly/~trenanc/0/

#include <Ethernet.h>
#include <SPI.h>
#include "plotly_streaming_ethernet.h"
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);

#define GPSECHO  true
boolean usingInterrupt = false;
void useInterrupt(boolean); 
// Sign up to plotly here: https://plot.ly
// View your API key and streamtokens here: https://plot.ly/settings
#define nTraces 2
// View your tokens here: https://plot.ly/settings
// Supply as many tokens as data traces
// e.g. if you want to ploty A0 and A1 vs time, supply two tokens
char *tokens[nTraces] = {"sjhdc32erp", "rsv9z5vewu"};
// arguments: username, api key, streaming token, filename
plotly graph = plotly("trenanc", "9c8e5ydnyf", tokens, "Arduino", nTraces);

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte my_ip[] = { 189, 6, 135, 133 }; // google will tell you: "public ip address"

void startEthernet(){
    Serial.println("... Initializing ethernet");
    if(Ethernet.begin(mac) == 0){
        Serial.println("... Failed to configure Ethernet using DHCP");
        // no point in carrying on, so do nothing forevermore:
        // try to congifure using IP address instead of DHCP:
        Ethernet.begin(mac, my_ip);
    }
    Serial.println("... Done initializing ethernet");
    delay(1000);
}


void setup() {

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  startEthernet();
  graph.fileopt="overwrite"; // See the "Usage" section in https://github.com/plotly/arduino-api for details
  bool success;
  success = graph.init();
  if(!success){while(true){}}
  graph.openStream();
  
  GPS.begin(9600);  
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
  GPS.sendCommand(PGCMD_ANTENNA);
  useInterrupt(true);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
}

SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
    // writing direct to UDR0 is much much faster than Serial.print 
    // but only one character can be written at a time. 
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();

unsigned long x;
int y;

void loop() {
    if (! usingInterrupt) {
    char c = GPS.read();
  }
    if (GPS.newNMEAreceived()) {
  
    if (!GPS.parse(GPS.lastNMEA()))
      return;
  }
  if (timer > millis())  timer = millis();

  graph.plot(millis(), GPS.altitude, tokens[0]);
  graph.plot(millis(), GPS.speed, tokens[1]);
  
  delay(50);

}