If you are using a ublox timing receiver, that which you should be using (models ending in T, though I think the models ending in 'F' are timing as well), then it depends on the model. At some point in the 5's or 6's they changed from sending tmode to tmode2. Best way to send it is with Ublox Ucenter code for windows (free). I would stay away from Ucenter V2 and find V1, Release 22.10 or around there as it is much easier to use, no login accounts, etc.
You bring up the config messages screen, scroll down to timing, find tmode or tmode2 depending on your model, and then set the parameters to like 10,000 observations and something less than .5 meters. Depending on the Ucenter version, you have to be careful as at one point you could send meters but the model expected centimeters or vice versa. Find v22 and put .25 meters, enable the srvin message and you can watch it count down.
Depending on the variance, I use .25m, it will take time to get there. .25m at c (300km/s will give you the minimum possible variance for the accuracy of your GPS and DO. So .25m is 7.5e-10th if I did my math correctly and since it is actually the square root of that variance, and I can't remember if the software takes that into account, you can assume you will be less than 1ns from where the GPS thinks it is. You can see on the chart I posted that the numbers were varying +/- about 25ns or so, maybe even as much as 50ns until the survey completed. At that point, the variance in TIC with sawtooth correction came down to much less than +/5ns. Other factors impact that though, temperature, humidity, power fluctuations, turning the lights on, anything that can upset a low noise oscillator.
Instead of using Ucenter, you can send the command from your code and the only tricky part is the CRC characters that need to be calculated. There is a 500 page manual on the Ublox GPS modules that explains all this.
I don't know who wrote this code. It was either Lars or Jim Harman, I modified it for the tmode2 message. Only thing to consider is if you send it and change your mind and want to send it with a looser variance, you need to send it with a cancel code (0x00) first. Once you send it, you should also config messages in Ucenter to receive the srvin messages so you can watch the progress. When the observations stop counting up, then the survey is completed.
This example is already setup for 1m^2 so you can send it as-is. You don't need to fill in the lat/long/altitude as that will be filled in by the GPS quickly and then resolve to the variance. Once you get it fixed at .5m or less, you can send it a fixed location message at reboot as long as you don't move your antenna.
This makes a very big difference in the performance of a GPSDO. Once I get my STM32 code completed, I am going to see if it will count down to 10cm. I've heard of people setting the variance to 1cm. I think you should also set the max number of sats to between 5 and 7 and raise the angle to minimize fluctuations from low sats. There is quite a bit on the web about that. Thinking is that 5 high sats with strong cn ratios is better than 12 sats banging away at your receiver. My variance also correlated more quickly when I did that. I think I used 5 sats and 25 degrees with cn > 35. That is in like the sat5 message? can't remember. Again, Jim H. really helped me with all this. I'm sure there are much more knowledgeable people on here that can throw-in at this point.
call this routine with a duration of at least 5,000 to get 1m
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
// Send the Ublox CFG-TMODE2 message to initiate a survey of length duration sec
void startSurvey(long duration) { // jth changed to tmode2 message as m8t doesn't support tmode
// note LSB is sent first
uint8_t packet[] = {
0xB5, 0x62, // header
0x06, 0x3D, // class = CFG, id = TMODE2
0x1C, 0x00, // length = 28
0x01, // 01 survey in, 00 cancel, 02 fixed
0x00, // reserved
0x00, 0x00, // flags
0x00, 0x00, 0x00, 0x00, // X coordinate ignore for survey, set for fixed
0x00, 0x00, 0x00, 0x00, // Y coordinate as above
0x00, 0x00, 0x00, 0x00, // Z coordinate as above
0x00, 0x00, 0x00, 0x00, // position variance measured
(uint8_t)(duration & 0xFF), //duration
(uint8_t)((duration >> 8) & 0xFF),
(uint8_t)((duration >> 16) & 0xFF),
(uint8_t)((duration >> 24) & 0xFF),
// 0x40, 0x42, 0x0F, 0x00, // position variance = 1 m^2
0xE8, 0x03, 0x00, 0x00, // position variance = 1 m^2
0x00, 0x00 // 2 bytes for checksum
};
sendPacket_crc(packet, sizeof(packet));
}
//----------------------------------------------------------------------------------------
// send a packet to Ublox with crc
void sendPacket_crc(uint8_t *packet, uint8_t len) {
uint8_t ck_a = 0;
uint8_t ck_b = 0;
for (uint8_t i = 2; i < len-2; i++) { // compute crc
ck_a += packet[i];
ck_b += ck_a;
}
packet[len-2] = ck_a; // put crc in packet
packet[len-1] = ck_b;
for (uint8_t i = 0; i < len; i++) { // send it out
Serial1.write(packet[i]);
}
}