My ADS (analog Digital Synthesiser) built using an Arduino UNO and an AD9851 chip includes a RTC DS3231 with a back up battery. The intention is to have UTC time available to software running on the Arduino UNO. So that it can generate correctly timed WSPR and JT65 output. It also includes a MMIC amplifier to output up to 10mW into 50R.
Internal view of the VFO
TIME
At the moment I have a special Arduino sketch "DATE_TIME_SET_OLED" - see below - which I use to set the date and time in the RTC, it needs you to enter the date & time in the format YYMMDDWHHMMSS (W = day of week, Sunday = 1) in the Arduino Monitor window, then hit "Send" at exactly the right moment to set the correct time. Obviously this is a bit hit-and-miss, and also relies on your Computer displaying the right time to the second (my MacBook does this automatically by reading time from time.apple.com, but I have had trouble with my Windows PC which loses lock).
Anyway it seemed to me that by providing a new input/output connection to the Arduino UNO in the VFO I could send in information from a GPS receiver, extract the date and time and automatically calibrate the internal RTC. I could then also use the same connection in other sketches to input or output a couple of signals to any external device when the GPS is not used...
GPS RECEIVER
First a GPS receiver, I searched the internet and found a very low cost solution - GPS receivers that are targeted at car navigation and dash board cameras market. Like this one, VK-163 G-Mouse Headphone Wire Interface Navigation GPS,
GPS Receiver
It has a 4 way 3.5mm jack plug. After a considerable time fussing about with it I discovered the connections, which are,
Jack tip = VCC 3.6-5V
1st ring = GPS TX output (NMEA output data strings)
2nd ring = GPS RX Input (configuration input commands)
Jack shaft = Ground
And I wired it up to an Arduino UNO, using pin 12 as UNO RX to GPSTX, and pin 13 as UNO TX to GPS RX. />
GPS wiring to Arduino UNO
The Arduino connections I used can be read in the sketch below. Basically pin 12 for data coming in, and pin 13 for any commands I may want to send out. Though I found the GPS works out of the box with 1 second updated outputs without giving any new commands, so I haven't used pin 13 in my sketch.
The results, when I insert Serial.print() commands, are that I can read the NMEA message "$GPRMC" on the serial monitor like this,
GPS NMEA ASCII string data for the $GPRMC message ID
Below are the sketches code for the manual set time and the GPS reception. Now all I have to do is extract the time and date info from the GPS string and program the RTC...
CODE
// DATE_TIME_SET_OLED // V1.0 9-5-17 does not use DS3231 library // enter YYMMDDwHHMMSS, reset/reload to repeat // w = day-of-week 1 = mon, 01 = Jan 17 = 2017, 24 hour clock // RTC // SDA A4 // SCL A5 // SW 4 #include "Wire.h" #include "Oled_128X64_I2C.h" // RTC address #define RTCADDR 0x68 // RTC time and date byte doW, date, month, year; byte hrs, mns, sec; bool gotString; void setup() { Serial.begin(9600); Wire.begin(); oled.begin(); gotString = false; dispUpdate(); } void loop() { char inString[20] = ""; byte j = 0; while (!gotString) { if (Serial.available()) { inString[j] = Serial.read(); if (inString[j] == '\n') { gotString = true; // convert ASCII codes to bytes year = ((byte)inString[0] - 48) * 10 + (byte)inString[1] - 48; month = ((byte)inString[2] - 48) * 10 + (byte)inString[3] - 48; date = ((byte)inString[4] - 48) * 10 + (byte)inString[5] - 48; doW = ((byte)inString[6] - 48); hrs = ((byte)inString[7] - 48) * 10 + (byte)inString[8] - 48; mns = ((byte)inString[9] - 48) * 10 + (byte)inString[10] - 48; sec = ((byte)inString[11] - 48) * 10 + (byte)inString[12] - 48; setRTC(); } j += 1; } } getRTC(); // get time dispUpdate(); } // set the time int he RTC void setRTC() { // sets time and date data to DS3231 Wire.beginTransmission(RTCADDR); Wire.write(0); // set next input to start at the sec register Wire.write(decToBcd(sec)); // set seconds Wire.write(decToBcd(mns)); // set minutes Wire.write(decToBcd(hrs)); // set hours Wire.write(decToBcd(doW)); // set day of week (1=Sunday, 7=Saturday) Wire.write(decToBcd(date)); // set date (1 to 31) Wire.write(decToBcd(month)); // set month Wire.write(decToBcd(year)); // set year (0 to 99) Wire.endTransmission(); } // get time from RTC, convert bcd to decimal void getRTC() { // Reset the RTC register pointer Wire.beginTransmission(RTCADDR); Wire.write(0x00); // output start at sec register Wire.endTransmission(); // request 7 bytes from the RTC address Wire.requestFrom(RTCADDR, 7); // get the time data sec = bcdToDec(Wire.read()); // 0 - 59 mns = bcdToDec(Wire.read()); // 0 - 59 hrs = bcdToDec(Wire.read() & 0b111111); //mask 12/24 bit doW = bcdToDec(Wire.read()); //0 - 6 = Sunday - Saturday date = bcdToDec(Wire.read()); // 1 - 31 month = bcdToDec(Wire.read()); // 0 = jan year = bcdToDec(Wire.read()); // 20xx } // Convert normal decimal numbers to binary coded decimal byte decToBcd(byte val) { return( (val/10*16) + (val%10) ); } // Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) { return( (val/16*10) + (val%16) ); } // picture loop, display init data void dispUpdate() { oled.firstPage(); do { if (gotString == true) { dispDate(15, 15, doW, date, month, year); dispTimeL(25, 40, hrs, mns, sec); } else { dispMsg(0, 15, ">> YYMMDDwHHMMSS"); } } while ( oled.nextPage() ); }
MORE CODE
// GPS_READ_MSG_PRINT // V0.4 basics of read GPS // Jack plug/socket wiring // tip VCC (Y) // 2 TX GPS (R) // 3 RX GPS (OR) // ring GND (BWN) #include "SoftwareSerial.h" // connections GPSRX -> RX, GPSTX <- TX #define RX 12 #define TX 13 // GPS data buffer, gps message ID char gpsbuf[200]; char MSGID[10] = "$GPRMC"; // jack GPS 3(TX) -> RX, GPS 2(RX) <- TX SoftwareSerial gps (RX, TX); void setup() { pinMode(RX, INPUT); pinMode(TX, OUTPUT); Serial.begin(9600); gps.begin(9600); // start GPS serial Serial.println("Start"); } void loop() { // read MSGID line do { getline(gpsbuf); } while (strncmp(gpsbuf, MSGID, 6) != 0); Serial.print(gpsbuf); } // get a line from the GPS, inc /r/n, add /0 void getline(char *buf) { char c; int p = 0; do { if (gps.available() > 0) { c = gps.read(); buf[p++] = c; } } while ( c != '\n'); buf[p] = '\0'; }
1 comment:
pls edit the code this out in absence of millisecond format
Post a Comment