diff --git a/docs/display-led.md b/docs/display-led.md index 3f0f56316..aa843fa69 100644 --- a/docs/display-led.md +++ b/docs/display-led.md @@ -13,6 +13,64 @@ If you're using a device with OLED display, or if you add such one to the I2C bu by pressing the button of the device. +# Notes on powering OLED display + +**Different OLED display pinouts:** + +The TTGO T-beam boards do have solder pads for a pinheader which seems to be just right for a commonly used OLED display like the SSD1306. + +The most relevant pin pads are from left to right: + +- GND +- 3V3 +- GND +- 22 (SCL) +- 21 (SDA) +- 3.3V (label oddly differs from the other 3V3 labelled pin) + +However there are 2 versions of the SSD1306 OLED display available: + +- Most common available: GND/Vdd/SCL/SDA +- Hard to find: Vdd/GND/SCL/SDA + +As can be seen, GND and Vdd are swapped and thus the most commonly available display version cannot be used without some tweaking. + +In order to make the most commonly available version fit, you can strip of the plastics from the power pins and carefully bend both GND and Vdd pins in a Z-shape so they will fit in the adjacent pin hole. + + + +This way the display is still positioned correctly to fit in the many available 3D printable enclosure designs out there. + + +**Hardware mod for power-on issues:** + +Some boards like the TTGO T-beam v1.0 and newer do have a power management chip. + +- T-beam v1.0 and v1.1 use the AXP192 +- T-beam v1.2 uses AXP2101 + +At least the ones using the AXP192 power management chip do have a annoying oversight in the board design. + +When powering on the board, the AXP192 is set to output 1.8V to both pads in the aforementioned pin header labelled "3V3" and "3.3V". +If a display like the SSD1306 is soldered to use this as a power source, both I2C pins will be pulled down to about 1.8V + 0.3V = 2.1V by the protection diodes in the display controller. +This may be too low to work properly for all other I2C connected devices. + +So the ESP32 may not be able to scan the I2C bus for any available I2C device and also not able to setup the AXP192 chip to output a higher voltage on the DCDC1 pin which powers the OLED display. + +This catch-22 situation can be resolved by adding a simple diode from GPIO-0 to the "3.3V" pad. (the 'line' on the diode towards the "3.3V" pad) + + + +In this test setup, a basic 1N4001 is used, which has a voltage drop of about 0.5V. +Another option is to use a germanium diode like the 1N4148, which does have a voltage drop of 0.3V. + +GPIO-0 is pulled up to the 3V3 net of the ESP32. This is required for the ESP32 to boot the flashed sketch and not enter flash mode when powered on. + +So as soon as the ESP32 is powered, the Vdd of the OLED display will be pulled up to 3.3V - 0.5V = 2.8V. +This is enough for the I2C pins of the display to not being pulled down and thus the ESP32 can communicate with the AXP192 power management chip. + +N.B. Make sure the leads of the diode cannot short any of the other pins. + # LED blink pattern **Mono color LED:** diff --git a/docs/img/SSD1306_OLED_t-beam.jpg b/docs/img/SSD1306_OLED_t-beam.jpg new file mode 100644 index 000000000..479db9cdc Binary files /dev/null and b/docs/img/SSD1306_OLED_t-beam.jpg differ diff --git a/docs/img/SSD1306_t-beam_diode_mod.jpg b/docs/img/SSD1306_t-beam_diode_mod.jpg new file mode 100644 index 000000000..8f94c7090 Binary files /dev/null and b/docs/img/SSD1306_t-beam_diode_mod.jpg differ diff --git a/include/globals.h b/include/globals.h index 1e8a06752..a6a94c7de 100644 --- a/include/globals.h +++ b/include/globals.h @@ -88,11 +88,11 @@ typedef struct { } MessageBuffer_t; typedef struct { - int32_t latitude; - int32_t longitude; - uint8_t satellites; - uint16_t hdop; - int16_t altitude; + int32_t latitude{}; + int32_t longitude{}; + uint8_t satellites{}; + uint16_t hdop{}; + int16_t altitude{}; } gpsStatus_t; typedef struct { diff --git a/include/gpsread.h b/include/gpsread.h index cb234eb18..934d8fbc6 100644 --- a/include/gpsread.h +++ b/include/gpsread.h @@ -11,12 +11,13 @@ #endif extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe +extern bool gps_location_isupdated; // Keep track of whether it was updated when showing on the display extern TaskHandle_t GpsTask; int gps_init(void); int gps_config(); bool gps_hasfix(); -void gps_storelocation(gpsStatus_t *gps_store); +bool gps_storelocation(gpsStatus_t *gps_store); void gps_loop(void *pvParameters); time_t get_gpstime(uint16_t *msec); diff --git a/src/display.cpp b/src/display.cpp index e5332afff..aac010518 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -327,6 +327,14 @@ void dp_refresh(bool nextPage) { // show latitude and longitude dp_setFont(MY_FONT_STRETCHED); dp->setCursor(0, MY_DISPLAY_FIRSTLINE); + if (gps.location.isUpdated()) { + // When reading the GPS location, the updated flag is reset. + // However if we also need to send the GPS location data, + // we must know whether there has been an update since the last time + // we sent the location. + gps_location_isupdated = true; + } + dp->printf("%c%09.6f\r\n", gps.location.rawLat().negative ? 'S' : 'N', gps.location.lat()); dp->printf("%c%09.6f", gps.location.rawLng().negative ? 'W' : 'E', diff --git a/src/gpsread.cpp b/src/gpsread.cpp index 91e942b80..39f3fe36d 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -5,6 +5,7 @@ TinyGPSPlus gps; +bool gps_location_isupdated = false; TaskHandle_t GpsTask; HardwareSerial GPS_Serial(1); // use UART #1 @@ -142,15 +143,20 @@ int gps_init(void) { } // gps_init() // store current GPS location data in struct -void gps_storelocation(gpsStatus_t *gps_store) { - if (gps.location.isUpdated() && gps.location.isValid() && - (gps.location.age() < 1500)) { - gps_store->latitude = (int32_t)(gps.location.lat() * 1e6); - gps_store->longitude = (int32_t)(gps.location.lng() * 1e6); - gps_store->satellites = (uint8_t)gps.satellites.value(); - gps_store->hdop = (uint16_t)gps.hdop.value(); - gps_store->altitude = (int16_t)gps.altitude.meters(); +bool gps_storelocation(gpsStatus_t *gps_store) { + if (gps.location.isUpdated() || gps_location_isupdated) { + gps_location_isupdated = false; + if (gps.location.isValid() && + (gps.location.age() < 1500)) { + gps_store->latitude = (int32_t)(gps.location.lat() * 1e6); + gps_store->longitude = (int32_t)(gps.location.lng() * 1e6); + gps_store->satellites = (uint8_t)gps.satellites.value(); + gps_store->hdop = (uint16_t)gps.hdop.value(); + gps_store->altitude = (int16_t)gps.altitude.meters(); + return true; + } } + return false; } bool gps_hasfix() { diff --git a/src/senddata.cpp b/src/senddata.cpp index a9a68253f..d3569654a 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -87,8 +87,9 @@ void sendData() { if (GPSPORT == COUNTERPORT) { // send GPS position only if we have a fix if (gps_hasfix()) { - gps_storelocation(&gps_status); - payload.addGPS(gps_status); + if (gps_storelocation(&gps_status)) { + payload.addGPS(gps_status); + } } else ESP_LOGD(TAG, "No valid GPS position"); } @@ -134,10 +135,11 @@ void sendData() { if (GPSPORT != COUNTERPORT) { // send GPS position only if we have a fix if (gps_hasfix()) { - gps_storelocation(&gps_status); - payload.reset(); - payload.addGPS(gps_status); - SendPayload(GPSPORT); + if (gps_storelocation(&gps_status)) { + payload.reset(); + payload.addGPS(gps_status); + SendPayload(GPSPORT); + } } else ESP_LOGD(TAG, "No valid GPS position"); }