Cape Town South Africa
Offline
Edison Member
Karma: 17
Posts: 1104
A newbie with loads of posts, and still so much to learn !
|
 |
« on: November 11, 2011, 04:15:09 pm » |
I have searched and found loads of projects with clocks using a gps module, but some have RTC chips too, and some seem very complicated.
What I want to try is ( in its simplest form where the clock can be mounted by a window or wherever there is gps signal ) have a Arduino 328 chip, running a simple 4 digit LED clock.
The display will be latched using TPIC6B595 shift reg drivers. There are no multiplexing delays in the loop, the display is refreshed once per minute.
The general timing of the minute could be a simple " blink without delay" millis check to see if the count has reached 60 seconds.
A cheap gps module that churns out NMEA strings , via ttl connections to the Arduino chip UART from which I could mask out the hours and minutes digits.
If the signal lock is high, and there is a change in the ten minutes digit, it must update the display counter of the Arduino chip.
( I suppose I could get fancy and check the error first to correct the millis counter to fine tune the error )
The next step would be to have the gps module in the window, sending the time every 10 minutes via a rf link to the clock, or clocks across the room, but I just want to start somewhere.
If I wanted to start really simple, I could just mask out the minutes and hours numbers from the NMEA string, updated every second, and send them to the LED displays via a lookup table, and not bother with a timer at all in the micro?
Has anyone played with this?
|
|
|
|
|
Logged
|
We live in the era of the smart phones and stupid people.
|
|
|
|
Massachusetts, USA
Offline
Tesla Member
Karma: 98
Posts: 6389
|
 |
