Skip to content

Commit 6602cfb

Browse files
committed
Version v0.05f
- Added missing Bluetooth OCXO warmup messages - OCXO warmup now a separate function from calibration - Added countdown for calibration - Added selectable calibration countdowns (15s or 60s)
1 parent 79061de commit 6602cfb

File tree

1 file changed

+106
-31
lines changed

1 file changed

+106
-31
lines changed

software/GPSDO.ino

Lines changed: 106 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**********************************************************************************************************
2-
STM32 GPSDO v0.05e by André Balsa, February 2022
2+
STM32 GPSDO v0.05f by André Balsa, February 2022
33
GPLV3 license
44
Reuses small bits of the excellent GPS checker code Arduino sketch by Stuart Robinson - 05/04/20
55
From version 0.03 includes a command parser, so the GPSDO can receive commands from the USB serial or
@@ -126,7 +126,7 @@
126126
// 2. Refactor the setup and main loop functions to make them as simple as possible.
127127

128128
#define Program_Name "GPSDO"
129-
#define Program_Version "v0.05e"
129+
#define Program_Version "v0.05f"
130130
#define Author_Name "André Balsa"
131131

132132
// Debug options
@@ -391,17 +391,20 @@ volatile bool force_armpicDIV_flag = true; // indicates picDIV must be armed
391391
volatile bool force_calibration_flag = true; // indicates GPSDO should start calibration sequence
392392

393393
volatile bool ocxo_needs_warming = true; // indicates OCXO needs to warm up a few minutes after power on
394+
394395
#ifdef FastBootMode
395396
const uint16_t ocxo_warmup_time = 15; // ocxo warmup time in seconds; 15s for testing
397+
const uint16_t ocxo_calib_time = 15; // 15s fast calibration countdown time (for each calibration step)
396398
#else
397399
const uint16_t ocxo_warmup_time = 300; // ocxo warmup time in seconds; 300s or 600s normal use
400+
const uint16_t ocxo_calib_time = 60; // 60s normal calibration countdown time (for each calibration step)
398401
#endif // FastBootMode
399402

400403
volatile bool tunnel_mode_flag = false; // the GPSDO relays the information directly to and from the GPS module to the USB serial
401404
#ifdef TunnelModeTesting
402405
const uint16_t tunnelSecs = 15; // tunnel mode timeout in seconds; 15s for testing, 300s or 600s normal use
403406
#else
404-
const uint16_t tunnelSecs = 300; // tunnel mode timeout in seconds; 15s for testing, 300s or 600s normal use
407+
const uint16_t tunnelSecs = 300; // tunnel mode timeout in seconds; 15s for testing, 300s or 600s normal use
405408
#endif // TunnelModeTesting
406409

407410
// Miscellaneous functions
@@ -880,10 +883,13 @@ boolean getUBX_ACK(uint8_t *MSG) {
880883
}
881884
#endif // UBX_CONFIG
882885

886+
// ---------------------------------------------------------------------------------------------
887+
// GPSDO tunnel mode (GPS serial is relayed to Bluetooth serial or USB serial)
888+
// ---------------------------------------------------------------------------------------------
883889
void tunnelgps()
884890
// GPSDO tunnel mode operation
885891
{
886-
#ifdef GPSDO_BLUETOOTH // print calibrating started message to either
892+
#ifdef GPSDO_BLUETOOTH // print entering tunnel mode message to either
887893
Serial2.println(); // Bluetooth serial xor USB serial
888894
Serial2.print(F("Entering tunnel mode..."));
889895
Serial2.println();
@@ -893,7 +899,7 @@ void tunnelgps()
893899
Serial.println();
894900
#endif // BLUETOOTH
895901

896-
// tunnel mode operation goes here
902+
// tunnel mode operation starts here
897903
uint32_t endtunnelmS = millis() + (tunnelSecs * 1000);
898904
uint8_t GPSchar;
899905
uint8_t PCchar;
@@ -902,17 +908,29 @@ void tunnelgps()
902908
if (Serial1.available() > 0)
903909
{
904910
GPSchar = Serial1.read();
905-
Serial.write(GPSchar); // echo NMEA stream to USB serial
911+
#ifdef GPSDO_BLUETOOTH
912+
Serial2.write(GPSchar); // echo GPS NMEA serial stream to Bluetooth serial
913+
#else
914+
Serial.write(GPSchar); // echo GPS NMEA serial stream to USB serial
915+
#endif // BLUETOOTH
906916
}
917+
#ifdef GPSDO_BLUETOOTH
918+
if (Serial2.available() > 0)
919+
#else
907920
if (Serial.available() > 0)
921+
#endif // BLUETOOTH
908922
{
923+
#ifdef GPSDO_BLUETOOTH
924+
PCchar = Serial2.read();
925+
#else
909926
PCchar = Serial.read();
910-
Serial1.write(PCchar); // echo PC stream to GPS serial
927+
#endif // BLUETOOTH
928+
Serial1.write(PCchar); // echo USB serial stream to GPS serial
911929
}
912930
}
913931
// tunnel mode operation ends here
914932

