Files
MeshCore/variants/heltec_tracker/target.cpp
Wessel Nieboer 59d9770ab9 Add GPS support Heltec Wireless Tracker v1.x
Pin mapping verified against HTIT-Tracker V0.5 schematic:
- GPIO35 (GPS_EN): N-ch MOSFET drives P-ch high-side switch, active HIGH
- GPIO36 (GPS_RST): hardware reset, active LOW
- GPIO33/34: UART TX/RX

Delegates power management to MicroNMEALocationProvider begin()/stop()
which independently controls GPS power via GPS_EN and shares VEXT with
the display through RefCountedDigitalPin.
2026-02-28 19:09:28 +01:00

126 lines
3.4 KiB
C++

#include <Arduino.h>
#include "target.h"
#include <helpers/sensors/MicroNMEALocationProvider.h>
HeltecV3Board board;
#if defined(P_LORA_SCLK)
static SPIClass spi;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
#else
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY);
#endif
WRAPPER_CLASS radio_driver(radio, board);
ESP32RTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
// GPS_EN (GPIO35) drives N-ch MOSFET → P-ch high-side switch; GPS_RESET (GPIO36) active LOW
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, GPS_RESET, GPS_EN, &board.periph_power);
HWTSensorManager sensors = HWTSensorManager(nmea);
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display(&board.periph_power); // peripheral power pin is shared
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif
bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
#if defined(P_LORA_SCLK)
return radio.std_init(&spi);
#else
return radio.std_init();
#endif
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(int8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}
void HWTSensorManager::start_gps() {
if (!gps_active) {
_location->begin(); // Claims periph_power via RefCountedDigitalPin
gps_active = true;
Serial1.println("$CFGSYS,h35155*68"); // Configure GPS for all constellations
}
}
void HWTSensorManager::stop_gps() {
if (gps_active) {
gps_active = false;
_location->stop(); // Releases periph_power via RefCountedDigitalPin
}
}
bool HWTSensorManager::begin() {
// init GPS port
Serial1.begin(115200, SERIAL_8N1, PIN_GPS_RX, PIN_GPS_TX);
return true;
}
bool HWTSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) {
if (requester_permissions & TELEM_PERM_LOCATION) { // does requester have permission?
telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude);
}
return true;
}
void HWTSensorManager::loop() {
static long next_gps_update = 0;
_location->loop();
if (millis() > next_gps_update) {
if (gps_active && _location->isValid()) {
node_lat = ((double)_location->getLatitude())/1000000.;
node_lon = ((double)_location->getLongitude())/1000000.;
node_altitude = ((double)_location->getAltitude()) / 1000.0;
MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon);
}
next_gps_update = millis() + 1000;
}
}
int HWTSensorManager::getNumSettings() const { return 1; } // just one supported: "gps" (power switch)
const char* HWTSensorManager::getSettingName(int i) const {
return i == 0 ? "gps" : NULL;
}
const char* HWTSensorManager::getSettingValue(int i) const {
if (i == 0) {
return gps_active ? "1" : "0";
}
return NULL;
}
bool HWTSensorManager::setSettingValue(const char* name, const char* value) {
if (strcmp(name, "gps") == 0) {
if (strcmp(value, "0") == 0) {
stop_gps();
} else {
start_gps();
}
return true;
}
return false; // not supported
}