From d2990bfba914c69c9881cff81157f619462823d6 Mon Sep 17 00:00:00 2001 From: barry-ha Date: Mon, 12 Feb 2024 11:18:15 -0800 Subject: [PATCH 1/5] changed BMP388 from SPI to I2C --- Griduino.ino | 12 ++++++------ constants.h | 2 +- model_baro.h | 17 +++++++++-------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Griduino.ino b/Griduino.ino index b14109a..d6beb99 100644 --- a/Griduino.ino +++ b/Griduino.ino @@ -680,12 +680,12 @@ void setup() { GPS.begin(9600); // 9600 NMEA is the default baud rate for Adafruit MTK GPS's delay(50); // is delay really needed? - Serial.print("Set GPS baud rate to 57600: "); - Serial.println(PMTK_SET_BAUD_57600); - GPS.sendCommand(PMTK_SET_BAUD_57600); - delay(50); - GPS.begin(57600); - delay(50); + //Serial.print("Set GPS baud rate to 57600: "); + //Serial.println(PMTK_SET_BAUD_57600); + //GPS.sendCommand(PMTK_SET_BAUD_57600); + //delay(50); + //GPS.begin(57600); + //delay(50); // init Quectel L86 chip to improve USA satellite acquisition GPS.sendCommand("$PMTK353,1,0,0,0,0*2A"); // search American GPS satellites only (not Russian GLONASS satellites) diff --git a/constants.h b/constants.h index d9395ca..6d0176b 100644 --- a/constants.h +++ b/constants.h @@ -5,7 +5,7 @@ #if defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) #define PROGRAM_VERSION "v1.14 PCB v.7" #else -#define PROGRAM_VERSION "v1.14" +#define PROGRAM_VERSION "v1.14 pcb12" #endif #define PROGRAM_LINE1 "Barry K7BWH" #define PROGRAM_LINE2 "John KM7O" diff --git a/model_baro.h b/model_baro.h index 07bcc29..235f681 100644 --- a/model_baro.h +++ b/model_baro.h @@ -64,15 +64,15 @@ */ #if defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) -#include -#include // Precision barometric and temperature sensor -#include + #include + #include // Precision barometric and temperature sensor + #include #else -#include // Precision barometric and temperature sensor + #include // Precision barometric and temperature sensor #endif -#include "constants.h" // Griduino constants, colors, typedefs -#include "logger.h" // conditional printing to Serial port -#include "date_helper.h" // date/time conversions +#include "constants.h" // Griduino constants, colors, typedefs +#include "logger.h" // conditional printing to Serial port +#include "date_helper.h" // date/time conversions // ========== extern =========================================== extern Logger logger; // Griduino.ino @@ -122,7 +122,8 @@ class BarometerModel { Wire1.begin(); bool initialized = baro.begin(0x76, 0x58); // Griduino v7 pcb, I2C #else - bool initialized = baro.begin_SPI(bmp_cs); // Griduino v4 pcb, SPI + //ol initialized = baro.begin_SPI(bmp_cs); // Griduino v4 pcb, SPI + bool initialized = baro.begin_I2C(); // Griduino v11 pcb, I2C #endif if (initialized) { // IIR: From dda1a79e410d19b1c303207852a404c231e6cdcb Mon Sep 17 00:00:00 2001 From: barry-ha Date: Thu, 15 Feb 2024 14:56:08 -0800 Subject: [PATCH 2/5] added GPS function factoryReset() --- model_gps.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/model_gps.h b/model_gps.h index 8897b5c..3be9a10 100644 --- a/model_gps.h +++ b/model_gps.h @@ -74,6 +74,22 @@ class Model { // on a schedule convenient to their UI timing, typ. "endView()" // because saving entire model is slow, ~1 second } + void factoryReset() { + // Should never be needed, but in rare cases the GPS gets into some state + // where it goes for days/weeks without acquiring satellites. + // This will nuke it from orbit. + // It erases stored time, position, almanacs, ephemeris, clears + // system/user configurations, and resets receiver to factory status. + // Please allow 15 minutes to 2 hours to reacquire satellites. + #define PMTK_FACTORY_RESET "$PMTK104*37" ///< Full cold start, factory reset + + Serial.print("Full cold start: "); + Serial.println(PMTK_FACTORY_RESET); + GPS.sendCommand(PMTK_FACTORY_RESET); + + GPS.fix = false; // reset the Adafruit interface object, too + GPS.satellites = 0; // + } // ========== load/save config setting ========================= const char MODEL_FILE[25] = CONFIG_FOLDER "/gpsmodel.cfg"; // CONFIG_FOLDER From 44973b7ea34cd589907ccdcc48ce3314e1163168 Mon Sep 17 00:00:00 2001 From: barry-ha Date: Thu, 15 Feb 2024 14:57:13 -0800 Subject: [PATCH 3/5] created "GPS Cold Start" control panel screen --- cfg_gps_reset.h | 192 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 cfg_gps_reset.h diff --git a/cfg_gps_reset.h b/cfg_gps_reset.h new file mode 100644 index 0000000..261bee8 --- /dev/null +++ b/cfg_gps_reset.h @@ -0,0 +1,192 @@ +#pragma once // Please format this file with clang before check-in to GitHub +/* + File: cfg_gps_reset.h + + Software: Barry Hansen, K7BWH, barry@k7bwh.com, Seattle, WA + Hardware: John Vanderbeck, KM7O, Seattle, WA + + Purpose: Optionally reset GPS to factory state. + User interface calls it "cold restart" but really + the GPS is completely reset to as-shipped condition. + + +-------------------------------------------+ + | * GPS Cold Restart > |... yRow1 + | | + | If your GPS receives no satellites |... yRow2 + | for hours, this action might help. |... yRow3 + | +---------------+ |... yBtn + | | | | + | | Restart GPS | |... yBtn + | | | | + | +---------------+ | + | : | + | Please allow time to acquire satellites. |... yRow8 Confirmation + | v1.14, Feb 15 2024 |... yRow9 + +-------------:-----------------------------+ + : + xBtn +*/ + +#include // TFT color display library +#include "constants.h" // Griduino constants and colors +#include "logger.h" // conditional printing to Serial port +#include "TextField.h" // Optimize TFT display text for proportional fonts +#include "view.h" // Base class for all views + +// ========== extern =========================================== +extern Logger logger; // Griduino.ino + +#include "model_gps.h" // Model of a GPS for model-view-controller +extern Model *model; + +// ========== class ViewCfgGpsReset ================================ +class ViewCfgGpsReset : public View { +public: + // ---------- public interface ---------- + // This derived class must implement the public interface: + ViewCfgGpsReset(Adafruit_ILI9341 *vtft, int vid) // ctor + : View{vtft, vid} { + background = cBACKGROUND; // every view can have its own background color + } + void updateScreen(); + void startScreen(); + bool onTouch(Point touch); + +protected: + // ---------- local data for this derived class ---------- + // color scheme: see constants.h + + const int radius = 10; // rounded corners on buttons + + // vertical placement of text rows + const int space = 24; + const int half = space / 2; + + const int yRow1 = 36; + const int yRow2 = yRow1 + space + half; + const int yRow3 = yRow2 + space; + const int yBtn = yRow3 + space; // ul corner of big button + const int yRow8 = gScreenHeight - 10 - space; // Confirmation message + const int yRow9 = gScreenHeight - 10; // "v1.14, Feb 15 2024" + + // ----- screen text + // names for the array indexes, must be named in same order as array below + enum txtIndex { + TITLE = 0, + LINE1, + LINE2, + NUMSATS, + CONFIRMATION, + COMPILED, + }; + + const int bWidth = 320 / 2; + const int bHeight = 64; + + const int xBtn = 320 / 4; + const int yBtnText = yBtn + (bHeight / 2) + 6; // vertically center text inside big button + + // ----- static screen text + // clang-format off +#define nRestartValues 6 + TextField txtStatic[nRestartValues] = { + // text x, y color + {"GPS Cold Start", -1, 20, cHIGHLIGHT, ALIGNCENTER}, // [TITLE] + {"If your GPS receives no satellites", -1, yRow2, cFAINT, ALIGNCENTER, eFONTSMALLEST}, // [LINE1] + {"for hours, this action might help.", -1, yRow3, cFAINT, ALIGNCENTER, eFONTSMALLEST}, // [LINE2] + {"n#", (320-32), yBtnText, cLABEL, ALIGNRIGHT}, // [NUMSATS] + {"Done! Please allow time to acquire sats.", -1, yRow8, cBACKGROUND, ALIGNCENTER}, // [CONFIRMATION] + {PROGRAM_VERDATE, -1, yRow9, cFAINT, ALIGNCENTER, eFONTSMALLEST}, // [COMPILED] + }; + +enum buttonID { + eRESTART, +}; +#define nRestartButtons 1 + FunctionButton myButtons[nRestartButtons] = { + // label origin size { touch-target } + // text x,y w,h { x,y w,h }, radius, color, functionID + {"Cold Start GPS", xBtn,yBtn, bWidth,bHeight, {180,yBtn, 140,110 }, radius, cBUTTONLABEL, eRESTART}, + }; + // clang-format on + + // ---------- local functions for this derived class ---------- + void fRestart() { + logger.info("->->-> Clicked RESTART button."); + txtStatic[CONFIRMATION].color = cVALUEFAINT; + txtStatic[CONFIRMATION].dirty = true; + txtStatic[CONFIRMATION].print(); + + model->factoryReset(); // do the thing + } + void drawNumSatellites() { + char sTemp[4]; // strlen("12#") = 3 + snprintf(sTemp, sizeof(sTemp), "%d#", model->gSatellites); + txtStatic[NUMSATS].print(sTemp); // number of satellites + } + +}; // end class ViewCfgGpsReset + +// ============== implement public interface ================ +void ViewCfgGpsReset::updateScreen() { + // called on every pass through main() + // nothing to do in the main loop - this screen has no dynamic items + drawNumSatellites(); +} // end updateScreen + +void ViewCfgGpsReset::startScreen() { + // called once each time this view becomes active + this->clearScreen(this->background); // clear screen + txtStatic[0].setBackground(this->background); // set background for all TextFields in this view + TextField::setTextDirty(txtStatic, nRestartValues); // make sure all fields get re-printed on screen change + + drawAllIcons(); // draw gear (settings) and arrow (next screen) + showDefaultTouchTargets(); // optionally draw box around default button-touch areas + showMyTouchTargets(myButtons, nRestartButtons); // optionally show this view's touch targets + showScreenBorder(); // optionally outline visible area + showScreenCenterline(); // optionally draw visual alignment bar + + // ----- draw text fields + for (int ii = 0; ii < nRestartValues; ii++) { + txtStatic[ii].print(); + } + + // ----- draw buttons + setFontSize(eFONTSMALLEST); + for (int ii = 0; ii < nRestartButtons; ii++) { + FunctionButton item = myButtons[ii]; + tft->fillRoundRect(item.x, item.y, item.w, item.h, item.radius, cBUTTONFILL); + tft->drawRoundRect(item.x, item.y, item.w, item.h, item.radius, cBUTTONOUTLINE); + + // ----- label on top of button + int xx = getOffsetToCenterTextOnButton(item.text, item.x, item.w); + + tft->setCursor(xx, item.y + item.h / 2 + 5); // place text centered inside button + tft->setTextColor(item.color); + tft->print(item.text); + } + + showProgressBar(6, 8); // draw marker for advancing through settings + updateScreen(); // update UI immediately, don't wait for the main loop to eventually get around to it +} // end startScreen() + +bool ViewCfgGpsReset::onTouch(Point touch) { + logger.info("->->-> Touched GPS restart screen."); + bool handled = false; // assume a touch target was not hit + for (int ii = 0; ii < nRestartButtons; ii++) { + FunctionButton item = myButtons[ii]; + if (item.hitTarget.contains(touch)) { + handled = true; // hit! + switch (item.functionIndex) // do the thing + { + case eRESTART: + fRestart(); + break; + default: + logger.error("Internal error, unknown function ", item.functionIndex); + break; + } + } + } + return handled; // true=handled, false=controller uses default action +} // end onTouch() From 647f939782d5fd72caa94b4050d3cba9e802d753 Mon Sep 17 00:00:00 2001 From: barry-ha Date: Thu, 15 Feb 2024 14:57:59 -0800 Subject: [PATCH 4/5] inserted "GPS Cold Start" screen into control panel --- Griduino.ino | 24 ++++++++++++++++++------ cfg_audio_type.h | 2 +- cfg_crossing.h | 2 +- cfg_gps.h | 3 +-- cfg_nmea.h | 7 ++++--- cfg_reboot.h | 2 +- cfg_rotation.h | 2 +- cfg_volume.h | 2 +- 8 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Griduino.ino b/Griduino.ino index d6beb99..9f52263 100644 --- a/Griduino.ino +++ b/Griduino.ino @@ -111,6 +111,7 @@ #include "cfg_audio_type.h" // config audio Morse/speech #include "cfg_crossing.h" // config 4/6 digit crossing #include "cfg_gps.h" // config GPS (alphabetical order) +#include "cfg_gps_reset.h" // config GPS reset to factory #include "cfg_nmea.h" // config NMEA broadcasting #include "cfg_reboot.h" // show firmware update option #include "cfg_rotation.h" // config screen rotation @@ -331,6 +332,7 @@ enum VIEW_INDEX { CFG_AUDIO_TYPE, // audio output Morse/speech CFG_CROSSING, // announce grid crossing 4/6 digit boundaries CFG_GPS, // gps/simulator + CFG_GPS_RESET, // factory reset GPS CFG_NMEA, // broadcast NMEA CFG_REBOOT, // confirm reboot CFG_ROTATION, // screen rotation @@ -369,6 +371,7 @@ ViewBaro baroView(&tft, BARO_VIEW); // instantiate derived c ViewCfgAudioType cfgAudioType(&tft, CFG_AUDIO_TYPE); ViewCfgCrossing cfgCrossing(&tft, CFG_CROSSING); ViewCfgGPS cfgGPS(&tft, CFG_GPS); +ViewCfgGpsReset cfgGpsReset(&tft, CFG_GPS_RESET); ViewCfgNMEA cfgNMEA(&tft, CFG_NMEA); ViewCfgReboot cfgReboot(&tft, CFG_REBOOT); ViewCfgRotation cfgRotation(&tft, CFG_ROTATION); @@ -396,6 +399,7 @@ void selectNewView(int cmd) { &cfgAudioType, // [CFG_AUDIO_TYPE] &cfgCrossing, // [CFG_CROSSING] &cfgGPS, // [CFG_GPS] + &cfgGpsReset, // [CFG_GPS_RESET] &cfgNMEA, // [CFG_NMEA] &cfgReboot, // [CFG_REBOOT] &cfgRotation, // [CFG_ROTATION] @@ -441,7 +445,8 @@ void selectNewView(int cmd) { case CFG_AUDIO_TYPE: nextView = CFG_CROSSING; break; case CFG_CROSSING: nextView = CFG_GPS; break; case CFG_GPS: nextView = CFG_NMEA; break; - case CFG_NMEA: nextView = CFG_UNITS; break; + case CFG_NMEA: nextView = CFG_GPS_RESET; break; + case CFG_GPS_RESET: nextView = CFG_UNITS; break; case CFG_UNITS: nextView = CFG_ROTATION; break; #if defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) case CFG_ROTATION: nextView = CFG_REBOOT; break; @@ -680,12 +685,19 @@ void setup() { GPS.begin(9600); // 9600 NMEA is the default baud rate for Adafruit MTK GPS's delay(50); // is delay really needed? - //Serial.print("Set GPS baud rate to 57600: "); - //Serial.println(PMTK_SET_BAUD_57600); - //GPS.sendCommand(PMTK_SET_BAUD_57600); - //delay(50); - //GPS.begin(57600); + Serial.print("Set GPS baud rate to 57600: "); + Serial.println(PMTK_SET_BAUD_57600); + GPS.sendCommand(PMTK_SET_BAUD_57600); + delay(50); + GPS.begin(57600); + delay(50); + + /****************** DANGER ****************/ + // one-time usage + // Full Cold Restart: reset the receiver to the factory status + //GPS.sendCommand("$PMTK104*37\r\n"); //delay(50); + /****************** DANGER ****************/ // init Quectel L86 chip to improve USA satellite acquisition GPS.sendCommand("$PMTK353,1,0,0,0,0*2A"); // search American GPS satellites only (not Russian GLONASS satellites) diff --git a/cfg_audio_type.h b/cfg_audio_type.h index b2762cb..2bb9cc3 100644 --- a/cfg_audio_type.h +++ b/cfg_audio_type.h @@ -204,7 +204,7 @@ void ViewCfgAudioType::startScreen() { txtSettings5[ii].print(); } - showProgressBar(2, 7); // draw marker for advancing through settings + showProgressBar(2, 8); // draw marker for advancing through settings showScreenBorder(); // optionally outline visible area showScreenCenterline(); // optionally draw alignment bar diff --git a/cfg_crossing.h b/cfg_crossing.h index 5a8a647..40086d9 100644 --- a/cfg_crossing.h +++ b/cfg_crossing.h @@ -197,7 +197,7 @@ void ViewCfgCrossing::startScreen() { txtSettings4[ii].print(); } - showProgressBar(3, 7); // draw marker for advancing through settings + showProgressBar(3, 8); // draw marker for advancing through settings showScreenBorder(); // optionally outline visible area showScreenCenterline(); // optionally draw alignment bar diff --git a/cfg_gps.h b/cfg_gps.h index d197055..0bccca8 100644 --- a/cfg_gps.h +++ b/cfg_gps.h @@ -87,7 +87,6 @@ class ViewCfgGPS : public View { {"%d crumbs", col1, yRow2, cLABEL}, // [TRAILCOUNT] {"Route", col1, yRow3, cVALUE}, // [GPSTYPE] {PROGRAM_VERDATE, -1, yRow9, cLABEL, ALIGNCENTER}, // [COMPILED] - //{"4 of 6", xPanel, 20, cFAINT}, // [PANEL] }; // clang-format on @@ -205,7 +204,7 @@ void ViewCfgGPS::startScreen() { tft->drawCircle(xCenter, yCenter, 7, cVALUE); } - showProgressBar(4, 7); // draw marker for advancing through settings + showProgressBar(4, 8); // draw marker for advancing through settings updateScreen(); // fill in values immediately, don't wait for the main loop to eventually get around to it showScreenCenterline(); // optionally draw alignment bar diff --git a/cfg_nmea.h b/cfg_nmea.h index f54ea83..6c324bc 100644 --- a/cfg_nmea.h +++ b/cfg_nmea.h @@ -63,12 +63,13 @@ class ViewCfgNMEA : public View { // color scheme: see constants.h // vertical placement of text rows + const int space = 30; const int yRow1 = 80; const int yRow2 = yRow1 + 24; const int yRow3 = yRow2 + 24; const int yRow4 = yRow3 + 50; const int yRow5 = yRow4 + 24; - const int yRow9 = gScreenHeight - 10; // "v1.14, Feb 12 2024" + const int yRow9 = gScreenHeight - 10; // "v1.14, Feb 15 2024" const int yButton1 = 62; const int yButton2 = yButton1 + 54; @@ -82,7 +83,7 @@ class ViewCfgNMEA : public View { #define nTextNMEA 6 TextField txtStatic[nTextNMEA] = { // text x, y color - {"NMEA Sentences", -1, 20, cHIGHLIGHT, ALIGNCENTER}, + {"GPS NMEA Sentences", -1, 20, cHIGHLIGHT, ALIGNCENTER}, {"Report GPS ", col1, yRow1, cVALUE}, {"positions", col1, yRow2, cVALUE}, {"NMEA sentences are available", -1, yRow4, cFAINT, ALIGNCENTER}, @@ -182,7 +183,7 @@ void ViewCfgNMEA::startScreen() { tft->drawCircle(xCenter, yCenter, 7, cVALUE); } - showProgressBar(5, 7); // draw marker for advancing through settings + showProgressBar(5, 8); // draw marker for advancing through settings updateScreen(); // update UI immediately, don't wait for laggy mainline loop } // end startScreen() diff --git a/cfg_reboot.h b/cfg_reboot.h index f2f93c3..3af2f35 100644 --- a/cfg_reboot.h +++ b/cfg_reboot.h @@ -207,7 +207,7 @@ void ViewCfgReboot::startScreen() { tft->print(item.text); } - showProgressBar(7, 7); // draw marker for advancing through settings + showProgressBar(7, 8); // draw marker for advancing through settings updateScreen(); // update UI immediately, don't wait for the main loop to eventually get around to it } // end startScreen() diff --git a/cfg_rotation.h b/cfg_rotation.h index 8808bf9..15c2b34 100644 --- a/cfg_rotation.h +++ b/cfg_rotation.h @@ -186,7 +186,7 @@ void ViewCfgRotation::startScreen() { tft->drawCircle(xCenter, yCenter, 7, cVALUE); } - showProgressBar(6, 7); // draw marker for advancing through settings + showProgressBar(8, 8); // draw marker for advancing through settings updateScreen(); // update UI immediately, don't wait for laggy mainline loop } // end startScreen() diff --git a/cfg_volume.h b/cfg_volume.h index a255f10..923fcca 100644 --- a/cfg_volume.h +++ b/cfg_volume.h @@ -256,7 +256,7 @@ void ViewVolume::startScreen() { yy = volButtons[1].y + volButtons[1].h / 2; tft->fillTriangle(xx - ww, yy - nn, xx + ww, yy - nn, xx, yy + ht - nn, cVALUE); // arrow DOWN - showProgressBar(1, 7); // draw marker for advancing through settings + showProgressBar(1, 8); // draw marker for advancing through settings updateScreen(); // update UI immediately, don't wait for laggy mainline loop } // end startScreen() From 5c0b8996b00b07e8cc4d55b708b3983931d3dccc Mon Sep 17 00:00:00 2001 From: barry-ha Date: Thu, 15 Feb 2024 14:58:14 -0800 Subject: [PATCH 5/5] added comments --- .../GPS_Demo_Loopback/GPS_Demo_Loopback.ino | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/examples/GPS_Demo_Loopback/GPS_Demo_Loopback.ino b/examples/GPS_Demo_Loopback/GPS_Demo_Loopback.ino index 6d86f27..376b554 100644 --- a/examples/GPS_Demo_Loopback/GPS_Demo_Loopback.ino +++ b/examples/GPS_Demo_Loopback/GPS_Demo_Loopback.ino @@ -287,13 +287,19 @@ void init_Adafruit_GPS() { delay(50); // ----- turn on additional satellite reporting to support NMEATime2 -// GPGLL Geographic Latitude longitude -// | GPRMC Recommended Minimum Coordinates -// | | GPVTG Velocity Over Ground -// | | | GPGGA GPS Fix Data -// | | | | GPGSA GPS Satellites Active -// | | | | | GPGSV GPS Satellites in View +// GPGLL Geographic Latitude longitude +// | GPRMC Recommended Minimum Coordinates +// | | GPVTG Velocity Over Ground +// | | | GPGGA GPS Fix Data +// | | | | GPGSA GNSS DOPS and Active Satellites +// | | | | | GPGSV GNSS Satellites in View #define PMTK_SENTENCE_FREQUENCIES "$PMTK314,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28" +// | | | | | PMTKDBG MTK debug information +// | | | | MTKDGP GPS differential correction information +// | | | PMTKEPH GPS ephemeris information +// | | PMTKALM GPS almanac information +// | GPGST GNSS Pseudorange Errors Statistics +// GPGRS GNSS Range Residuals Serial.print("Sending command to set sentence output frequencies: "); Serial.println(PMTK_SENTENCE_FREQUENCIES); // Echo command to console GPS.sendCommand(PMTK_SENTENCE_FREQUENCIES); // Send command to GPS unit