915-
#ifdef GPSDO_BLUETOOTH // print calibrating started message to either
933+
#ifdef GPSDO_BLUETOOTH // print exiting tunnel mode message to either
916934
Serial2.println(); // Bluetooth serial xor USB serial
917935
Serial2.print(F("Tunnel mode exited."));
918936
Serial2.println();
@@ -923,20 +941,21 @@ void tunnelgps()
923941
#endif // BLUETOOTH
924942

925943
tunnel_mode_flag = false; // reset flag, exit tunnel mode
926-
}
927-
void docalibration()
928-
// OCXO Vctl calibration routine: find an approximate value for Vctl
944+
} // end of tunnel mode routine
945+
946+
// ---------------------------------------------------------------------------------------------
947+
// OCXO warmup delay routine (only needed during a GPSDO "cold start")
948+
// ---------------------------------------------------------------------------------------------
949+
void doocxowarmup()
929950
{
930951
unsigned long startWarmup = millis(); // we need a rough timer
931-
if (ocxo_needs_warming) {
932-
// spend a few seconds/minutes here waiting for the OCXO to warm
933-
// show countdown timer on OLED display
934-
// and report on either USB serial or Bluetooth serial
935-
// Note: during calibration the GPSDO does not accept any commands
936-
uint16_t countdown = ocxo_warmup_time;
937-
while (countdown) {
938-
yellow_led_state = 2; // blink yellow LED
939-
952+
// spend a few seconds/minutes here waiting for the OCXO to warm
953+
// show countdown timer on OLED display
954+
// and report on either USB serial or Bluetooth serial
955+
// Note: during warmup the GPSDO does not accept any commands
956+
uint16_t countdown = ocxo_warmup_time;
957+
while (countdown) {
958+
940959
#ifdef GPSDO_OLED
941960
disp.clear(); // display warmup message on OLED
942961
disp.setCursor(0, 0);
@@ -982,11 +1001,22 @@ void docalibration()
9821001
// do nothing for 1s
9831002
delay(1000);
9841003
countdown--;
985-
}
986-
ocxo_needs_warming = false; // reset flag, next "hot" calibration skips ocxo warmup
9871004
}
988-
// proceed with calibration
989-
#ifdef GPSDO_BLUETOOTH // print calibrating started message to either
1005+
ocxo_needs_warming = false; // reset flag, next "hot" calibration skips ocxo warmup
1006+
} // end of OCXO warmup routine
1007+
1008+
// ---------------------------------------------------------------------------------------------
1009+
// GPSDO calibration routine
1010+
// ---------------------------------------------------------------------------------------------
1011+
void docalibration()
1012+
// OCXO Vctl calibration: find an approximate value for Vctl
1013+
{
1014+
yellow_led_state = 2; // blink yellow LED (handled by 2Hz ISR)
1015+
1016+
if (ocxo_needs_warming) doocxowarmup();
1017+
1018+
// Note: during calibration the GPSDO does not accept any commands
1019+
#ifdef GPSDO_BLUETOOTH // print calibration started message to either
9901020
Serial2.println(); // Bluetooth serial xor USB serial
9911021
Serial2.print(F("Calibrating..."));
9921022
Serial2.println();
@@ -1039,27 +1069,56 @@ void docalibration()
10391069
// 1.5V for PWM = 65536 x (1.5 / 3.2) = 30720 results in frequency f1 = 10MHz + e1
10401070
// 2.5V for PWM = 65536 x (2.5 / 3.2) = 51200 results in frequency f2 = 10MHz + e2
10411071
// where f2 > f1 (most OCXOs have positive slope).
1072+
10421073
double f1, f2, e1, e2;
1074+
10431075
// make sure we have a fix and data
1044-
while (!cbTen_full) delay(1000);
1076+
while (!cbTen_full) delay(1000); // note there is a small chance that we lose PPS during calibration
1077+
// resulting in completely wrong calibration value
1078+
10451079
// measure frequency for Vctl=1.5V
1046-
Serial.println(F("set PWM 1.5V, wait 15s"));
1080+
Serial.println(F("Measure frequency for Vctl=1.5V"));
1081+
Serial.print(F("Set PWM Vctl to 1.5V, wait ")); Serial.print(ocxo_calib_time); Serial.println(F("s"));
10471082
analogWrite(VctlPWMOutputPin, 30720);
1048-
delay(15000);
1049-
Serial.print(F("f1 (average frequency for 1.5V Vctl): "));
1083+
1084+
uint16_t calib_countdown = ocxo_calib_time; // note there are two possible values depending on FastBootMode setting
1085+
while (calib_countdown > 0)
1086+
{
1087+
calib_countdown--;
1088+
Serial.print(calib_countdown); Serial.print(F("s "));
1089+
delay(1000);
1090+
}
1091+
1092+
Serial.println();
1093+
Serial.print(F("f1 (average frequency for Vctl=1.5V): "));
10501094
f1 = avgften;
10511095
Serial.print(f1,1);
10521096
Serial.println(F(" Hz"));
1097+
Serial.println();
1098+
10531099
// make sure we have a fix and data again
10541100
while (!cbTen_full) delay(1000);
1101+
10551102
// measure frequency for Vctl=2.5V
1056-
Serial.println(F("set PWM 2.5V, wait 15s"));
1103+
Serial.println(F("Measure frequency for Vctl=2.5V"));
1104+
Serial.println(F("Set PWM Vctl to 2.5V, wait ")); Serial.print(ocxo_calib_time); Serial.println(F("s"));
10571105
analogWrite(VctlPWMOutputPin, 51200);
1058-
delay(15000);
1106+
1107+
calib_countdown = ocxo_calib_time; // no need to declare variable again
1108+
while (calib_countdown > 0)
1109+
{
1110+
calib_countdown--;
1111+
Serial.print(calib_countdown); Serial.print(F("s "));
1112+
delay(1000);
1113+
}
1114+
1115+
Serial.println();
10591116
Serial.print(F("f2 (average frequency for 2.5V Vctl): "));
10601117
f2 = avgften;
10611118
Serial.print(f2,1);
10621119
Serial.println(F(" Hz"));
1120+
Serial.println();
1121+
10631122
// slope s is (f2-f1) / (51200-30720) for PWM
10641123
// So F=10MHz +/- 0.1Hz for PWM = 30720 - (e1 / s)
10651124
// set Vctl
@@ -1088,9 +1147,14 @@ void docalibration()
10881147
disp.fillScreen(ST7735_BLACK);
10891148
#endif // LCD_ST7735
10901149

1150+
yellow_led_state = 0; // turn off yellow LED (handled by 2Hz ISR)
10911151
force_calibration_flag = false; // reset flag, calibration done
1092-
} // end of docalibration()
1152+
} // end of GPSDO calibration routine
10931153

