/ RFout1MHzV1_0 / RFout1MHzV1_01.ino
RFout1MHzV1_01.ino
1 /*Software for Zachtek "GPS Referenced RF generator 1MHz Out V1R2" 2 This will program the Neo-6 GPS module at every start-up to output a signal of the desired frequency 3 It can be set to different freqencies and duty cycles for the two condisions "GPS Lock" and "not GPS Lock" e.g GPS have a fix or not. 4 The standard setting would be no output if no fix (duty cycle =0% is used to turn off the output) 5 and 1MHz 50% when a fix has been acuired. 6 7 The Version of this software is stored in the constant "softwareversion" and is displayed on the Serialport att startup 8 Arduino pin A3 is output - Voltage Regulator Enable 9 pin 2 and 3 is Sofware serial port to GPS module 10 pin 4 is output - High when a fix have been acuired. Goes to the IDC connector 11 pin 5 is output - Yellow LED indicator, blinking when waiting for fix. 12 13 For Arduino Pro Mini 8MHz 14 */ 15 16 #include <SoftwareSerial.h> 17 #include <MicroNMEA.h> 18 #define LEDIndicator1 5 //LED to indicator for GPS Lock on pin A3 19 #define FIXOut 4 //Output high at fix 20 #define LDO_Enable A3 //GPS Voltage regulator Enable on pin A0 21 SoftwareSerial GPSSerial(2, 3); // RX, TX 22 const char softwareversion[] = "1.01" ; //Version of this program, sent to serialport at startup 23 24 char NMEAbuffer[500]; 25 int bufferIndex = 0; 26 unsigned long LastCheck, LastConfig; 27 MicroNMEA nmea(NMEAbuffer, sizeof(NMEAbuffer)); 28 Stream& console = Serial; 29 boolean GPSOK; 30 31 32 void setup() { 33 GPSSerial.begin(9600); 34 Serial.begin (9600); 35 delay(500);//Wait for Serialport to be initialized properly 36 Serial.print(F("Zachtek GPS referenced RF, Software version: ")); 37 Serial.println(softwareversion); 38 39 Serial.println(F("Initializing..")); 40 pinMode(LDO_Enable, OUTPUT); // Set Voltage Regulator Enable pin as output. 41 Serial.println (F("Turning on Voltage Regulator for GPS module")); 42 digitalWrite(LDO_Enable, HIGH); //Turn on 3.1V Power supply for the Ublox GPS module 43 44 pinMode(LEDIndicator1, OUTPUT); // Set GPS Lock LED pin as output. 45 pinMode(FIXOut, OUTPUT); // Set GPS Lock line as output. 46 digitalWrite(LEDIndicator1, LOW); //Turn off Lock LED 47 digitalWrite(FIXOut, LOW); //Go low on Lock line 48 delay(250);//Wait for GPSmodule to complete it's initialization. 49 50 //Send command to GPS that its RF output will be 2MHz at GPS unlock and GPS referenced 2MHz at GPS Lock 51 if (setGPS_OutputFreq1MHz()) { 52 GPSOK=true; 53 Serial.println ("GPS module detected OK"); 54 Serial.println ("RF Output programed for 1MHz (Output will be off until the GPS have accuired the correct position)"); 55 Serial.println ("Initialization is complete."); 56 Serial.println (""); 57 58 } 59 else 60 { 61 Serial.println ("Error! Could not connect to GPS!"); 62 GPSOK=false; 63 } 64 LastConfig=millis(); 65 } 66 67 void loop() { 68 if(GPSSerial.available()) 69 { 70 char ch = GPSSerial.read(); 71 nmea.process(ch);//send to NMEA parsing routine 72 if( bufferIndex>499) // 73 { 74 NMEAbuffer[ bufferIndex ] = 0; // terminate the string with a 0 75 bufferIndex = 0; // reset the index ready for another string 76 } 77 else 78 NMEAbuffer[ bufferIndex++ ] = ch; // add the character into the buffer 79 } 80 81 82 83 //Read the GPS Serial port every second and parse the data to be able detect any loss of signal 84 if ((millis()-LastCheck) >1000) { 85 LastCheck=millis(); 86 if (nmea.isValid()) { 87 digitalWrite(LEDIndicator1, HIGH); // turn the LED on 88 digitalWrite(FIXOut, HIGH); // Set Lock Line high 89 } 90 else 91 { 92 if (GPSOK) { //If the GPS is connected but not locked then short blink 93 digitalWrite(LEDIndicator1, HIGH); // turn the LED on 94 digitalWrite(FIXOut, LOW); // Set Lock Line low 95 delay(100); 96 digitalWrite(LEDIndicator1, LOW); // turn the LED off 97 } 98 } 99 100 if (GPSOK) { 101 console.print("Valid fix: "); 102 console.println(nmea.isValid() ? "yes" : "no"); 103 if (nmea.isValid()) 104 { 105 console.print("Nav. system: "); 106 if (nmea.getNavSystem()) 107 console.println(nmea.getNavSystem()); 108 else 109 console.println("none"); 110 111 console.print("Num. satellites: "); 112 console.println(nmea.getNumSatellites()); 113 114 console.print("UTC: "); 115 console.print(int(nmea.getHour())); 116 console.print(':'); 117 console.print(int(nmea.getMinute())); 118 console.print(':'); 119 console.println(int(nmea.getSecond())); 120 121 long latitude_mdeg = nmea.getLatitude(); 122 long longitude_mdeg = nmea.getLongitude(); 123 console.print("Latitude (deg): "); 124 console.println(latitude_mdeg / 1000000., 6); 125 126 console.print("Longitude (deg): "); 127 console.println(longitude_mdeg / 1000000., 6); 128 129 long alt; 130 console.print("Altitude (m): "); 131 if (nmea.getAltitude(alt)) 132 console.println(alt / 1000., 3); 133 else 134 console.println("not available"); 135 nmea.clear(); 136 } 137 } 138 } 139 } 140 141 142 143 144 bool setGPS_OutputFreq100kHz() 145 { 146 int gps_set_sucess=0; 147 uint8_t setOutputFreq[] = { 148 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 149 0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 150 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x20, 0x1B }; 151 152 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 153 gps_set_sucess=getUBX_ACK(setOutputFreq); 154 //Serial.println("Set output Freq Done"); 155 return gps_set_sucess; 156 } 157 158 bool setGPS_OutputFreq1MHz() 159 { 160 int gps_set_sucess=0; 161 uint8_t setOutputFreq[] = { 162 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 163 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 164 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x8A, 0x8B }; 165 166 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 167 gps_set_sucess=getUBX_ACK(setOutputFreq); 168 //Serial.println("Set output Freq Done"); 169 return gps_set_sucess; 170 } 171 172 bool setGPS_OutputFreq2MHz() 173 { 174 int gps_set_sucess=0; 175 uint8_t setOutputFreq[] = { 176 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 177 0x00, 0x00, 0x80, 0x84, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 178 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x1B, 0x7F }; 179 180 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 181 gps_set_sucess=getUBX_ACK(setOutputFreq); 182 //Serial.println("Set output Freq Done"); 183 return gps_set_sucess; 184 } 185 186 187 bool setGPS_OutputFreq4MHz() 188 { 189 int gps_set_sucess=0; 190 uint8_t setOutputFreq[] = { 191 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 192 0x00, 0x00, 0x00, 0x09, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 193 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x3F, 0x8C }; 194 195 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 196 gps_set_sucess=getUBX_ACK(setOutputFreq); 197 //Serial.println("Set output Freq Done"); 198 return gps_set_sucess; 199 } 200 201 //8MHz is the highest low-jitter frequency possible 202 bool setGPS_OutputFreq8MHz() 203 { 204 int gps_set_sucess=0; 205 uint8_t setOutputFreq[] = { 206 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 207 0x00, 0x00, 0x00, 0x12, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 208 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0xD4, 0x28 }; 209 210 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 211 gps_set_sucess=getUBX_ACK(setOutputFreq); 212 //Serial.println("Set output Freq Done"); 213 return gps_set_sucess; 214 } 215 216 //10 MHz is very jittery. Frequencies that are an integer division of 48MHz will produce the lowest jitter. 217 //If 10MHz low jitter is needed an option is to output 2MHz and filter out the 5th overtone from it arriving at 10MHz 218 bool setGPS_OutputFreq10MHz() 219 { 220 int gps_set_sucess=0; 221 uint8_t setOutputFreq[] = { 222 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 223 0x00, 0x00, 0x80, 0x96, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 224 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0xF6, 0x10 }; 225 226 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 227 gps_set_sucess=getUBX_ACK(setOutputFreq); 228 //Serial.println("Set output Freq Done"); 229 return gps_set_sucess; 230 } 231 232 //Ublox Neo-6 is not accurate or stable above 10MHz so only use this in experiments. 233 //This will not produce as clean Square wave. 234 bool setGPS_OutputFreq16MHz() 235 { 236 int gps_set_sucess=0; 237 uint8_t setOutputFreq[] = { 238 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 239 0x00, 0x00, 0x00, 0x24, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 240 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x60, 0x12 }; 241 242 sendUBX(setOutputFreq, sizeof(setOutputFreq)/sizeof(uint8_t)); 243 gps_set_sucess=getUBX_ACK(setOutputFreq); 244 //Serial.println("Set output Freq Done"); 245 return gps_set_sucess; 246 } 247 248 void sendUBX(uint8_t *MSG, uint8_t len) { 249 GPSSerial.flush(); 250 GPSSerial.write(0xFF); 251 _delay_ms(500); 252 for(int i=0; i<len; i++) { 253 GPSSerial.write(MSG[i]); 254 } 255 } 256 257 boolean getUBX_ACK(uint8_t *MSG) { 258 uint8_t b; 259 uint8_t ackByteID = 0; 260 uint8_t ackPacket[10]; 261 unsigned long startTime = millis(); 262 263 // Construct the expected ACK packet 264 ackPacket[0] = 0xB5; // header 265 ackPacket[1] = 0x62; // header 266 ackPacket[2] = 0x05; // class 267 ackPacket[3] = 0x01; // id 268 ackPacket[4] = 0x02; // length 269 ackPacket[5] = 0x00; 270 ackPacket[6] = MSG[2]; // ACK class 271 ackPacket[7] = MSG[3]; // ACK id 272 ackPacket[8] = 0; // CK_A 273 ackPacket[9] = 0; // CK_B 274 275 // Calculate the checksums 276 for (uint8_t ubxi=2; ubxi<8; ubxi++) { 277 ackPacket[8] = ackPacket[8] + ackPacket[ubxi]; 278 ackPacket[9] = ackPacket[9] + ackPacket[8]; 279 } 280 281 while (1) { // Test for success 282 if (ackByteID > 9) { 283 // All packets in order! 284 return true; 285 } 286 287 // Timeout if no valid response in 3 seconds 288 if (millis() - startTime > 3000) { 289 return false; 290 } 291 292 // Make sure data is available to read 293 if (GPSSerial.available()) { 294 b = GPSSerial.read(); 295 // Check that bytes arrive in sequence as per expected ACK packet 296 if (b == ackPacket[ackByteID]) { 297 ackByteID++; 298 } 299 else { 300 ackByteID = 0; // Reset and look again, invalid order 301 }//else 302 }//If 303 }//While 304 }//getUBX_ACK 305 306 307