Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GPS] Only send valid GPS coordinates (#1009) #1011

Merged
merged 2 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions docs/display-led.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<img src="img/SSD1306_OLED_t-beam.jpg">

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)

<img src="img/SSD1306_t-beam_diode_mod.jpg">

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:**
Expand Down
Binary file added docs/img/SSD1306_OLED_t-beam.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/SSD1306_t-beam_diode_mod.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 5 additions & 5 deletions include/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion include/gpsread.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 8 additions & 0 deletions src/display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,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',
Expand Down
22 changes: 14 additions & 8 deletions src/gpsread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@


TinyGPSPlus gps;
bool gps_location_isupdated = false;
TaskHandle_t GpsTask;
HardwareSerial GPS_Serial(1); // use UART #1

Expand Down Expand Up @@ -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() {
Expand Down
14 changes: 8 additions & 6 deletions src/senddata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -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");
}
Expand Down
Loading