1154+
1155+
// ---------------------------------------------------------------------------------------------
1156+
// Adjust Vctl DAC routine
1157+
// ---------------------------------------------------------------------------------------------
10941158
#ifdef GPSDO_MCP4725
10951159
void adjustVctlDAC()
10961160
// This should reach a stable DAC output value / a stable 10000000.00 frequency
@@ -1123,6 +1187,9 @@ void adjustVctlDAC()
11231187
}
11241188
#endif // MCP4725
11251189

1190+
// ---------------------------------------------------------------------------------------------
1191+
// Adjust Vctl PWM routine
1192+
// ---------------------------------------------------------------------------------------------
11261193
#ifdef GPSDO_PWM_DAC
11271194
void adjustVctlPWM()
11281195
// This should reach a stable PWM output value / a stable 10000000.00 frequency
@@ -1748,6 +1815,9 @@ void uptimetostrings() {
17481815
}
17491816
}
17501817

1818+
// ---------------------------------------------------------------------------------------------
1819+
// setup routine, prepares the hardware for normal operation
1820+
// ---------------------------------------------------------------------------------------------
17511821
void setup()
17521822
{
17531823
// Wait 1 second for things to stabilize
@@ -1961,9 +2031,11 @@ void setup()
19612031
avgVcc = avg_adcVcc.reading(adcVcc);
19622032
# endif // VCC
19632033

2034+
#ifdef GPSDO_MCP4725
19642035
avg_dacVctl.begin();
19652036
dacVctl = analogRead(VctlInputPin);
19662037
avgdacVctl = avg_dacVctl.reading(dacVctl);
2038+
# endif // MCP4725
19672039

19682040
avg_pwmVctl.begin();
19692041
pwmVctl = analogRead(VctlPWMInputPin);
@@ -1974,6 +2046,9 @@ void setup()
19742046
// setup done
19752047
}
19762048

2049+
// ---------------------------------------------------------------------------------------------
2050+
// loop routine: this is the main loop
2051+
// ---------------------------------------------------------------------------------------------
19772052
void loop()
19782053
{
19792054
serial_commands_.ReadSerial(); // process any command from either USB serial (usually

0 commit comments

Comments
 (0)