« Reply #1 on: November 11, 2011, 04:38:32 pm » |
I've done parsing of a NEMA message. In my case I wanted Lat, Lon, and Altitude. Perhaps my code can be used as a model. #include <NewSoftSerial.h>
// Fault flags extern const unsigned int GPS_fault; extern unsigned int Faults;
NewSoftSerial GPS(2, -1);
// Parse GPS message byte GPS_byteCount = 0; unsigned char GPS_buff[100]; unsigned long GPS_time = 0; String GPS_lat = ""; String GPS_long = ""; String GPS_altitude = ""; unsigned long GPS_lastgood = 0; unsigned long GPS_lasttest = 0;
void GPS_setup(void) { GPS.begin(4800); }
void GPS_loop(void) { // If any characters are available from the GPS, send them to the parser while (GPS.available()) { GPS_parse_char(GPS.read()); }
// Check for GPS status if ((millis() - GPS_lastgood > 3000)) Faults |= GPS_fault; }
void GPS_log(Print &dest) { // Log GPS data dest.print(GPS_time, DEC); dest.print(','); dest.print(GPS_lat); dest.print(','); dest.print(GPS_long); dest.print(','); dest.print(GPS_altitude); dest.print(','); dest.print((millis() - GPS_lastgood)/1000); }
int GPS_parse_char(byte inputChar) { switch (inputChar) { case '\r': return GPS_check_buffer();
case '$': GPS_byteCount = 0; // Start of message
default: GPS_buff[GPS_byteCount++] = inputChar; if (GPS_byteCount == 100) { GPS_byteCount = 0; // Start of message return -3; // Buffer overrun } return 0; // Not a full message } }
int GPS_check_buffer() { GPS_buff[GPS_byteCount] = '\0';
unsigned char *buffp = GPS_buff;
// Check the message type for (int i=0; i<7; i++) { if (buffp[i] != "$GPGGA,"[i]) return 0; }
// Verify the checksum before doing any more if (GPS_buff[GPS_byteCount-3] != '*') // Checksum marker return -1; // Bad message format
byte checksum = 0; for (int i=1; i<GPS_byteCount-3; i++) // Skip '$' and '*' checksum ^= GPS_buff[i]; // Test the result checksum -= hexval(GPS_buff[GPS_byteCount-2]) << 4; checksum -= hexval(GPS_buff[GPS_byteCount-1]);
if (checksum != 0) return -2; // Checksum failure
// parse the time field buffp += 7; // Skip over $GPGGA, GPS_time = 0; while (hexval(*buffp) != -1) // for each digit { GPS_time *= 10; GPS_time += hexval(*buffp); buffp++; }
if (*buffp++ != '.') // Should be a decimal point return -1;
while (*buffp == '0') // Skip zeros buffp++;
if (*buffp++ != ',') // Should be a comma return -1;
// Parse latitude GPS_lat = ""; for (int i=0; i<20; i++) { if (*buffp == ',') break; GPS_lat += *buffp++; if (i == 1) GPS_lat += ' '; // Separate degrees from minutes } buffp++; // skip the comma
if (*buffp == 'S') GPS_lat = "-" + GPS_lat; else if (*buffp != 'N') return -1;
buffp++; // Skip the N or S
if (*buffp++ != ',') // Should be a comma return -1;
// Parse longitude GPS_long = ""; for (int i=0; i<20; i++) { if (*buffp == ',') break; GPS_long += *buffp++; if (i == 2) GPS_long += ' '; // Separate degrees from minutes } buffp++; // skip the comma
if (*buffp == 'W') GPS_long = "-" + GPS_long; else if (*buffp != 'E') return -1;
buffp++; // Skip the E or W
if (*buffp++ != ',') // Should be a comma return -1;
if (*buffp++ == '0') { Faults |= GPS_fault; return -3; // No view of sattelites }
if (*buffp++ != ',') // Should be a comma return -1;
GPS_lastgood = millis();
while (*buffp++ != ',') ; // Skip number of satellites while (*buffp++ != ',') ; // Skip horizontal dillution GPS_altitude = ""; while (*buffp != ',') GPS_altitude += *buffp++;
//Serial.println((char *)GPS_buff); Faults &= ~GPS_fault; return 1; // Good fix }
int hexval(char digit) { if (digit >= '0' && digit <= '9') return digit - '0';
if (digit >= 'A' && digit <= 'F') return digit - 'A' + 10;
if (digit >= 'a' && digit <= 'f') return digit - 'a' + 10;
return -1; }
|
|
|
|
|
Logged
|
|
|
|
|
Newcastle, England
Offline
Sr. Member
Karma: 2
Posts: 489
Always learning!
|
 |
« Reply #2 on: November 11, 2011, 04:49:17 pm » |
I've played with a GPS module before, using this code: char data[300]; char GPSsignature[7] = "$GPRMC"; int comma[13]; int ledPin = 13; // LED test pin int GPSbyte; int count; int correctData;
void setup() { pinMode(ledPin, OUTPUT); // Initialize LED pin Serial.begin(4800); }
void loop() { digitalWrite(ledPin, HIGH);
if (Serial.available() > 0){ GPSbyte=Serial.read(); // Read a byte of the serial port data[count]=GPSbyte; // If there is serial port data, it is put in the array count++;
if (GPSbyte==13){ // If the received byte is = to 13, end of transmission digitalWrite(ledPin, LOW); count=0; correctData=1;
for (int i=1;i<7;i++){ // Verifies if the received command starts with $GPR if (data[i]!=GPSsignature[i-1]) correctData=0; }
if(correctData){ // If yes, countinue and process the data for (int i=0;i<300;i++){ if (data[i]==','){ // check for the position of the "," separator comma[count]=i; count++; } if (data[i]=='*'){ // ... and the "*" comma[12]=i; count++; } } count = 0;
Serial.println("---------------"); for (int i=0;i<8;i++){ switch(i){ case 0 : Serial.print("Time in UTC (HhMmSs): "); break; case 1 : Serial.print("Status (A=OK,V=!OK): "); break; case 2 : Serial.print("Latitude: "); break; case 3 : Serial.print("Direction (N/S): "); break; case 4 : Serial.print("Longitude: "); break; case 5 : Serial.print("Direction (E/W): "); break; case 6 : Serial.print("Velocity in knots: "); break; case 7 : Serial.print("Heading in degrees: "); break; case 8 : Serial.print("Date UTC (DdMmAa): "); break; }
for (int j=comma[i];j<(comma[i+1]-1);j++){ Serial.print(data[j+1]); } Serial.println(""); } } } } else delay(100); }
It takes in all the data from the GPS via the serial port, then extrancs the data and prints out each individual part. If you wanted, you could ignore the lat,lon,altitude,n/s,e/w bits and just look at the time, which will not be too hard. I managed to find a decent GPS module for £20, but I cannot find it in the shop I bought it from, so no links... It had good accuracy though, quick to find sattelites, and worked indoors! Onions.
|
|
|
|
|
Logged
|
|
|
|
|
Cape Town South Africa
Offline
Edison Member
Karma: 17
Posts: 1104
A newbie with loads of posts, and still so much to learn !
|
 |
« Reply #3 on: November 11, 2011, 04:56:01 pm » |
Thanks guys, that helps a lot.
There are some cheap GPS modules here, I will get one and try it out if I get some time this weekend, I must make sure it has ttl connections though.
I will first try the simplest displaying the hhmm barebones version, and post any results
|
|
|
|
|
Logged
|
We live in the era of the smart phones and stupid people.
|
|
|
|
New River, Arizona
Offline
God Member
Karma: 15
Posts: 876
Arduino rocks
|
 |
« Reply #4 on: November 11, 2011, 10:57:36 pm » |
I did this, but a bit more elaborately. I needed a time standard for my entire house. I have several devices (thermostats, timers, etc) around the house that needed the time, and originally, I was getting the time over the internet from NIS. This wasn't as good an idea as I thought it would be. Seems the NIS servers sometimes don't respond and sometimes the internet doesn't work (duh !). So I got a GPS module, hooked an arduino to it with an ethernet shield and had a LAN based clock that was synced to the satellites. This was cool, but I still had some problems with the ethernet. So, I built an XBee network and modified the satellite clock to work over it as well. Now, I have a clock that is synced with the satellites and transmits the time over the LAN on request and also transmits over the XBee network to sync the various devices around the house. Oh, it also has a serial LCD display that shows the time on the front of it. However, I almost never see the display, it is in an attic room that also houses my router, phone and TV distribution stuff as well as my comic book collection (total geek I am). The code is online at my blog (see signature line) or get to it directly http://www.desert-home.com/p/house-clock.htmlFeel free to snag anything you want.
|
|
|
|
|
Logged
|
|
|
|
|
Cape Town South Africa
Offline
Edison Member
Karma: 17
Posts: 1104
A newbie with loads of posts, and still so much to learn !
|
 |
« Reply #5 on: November 12, 2011, 12:24:06 am » |
Thats a cool house/lab you have there ! I looked at your code and have to admit it makes me realise how little I know yet about programming ! but I am learning all the time.
I am sure with all the sketches you guys have supplied I will find a way to get the time from the NMEA string.
Sending to the LED displays I am an old hat with now :-)
|
|
|
|
|
Logged
|
We live in the era of the smart phones and stupid people.
|
|
|
|
Dubuque, Iowa, USA
Offline
Edison Member
Karma: 13
Posts: 1546
|
 |
« Reply #6 on: November 12, 2011, 01:34:34 am » |
Use a TLC5916 or STP16C596 instead of the TPIC6B59. The outputs are current-controlled so you can avoid all the resistors.
|
|
|
|
|
Logged
|
|
|
|
|
Cape Town South Africa
Offline
Edison Member
Karma: 17
Posts: 1104
A newbie with loads of posts, and still so much to learn !
|
 |
« Reply #7 on: November 12, 2011, 03:05:46 am » |
Thats a far better chip,, but I still have a few hundred of the TPIC595 ones to use up first .
|
|
|
|
|
Logged
|
We live in the era of the smart phones and stupid people.
|
|
|
|
New River, Arizona
Offline
God Member
Karma: 15
Posts: 876
Arduino rocks
|
 |
« Reply #8 on: November 12, 2011, 12:25:26 pm » |
Few HUNDRED ??? Wow, you believe in stocking up....
Regarding code, don't take mine as an example of how it should be. Even though it works pretty well, I keep finding things I should have done differently. I don't know about other folk, but sometimes I'm a-feared of showing my code because people will laugh at it. They haven't yet, but I'm sure it's coming.
shudder
|
|
|
|
|
Logged
|
|
|
|
|
Cape Town South Africa
Offline
Edison Member
Karma: 17
Posts: 1104
A newbie with loads of posts, and still so much to learn !
|
 |
« Reply #9 on: November 12, 2011, 03:25:13 pm » |
I use a lot of them in my business, so I choose them for the hobby experimantal stuff too.
I asked a good friend who sells components for a quote on them a few months ago, and his supplier in Hong Kong thought he was ordering them, and sent them in the next container, so I am sort of committed to buying these chips until they are used up !
Re your code, thats fine its a great starting point, I often start with a section of code from someones example, and mess around experimenting with it to help me learn...... I have been playing with the Arduino for a year now, and have made dozens of projects, and I feel I probably know 1% of it all now !
|
|
|
|
|
Logged
|
We live in the era of the smart phones and stupid people.
|
|
|
|
Cape Town South Africa
Offline
Edison Member
Karma: 17
Posts: 1104
A newbie with loads of posts, and still so much to learn !
|
 |
« Reply #10 on: November 12, 2011, 08:16:32 pm » |
Its 3 am , passing through the office, brain still asleep, wondering how I am going to Serial.print("Velocity in knots: "); when I have the gps module connected to the serial port ???
|
|
|
|
|
Logged
|
We live in the era of the smart phones and stupid people.
|
|
|
|
New River, Arizona
Offline
God Member
Karma: 15
Posts: 876
Arduino rocks
|
 |
« Reply #11 on: November 12, 2011, 08:39:14 pm » |
read about NewSoftSerial when you wake up.
|
|
|
|
|
Logged
|
|
|
|
|
Cape Town South Africa
Offline
Edison Member
Karma: 17
Posts: 1104
A newbie with loads of posts, and still so much to learn !
|
 |
« Reply #12 on: November 12, 2011, 10:56:51 pm » |
Ah, now that rings a bell, thanks
|
|
|
|
|
Logged
|
We live in the era of the smart phones and stupid people.
|
|
|
|
Cape Town South Africa
Offline
Edison Member
Karma: 17
Posts: 1104
A newbie with loads of posts, and still so much to learn !
|
 |
« Reply #13 on: November 25, 2011, 03:35:19 am » |
Back on the project again, finally got the cheapy GPS receiver module, hooked it up on a bit of stripboard and used NewSerailSoft and the sketch from Onions ( thank you ) and its working fine from the 3v3 supply from the Arduino board.
The time comes on correct immediately , even while its waiting for the satellite fixes ? Theres no back up battery, but thats fine. I guess it only needs the first satellite for the time.
I dont know if I have found why it was cheap, but it places my house about 100 Km up the coast , every time !
I couldnt give a hoot about the position for my clock project, and will find out if they have a whole bucket of these cheap :-)
|
|
|
|
|
Logged
|
We live in the era of the smart phones and stupid people.
|
|
|
|
Cape Town South Africa
Offline
Edison Member
Karma: 17
Posts: 1104
A newbie with loads of posts, and still so much to learn !
|
 |
« Reply #14 on: November 25, 2011, 11:49:27 am » |
Hmm, while it runs fine for 10 minutes, reading out the time etc, it freezes after 10 minutes or so. Am I filling some buffer or something? Heres the test sketch :- #include <NewSoftSerial.h>
NewSoftSerial GPS1(14, 15);
char data[300]; char GPSsignature[7] = "$GPRMC"; int comma[13]; int ledPin = 13; // LED test pin int GPSbyte; int count; int correctData;
void setup() { pinMode(ledPin, OUTPUT); // Initialize LED pin Serial.begin(115200); GPS1.begin(9600); }
void loop() { digitalWrite(ledPin, HIGH);
if (GPS1.available() > 0){ GPSbyte=GPS1.read(); // Read a byte of the serial port data[count]=GPSbyte; // If there is serial port data, it is put in the array count++;
if (GPSbyte==13){ // If the received byte is = to 13, end of transmission digitalWrite(ledPin, LOW); count=0; correctData=1;
for (int i=1;i<7;i++){ // Verifies if the received command starts with $GPR if (data[i]!=GPSsignature[i-1]) correctData=0; }
if(correctData){ // If yes, countinue and process the data for (int i=0;i<300;i++){ if (data[i]==','){ // check for the position of the "," separator comma[count]=i; count++; } if (data[i]=='*'){ // ... and the "*" comma[12]=i; count++; } } count = 0;
Serial.println("---------------"); for (int i=0;i<9;i++){ switch(i){ case 0 : Serial.print("Time in UTC (HhMmSs): "); break; case 1 : Serial.print("Status (A=OK,V=!OK): "); break; case 2 : Serial.print("Latitude: "); break; case 3 : Serial.print("Direction (N/S): "); break; case 4 : Serial.print("Longitude: "); break; case 5 : Serial.print("Direction (E/W): "); break; case 6 : Serial.print("Velocity in knots: "); break; case 7 : Serial.print("Heading in degrees: "); break; case 8 : Serial.print("Date UTC (DdMmAa): "); break; }
for (int j=comma[i];j<(comma[i+1]-1);j++){ Serial.print(data[j+1]); } Serial.println(""); } } } } else delay(100); }
|
|
|
|
|
Logged
|
We live in the era of the smart phones and stupid people.
|
|
|
|
|