/ RFout1MHzV1_04 / RFout1MHzV1_04.ino
RFout1MHzV1_04.ino
1 //Software for Zachtek "GPS Referenced RF generator 1MHz Out" with a 8MHz Mini Pro Arduno 2 //This will program an NEO-6 Gps module at startup to output an RF signal when locked. 3 //The NEO-6 has an internal 48MHz PLL that can be diveded down to any freq below 10MHz. Divide to a frequency that is an integer fraction of 48MHz to get 4 //the lowest jitter 5 //Examples on low jitter freqencies is 1, 2, 4 and 8 MHz 6 //To compile you need to install the Library "NeoGps by SlashDevin", you can download it using The Library manager in the Arduino IDE 7 //ZachTec 2017-2018 8 9 //The Version of this software is stored in the constant "softwareversion" and is displayed on the Serialport att startup 10 //For Arduino Pro Mini. 11 #include <NMEAGPS.h> //NeoGps by SlashDEvin https://github.com/SlashDevin/NeoGPS 12 #include <SoftwareSerial.h> // SoftwareSerial by Arduino 13 SoftwareSerial gpsPort(2, 3); // RX, TX 14 #define LEDIndicator1 5 //LED indicator for GPS Lock on pin A3 15 #define FIXOut 4 //Pin Out at IDC. Indicator for GPS Lock on pin 4 16 #define LDO_Enable A3 //GPS Voltage regulator Enable on pin A0 17 boolean GPSOK; 18 const char softwareversion[] = "1.04" ; //Version of this program, sent to serialport at startup 19 NMEAGPS gps; // This parses the GPS characters 20 gps_fix fix; // This holds on to the latest values 21 22 23 24 //-------------------------- SETUP ----------------------- 25 26 void setup() 27 { 28 Serial.begin(9600); 29 while (!Serial) 30 ; 31 32 Serial.println(""); 33 Serial.print(F("Zachtek GPS referenced RF, Software version: ")); 34 Serial.println(softwareversion); 35 36 pinMode(LDO_Enable, OUTPUT); // Set Voltage Regulator Enable pin as output. 37 digitalWrite(LDO_Enable, HIGH); //Turn on 3.1V Power supply for the Ublox GPS module 38 Serial.println (F("Turning on Voltage Regulator for GPS module")); 39 pinMode(LEDIndicator1, OUTPUT); // Set GPS Lock LED pin as output. 40 pinMode(FIXOut, OUTPUT); // Set GPS Lock line as output. 41 digitalWrite(LEDIndicator1, LOW); //Turn off Lock LED 42 digitalWrite(FIXOut, LOW); //Go low on Lock line 43 delay(500);//Wait for GPSmodule to complete it's power on. 44 gpsPort.begin(9600); 45 GPSOK=true; 46 47 //Program GPS to output RF 48 if (setGPS_OutputFreq1MHz()) { 49 Serial.println ("GPS Initialized to output RF at 1MHz"); 50 Serial.println ("Initialization is complete."); 51 Serial.println (""); 52 GPSOK=true; 53 } 54 else 55 { 56 Serial.println ("Error! Could not program GPS!"); 57 GPSOK=false; 58 } 59 } 60 61 //-------------------------- 62 63 64 65 66 //-------------------------- Main loop ----------------------- 67 void loop() 68 { 69 while (gps.available( gpsPort )) { 70 fix = gps.read(); 71 if (fix.valid.location && fix.valid.date && fix.valid.time) 72 { 73 Serial.print( F("Fix - Location: ") ); 74 digitalWrite(LEDIndicator1, HIGH); // turn the LED on 75 digitalWrite(FIXOut, HIGH); // Set Lock Line high 76 Serial.print( fix.latitude(), 6 ); 77 Serial.print( ',' ); 78 Serial.print( fix.longitude(), 6 ); 79 Serial.println(); 80 81 } 82 else 83 { 84 if (GPSOK) { //If the GPS is connected but not locked then short blink 85 digitalWrite(LEDIndicator1, HIGH); // turn the LED on 86 digitalWrite(FIXOut, LOW); // Set Lock Line low 87 delay(100); 88 digitalWrite(LEDIndicator1, LOW); // turn the LED off 89 Serial.println(F("Waiting for GPS location fix")); 90 } 91 } 92 } 93 } 94 95 96 //-------------------------- 97 98 bool setGPS_OutputFreq100kHz() 99 { 100 int gps_set_sucess=0; 101 uint8_t setOutputFreq[] = { 102 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 103 0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 104 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x20, 0x1B }; 105 106 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 107 gps_set_sucess=getUBX_ACK(setOutputFreq); 108 //Serial.println("Set output Freq Done"); 109 return gps_set_sucess; 110 } 111 112 bool setGPS_OutputFreq1MHz() 113 { 114 int gps_set_sucess=0; 115 uint8_t setOutputFreq[] = { 116 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 117 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 118 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x8A, 0x8B }; 119 120 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 121 gps_set_sucess=getUBX_ACK(setOutputFreq); 122 //Serial.println("Set output Freq Done"); 123 return gps_set_sucess; 124 } 125 126 bool setGPS_OutputFreq2MHz() 127 { 128 int gps_set_sucess=0; 129 uint8_t setOutputFreq[] = { 130 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 131 0x00, 0x00, 0x80, 0x84, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 132 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x1B, 0x7F }; 133 134 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 135 gps_set_sucess=getUBX_ACK(setOutputFreq); 136 //Serial.println("Set output Freq Done"); 137 return gps_set_sucess; 138 } 139 140 141 bool setGPS_OutputFreq4MHz() 142 { 143 int gps_set_sucess=0; 144 uint8_t setOutputFreq[] = { 145 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 146 0x00, 0x00, 0x00, 0x09, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 147 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x3F, 0x8C }; 148 149 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 150 gps_set_sucess=getUBX_ACK(setOutputFreq); 151 //Serial.println("Set output Freq Done"); 152 return gps_set_sucess; 153 } 154 155 //8MHz is the highest low-jitter frequency possible 156 bool setGPS_OutputFreq8MHz() 157 { 158 int gps_set_sucess=0; 159 uint8_t setOutputFreq[] = { 160 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 161 0x00, 0x00, 0x00, 0x12, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 162 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0xD4, 0x28 }; 163 164 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 165 gps_set_sucess=getUBX_ACK(setOutputFreq); 166 //Serial.println("Set output Freq Done"); 167 return gps_set_sucess; 168 } 169 170 //10 MHz is very jittery. Numbers that can be done with an integer division from 48MHz will produce 171 //the lowest jitter so 16 ,12 ,8 ,6 ,4 ,2 and 1 MHz is low jitter but 10MHz is not 172 //If 10MHz low jitter is needed then one option is to output 2MHz and then filter out the 5th overtone arriving at 10MHz in that way. 173 bool setGPS_OutputFreq10MHz() 174 { 175 int gps_set_sucess=0; 176 uint8_t setOutputFreq[] = { 177 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 178 0x00, 0x00, 0x80, 0x96, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 179 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0xF6, 0x10 }; 180 181 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 182 gps_set_sucess=getUBX_ACK(setOutputFreq); 183 //Serial.println("Set output Freq Done"); 184 return gps_set_sucess; 185 } 186 187 //16MHz is above the specs for lUblox Neo-6, only included for experiments. 188 //This will not produce as clean Square wave. 189 bool setGPS_OutputFreq16MHz() 190 { 191 int gps_set_sucess=0; 192 uint8_t setOutputFreq[] = { 193 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 194 0x00, 0x00, 0x00, 0x24, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 195 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x60, 0x12 }; 196 197 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 198 gps_set_sucess=getUBX_ACK(setOutputFreq); 199 //Serial.println("Set output Freq Done"); 200 return gps_set_sucess; 201 } 202 203 204 void sendUBX(uint8_t *MSG, uint8_t len) { 205 gpsPort.flush(); 206 gpsPort.write(0xFF); 207 _delay_ms(500); 208 for(int i=0; i<len; i++) { 209 gpsPort.write(MSG[i]); 210 } 211 } 212 213 boolean getUBX_ACK(uint8_t *MSG) { 214 uint8_t b; 215 uint8_t ackByteID = 0; 216 uint8_t ackPacket[10]; 217 unsigned long startTime = millis(); 218 219 // Construct the expected ACK packet 220 ackPacket[0] = 0xB5; // header 221 ackPacket[1] = 0x62; // header 222 ackPacket[2] = 0x05; // class 223 ackPacket[3] = 0x01; // id 224 ackPacket[4] = 0x02; // length 225 ackPacket[5] = 0x00; 226 ackPacket[6] = MSG[2]; // ACK class 227 ackPacket[7] = MSG[3]; // ACK id 228 ackPacket[8] = 0; // CK_A 229 ackPacket[9] = 0; // CK_B 230 231 // Calculate the checksums 232 for (uint8_t ubxi=2; ubxi<8; ubxi++) { 233 ackPacket[8] = ackPacket[8] + ackPacket[ubxi]; 234 ackPacket[9] = ackPacket[9] + ackPacket[8]; 235 } 236 237 while (1) { // Test for success 238 if (ackByteID > 9) { 239 // All packets in order! 240 return true; 241 } 242 243 // Timeout if no valid response in 3 seconds 244 if (millis() - startTime > 3000) { 245 return false; 246 } 247 248 // Make sure data is available to read 249 if (gpsPort.available()) { 250 b = gpsPort.read(); 251 // Check that bytes arrive in sequence as per expected ACK packet 252 if (b == ackPacket[ackByteID]) { 253 ackByteID++; 254 } 255 else { 256 ackByteID = 0; // Reset and look again, invalid order 257 }//else 258 }//If 259 }//While 260 }//getUBX_ACK