diff --git a/.gitignore b/.gitignore index 51449c2d..7ca9335a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ out/ .direnv/ .DS_Store .vscode/settings.json +.vscode/extensions.json diff --git a/src/helpers/TBeamS3SupremeBoard.h b/src/helpers/TBeamS3SupremeBoard.h index 74d9ca2e..ccb8e24c 100644 --- a/src/helpers/TBeamS3SupremeBoard.h +++ b/src/helpers/TBeamS3SupremeBoard.h @@ -22,7 +22,7 @@ #define PIN_BOARD_SCL1 41 //SCL for PMU and PFC8563 (RTC) #define PIN_PMU_IRQ 40 //IRQ pin for PMU -#define PIN_USER_BTN 0 +//#define PIN_USER_BTN 0 #define P_BOARD_SPI_MOSI 35 //SPI for SD Card and QMI8653 (IMU) #define P_BOARD_SPI_MISO 37 //SPI for SD Card and QMI8653 (IMU) @@ -61,10 +61,10 @@ public: void begin() { - power_init(); - ESP32Board::begin(); + power_init(); + esp_reset_reason_t reason = esp_reset_reason(); if (reason == ESP_RST_DEEPSLEEP) { long wakeup_source = esp_sleep_get_ext1_wakeup_status(); diff --git a/src/helpers/nrf52/RAK4631Board.cpp b/src/helpers/nrf52/RAK4631Board.cpp index eb1a42c5..c75ecf29 100644 --- a/src/helpers/nrf52/RAK4631Board.cpp +++ b/src/helpers/nrf52/RAK4631Board.cpp @@ -80,6 +80,11 @@ bool RAK4631Board::startOTAUpdate(const char* id, char reply[]) { Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds - strcpy(reply, "OK - started"); + uint8_t mac_addr[6]; + memset(mac_addr, 0, sizeof(mac_addr)); + Bluefruit.getAddr(mac_addr); + sprintf(reply, "OK - mac: %02X:%02X:%02X:%02X:%02X:%02X", + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + return true; } diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index 0814ad4d..28c6d562 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -17,11 +17,20 @@ build_flags = -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 + -D ENV_INCLUDE_AHTX0=1 + -D ENV_INCLUDE_BME280=1 + -D ENV_INCLUDE_INA3221=1 + -D ENV_INCLUDE_INA219=1 build_src_filter = ${esp32_base.build_src_filter} +<../variants/heltec_v3> + + lib_deps = ${esp32_base.lib_deps} adafruit/Adafruit SSD1306 @ ^2.5.13 + adafruit/Adafruit INA3221 Library @ ^1.0.1 + adafruit/Adafruit INA219 @ ^1.2.3 + adafruit/Adafruit AHTX0 @ ^2.0.5 + adafruit/Adafruit BME280 Library @ ^2.3.0 [env:Heltec_v3_repeater] extends = Heltec_lora32_v3 diff --git a/variants/heltec_v3/target.cpp b/variants/heltec_v3/target.cpp index ab9b709f..be99a1e3 100644 --- a/variants/heltec_v3/target.cpp +++ b/variants/heltec_v3/target.cpp @@ -14,7 +14,7 @@ WRAPPER_CLASS radio_driver(radio, board); ESP32RTCClock fallback_clock; AutoDiscoverRTCClock rtc_clock(fallback_clock); -SensorManager sensors; +EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; diff --git a/variants/heltec_v3/target.h b/variants/heltec_v3/target.h index 76ad58a7..701f9cd5 100644 --- a/variants/heltec_v3/target.h +++ b/variants/heltec_v3/target.h @@ -7,6 +7,7 @@ #include #include #include +#include #ifdef DISPLAY_CLASS #include #endif @@ -14,7 +15,7 @@ extern HeltecV3Board board; extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; -extern SensorManager sensors; +extern EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; diff --git a/variants/lilygo_tbeam_supreme_SX1262/platformio.ini b/variants/lilygo_tbeam_supreme_SX1262/platformio.ini index e618613c..4e6721f9 100644 --- a/variants/lilygo_tbeam_supreme_SX1262/platformio.ini +++ b/variants/lilygo_tbeam_supreme_SX1262/platformio.ini @@ -8,19 +8,22 @@ build_flags = -D P_LORA_TX_LED=6 -D PIN_BOARD_SDA=17 -D PIN_BOARD_SCL=18 + -D PIN_USER_BTN=0 -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper - ;-D DISPLAY_CLASS=SSD1306Display ;Needs to be modified for SH1106 + -D DISPLAY_CLASS=SH1106Display -D SX126X_RX_BOOSTED_GAIN=1 -D SX126X_CURRENT_LIMIT=140 build_src_filter = ${esp32_base.build_src_filter} +<../variants/lilygo_tbeam_supreme_SX1262> + + board_build.partitions = min_spiffs.csv ; get around 4mb flash limit lib_deps = ${esp32_base.lib_deps} lewisxhe/XPowersLib @ ^0.2.7 - ;adafruit/Adafruit SSD1306 @ ^2.5.13 + adafruit/Adafruit SH110X @ ^2.1.13 stevemarple/MicroNMEA @ ^2.0.6 + adafruit/Adafruit BME280 Library @ ^2.3.0 ; === LILYGO T-Beam S3 Supreme with SX1262 environments === [env:T_Beam_S3_Supreme_SX1262_repeater] @@ -64,8 +67,8 @@ build_flags = -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 +; -D BLE_DEBUG_LOGGING=1 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 ; -D ENABLE_PRIVATE_KEY_EXPORT=1 ; -D MESH_PACKET_LOGGING=8 diff --git a/variants/lilygo_tbeam_supreme_SX1262/target.cpp b/variants/lilygo_tbeam_supreme_SX1262/target.cpp index f5b7080b..4b38b11d 100644 --- a/variants/lilygo_tbeam_supreme_SX1262/target.cpp +++ b/variants/lilygo_tbeam_supreme_SX1262/target.cpp @@ -4,6 +4,10 @@ TBeamS3SupremeBoard board; +#ifdef DISPLAY_CLASS + DISPLAY_CLASS display; +#endif + bool pmuIntFlag; #ifndef LORA_CR @@ -46,7 +50,7 @@ void scanDevices(TwoWire *w) switch (addr) { case 0x77: case 0x76: - Serial.println("\tFound BMX280 Sensor"); + Serial.println("\tFound BME280 Sensor"); deviceOnline |= BME280_ONLINE; break; case 0x34: @@ -107,6 +111,26 @@ void TBeamS3SupremeBoard::printPMU() Serial.println(); } +void TbeamSupSensorManager::printBMEValues() { + Serial.print("Temperature = "); + Serial.print(bme.readTemperature()); + Serial.println(" *C"); + + Serial.print("Pressure = "); + + Serial.print(bme.readPressure() / 100.0F); + Serial.println(" hPa"); + + Serial.print("Approx. Altitude = "); + Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + Serial.println(" m"); + + Serial.print("Humidity = "); + Serial.print(bme.readHumidity()); + Serial.println(" %"); + + Serial.println(); +} #endif bool TBeamS3SupremeBoard::power_init() @@ -119,9 +143,9 @@ bool TBeamS3SupremeBoard::power_init() PMU.setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG); // Set up PMU interrupts - // MESH_DEBUG_PRINTLN("Setting up PMU interrupts"); - // pinMode(PIN_PMU_IRQ, INPUT_PULLUP); - // attachInterrupt(PIN_PMU_IRQ, setPMUIntFlag, FALLING); + MESH_DEBUG_PRINTLN("Setting up PMU interrupts"); + pinMode(PIN_PMU_IRQ, INPUT_PULLUP); + attachInterrupt(PIN_PMU_IRQ, setPMUIntFlag, FALLING); // GPS MESH_DEBUG_PRINTLN("Setting and enabling a-ldo4 for GPS"); @@ -164,22 +188,22 @@ bool TBeamS3SupremeBoard::power_init() PMU.enableBLDO1(); // Out to header pins - // MESH_DEBUG_PRINTLN("Setting and enabling b-ldo2 for output to header"); - // PMU.setBLDO2Voltage(3300); - // PMU.enableBLDO2(); + MESH_DEBUG_PRINTLN("Setting and enabling b-ldo2 for output to header"); + PMU.setBLDO2Voltage(3300); + PMU.enableBLDO2(); - // MESH_DEBUG_PRINTLN("Setting and enabling dcdc4 for output to header"); - // PMU.setDC4Voltage(XPOWERS_AXP2101_DCDC4_VOL2_MAX); // 1.8V - // PMU.enableDC4(); + MESH_DEBUG_PRINTLN("Setting and enabling dcdc4 for output to header"); + PMU.setDC4Voltage(XPOWERS_AXP2101_DCDC4_VOL2_MAX); // 1.8V + PMU.enableDC4(); - // MESH_DEBUG_PRINTLN("Setting and enabling dcdc5 for output to header"); - // PMU.setDC5Voltage(3300); - // PMU.enableDC5(); + MESH_DEBUG_PRINTLN("Setting and enabling dcdc5 for output to header"); + PMU.setDC5Voltage(3300); + PMU.enableDC5(); // Unused power rails - MESH_DEBUG_PRINTLN("Disabling unused supplies dcdc2, dldo1 and dldo2"); + MESH_DEBUG_PRINTLN("Disabling unused supplies dcdc2, dcdc5, dldo1 and dldo2"); PMU.disableDC2(); - PMU.disableDC5(); + //PMU.disableDC5(); PMU.disableDLDO1(); PMU.disableDLDO2(); @@ -199,18 +223,18 @@ bool TBeamS3SupremeBoard::power_init() PMU.enableVbusVoltageMeasure(); // Reset and re-enable PMU interrupts - // MESH_DEBUG_PRINTLN("Re-enable interrupts"); - // PMU.disableIRQ(XPOWERS_AXP2101_ALL_IRQ); - // PMU.clearIrqStatus(); - // PMU.enableIRQ( - // XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | // Battery interrupts - // XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | // VBUS interrupts - // XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | // Power Key interrupts - // XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ // Charging interrupts - // ); + MESH_DEBUG_PRINTLN("Re-enable interrupts"); + PMU.disableIRQ(XPOWERS_AXP2101_ALL_IRQ); + PMU.clearIrqStatus(); + PMU.enableIRQ( + XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | // Battery interrupts + XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | // VBUS interrupts + XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | // Power Key interrupts + XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ // Charging interrupts + ); #ifdef MESH_DEBUG - // scanDevices(&Wire); - // scanDevices(&Wire1); + scanDevices(&Wire); + scanDevices(&Wire1); printPMU(); #endif @@ -235,60 +259,14 @@ static bool readStringUntil(Stream& s, char dest[], size_t max_len, char term, u return millis() < timeout; // false, if timed out } -static bool l76kProbe() -{ - bool result = false; - uint32_t startTimeout ; - Serial1.write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n"); - delay(5); - // Get version information - startTimeout = millis() + 3000; - MESH_DEBUG_PRINTLN("Trying to init L76K GPS"); - // Serial1.flush(); - while (Serial1.available()) { - int c = Serial1.read(); - // Serial.write(c); - // Serial.print("."); - // Serial.flush(); - // Serial1.flush(); - if (millis() > startTimeout) { - MESH_DEBUG_PRINTLN("L76K NMEA timeout!"); - return false; - } - }; - - Serial1.flush(); - delay(200); - - Serial1.write("$PCAS06,0*1B\r\n"); - - char ver[100]; - if (!readStringUntil(Serial1, ver, sizeof(ver), '\n', 500)) { - MESH_DEBUG_PRINTLN("Get L76K timeout!"); - return false; - } - - if (memcmp(ver, "$GPTXT,01,01,02", 15) == 0) { - MESH_DEBUG_PRINTLN("L76K GNSS init succeeded, using L76K GNSS Module\n"); - result = true; - } - delay(500); - - // Initialize the L76K Chip, use GPS + GLONASS - Serial1.write("$PCAS04,5*1C\r\n"); - delay(250); - // only ask for RMC and GGA - Serial1.write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n"); - delay(250); - // Switch to Vehicle Mode, since SoftRF enables Aviation < 2g - Serial1.write("$PCAS11,3*1E\r\n"); - return result; -} - bool radio_init() { fallback_clock.begin(); rtc_clock.begin(Wire1); + + // #ifdef MESH_DEBUG + // printBMEValues(); + // #endif #ifdef SX126X_DIO3_TCXO_VOLTAGE float tcxo = SX126X_DIO3_TCXO_VOLTAGE; @@ -340,55 +318,95 @@ void TbeamSupSensorManager::sleep_gps() { } bool TbeamSupSensorManager::begin() { + //init BME280 + if (! bme.begin(0x77, &Wire)) { + MESH_DEBUG_PRINTLN("Could not find a valid BME280 sensor"); + bme_active = false; + } + else + MESH_DEBUG_PRINTLN("BME280 found and init!"); + bme_active = true; + // init GPS port - Serial1.begin(GPS_BAUD_RATE, SERIAL_8N1, P_GPS_RX, P_GPS_TX); - bool result = false; - for ( int i = 0; i < 3; ++i) { - result = l76kProbe(); - if (result) { - gps_active = true; - return result; - } - } - return result; + MESH_DEBUG_PRINTLN("Sleeping GPS for initial state"); + sleep_gps(); + return true; } bool TbeamSupSensorManager::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); } + if (requester_permissions & TELEM_PERM_ENVIRONMENT && bme_active) { // does requester have permission? + telemetry.addTemperature(TELEM_CHANNEL_SELF, node_temp); + telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, node_hum); + telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, node_pres); + //telemetry.addAltitude(TELEM_CHANNEL_SELF, node_alt); + } return true; } void TbeamSupSensorManager::loop() { - static long next_gps_update = 0; + static long next_update = 0; _nmea->loop(); - if (millis() > next_gps_update) { - if (_nmea->isValid()) { + if (millis() > next_update) { + if (_nmea->isValid() && gps_active) { node_lat = ((double)_nmea->getLatitude())/1000000.; node_lon = ((double)_nmea->getLongitude())/1000000.; node_altitude = ((double)_nmea->getAltitude()) / 1000.0; - //Serial.printf("lat %f lon %f\r\n", _lat, _lon); + MESH_DEBUG_PRINT("lat %f lon %f alt %f\r\n", node_lat, node_lon, node_altitude); } - next_gps_update = millis() + 1000; + + //read BME280 values + if(bme_active){ + //node_alt = bme.readAltitude(SEALEVELPRESSURE_HPA); + node_temp = bme.readTemperature(); + node_hum = bme.readHumidity(); + node_pres = (bme.readPressure() / 100.0F); + + #ifdef MESH_DEBUG + // Serial.print("Temperature = "); + // Serial.print(node_temp); + // Serial.println(" *C"); + + // Serial.print("Humidity = "); + // Serial.print(node_hum); + // Serial.println(" %"); + + // Serial.print("Pressure = "); + // Serial.print(node_pres); + // Serial.println(" hPa"); + + // Serial.print("Approx. Altitude = "); + // Serial.print(node_alt); + // Serial.println(" m"); + #endif + } + + next_update = millis() + 1000; } } -int TbeamSupSensorManager::getNumSettings() const { return 1; } // just one supported: "gps" (power switch) +int TbeamSupSensorManager::getNumSettings() const { + return 1; +} const char* TbeamSupSensorManager::getSettingName(int i) const { - return i == 0 ? "gps" : NULL; + switch(i){ + case 0: return "gps"; + default: NULL; + } } const char* TbeamSupSensorManager::getSettingValue(int i) const { - if (i == 0) { - return gps_active ? "1" : "0"; + switch(i){ + case 0: return gps_active == true ? "1" : "0"; + default: NULL; } - return NULL; } bool TbeamSupSensorManager::setSettingValue(const char* name, const char* value) { diff --git a/variants/lilygo_tbeam_supreme_SX1262/target.h b/variants/lilygo_tbeam_supreme_SX1262/target.h index 107e2950..a3023750 100644 --- a/variants/lilygo_tbeam_supreme_SX1262/target.h +++ b/variants/lilygo_tbeam_supreme_SX1262/target.h @@ -8,15 +8,21 @@ #include #include #include +#include class TbeamSupSensorManager: public SensorManager { bool gps_active = false; + bool bme_active = false; LocationProvider * _nmea; - + Adafruit_BME280 bme; + double node_temp, node_hum, node_pres; + + #define SEALEVELPRESSURE_HPA (1013.25) + void start_gps(); void sleep_gps(); public: - TbeamSupSensorManager(LocationProvider &nmea): _nmea(&nmea) { } + TbeamSupSensorManager(LocationProvider &nmea): _nmea(&nmea) {node_temp = 0; node_hum = 0; node_pres = 0;} bool begin() override; bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; void loop() override; @@ -24,6 +30,11 @@ class TbeamSupSensorManager: public SensorManager { const char* getSettingName(int i) const override; const char* getSettingValue(int i) const override; bool setSettingValue(const char* name, const char* value) override; + + #ifdef MESH_DEBUG + void printBMEValues(); + #endif + }; extern TBeamS3SupremeBoard board; @@ -31,6 +42,11 @@ extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern TbeamSupSensorManager sensors; +#ifdef DISPLAY_CLASS + #include + extern DISPLAY_CLASS display; +#endif + enum { POWERMANAGE_ONLINE = _BV(0), DISPLAY_ONLINE = _BV(1), @@ -48,7 +64,6 @@ enum { OSC32768_ONLINE = _BV(13), }; -bool power_init(); bool radio_init(); uint32_t radio_get_rng_seed(); void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);