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