Compare commits

...

25 Commits

Author SHA1 Message Date
Alexander Begoon
7613baee53
Merge 73ddc8d3c8 into 655c6b51fe 2025-09-02 10:10:40 -05:00
Alexander Begoon
73ddc8d3c8
Merge remote-tracking branch 'origin/xiao_esp32c6_with_ble' into xiao_esp32c6_with_ble
Conflicts:
	arch/esp32/esp32c6.ini
	variants/tlora_c6/platformio.ini
2025-08-05 22:43:35 +02:00
Alexander Begoon
f667fd8704
Merge remote-tracking branch 'upstream/master' into xiao_esp32c6_with_ble
Conflicts:
	.gitignore
	bin/platformio-custom.py
	src/modules/AdminModule.cpp
	src/modules/Telemetry/EnvironmentTelemetry.cpp
	src/modules/Telemetry/PowerTelemetry.cpp
	src/nimble/NimbleBluetooth.cpp
	variants/esp32c6/tlora_c6/platformio.ini
2025-08-05 22:41:44 +02:00
Thomas Göttgens
310e605af0
Merge branch 'master' into xiao_esp32c6_with_ble 2025-06-05 14:31:56 +02:00
Alexander Begoon
35c77f265d
Merge remote-tracking branch 'upstream/master' into xiao_esp32c6_with_ble
Conflicts:
	arch/esp32/esp32c6.ini
	variants/tlora_c6/platformio.ini
2025-05-10 13:12:52 +02:00
Alexander Begoon
a34cfaee33
Add MAX17261 sensor 2025-05-10 13:11:00 +02:00
Alexander Begoon
b326fb76f3
Reroute to Meshimi pinout
Add MAX17261 sensor
2025-05-10 13:10:08 +02:00
Alexander Begoon
685c8c1df7
Add support for CONFIG_NIMBLE_CPP_IDF in NimbleBluetooth callbacks
Add support 1.x.x version of NimBLE-Arduino
2025-04-29 18:43:41 +02:00
Alexander Begoon
19fa899627
Merge remote-tracking branch 'upstream/master' into xiao_esp32c6_with_ble 2025-04-29 17:50:20 +02:00
Alexander Begoon
41db0aff3d
Merge remote-tracking branch 'upstream/master' into xiao_esp32c6_with_ble 2025-04-20 14:56:09 +02:00
Alexander Begoon
0e95ed2979
Fix a dependency source 2025-04-20 14:55:46 +02:00
Alexander Begoon
ba0f5688ae
Fix lint 2025-04-19 12:01:22 +02:00
Alexander Begoon
9874c5c696
Fix lint 2025-04-19 12:00:20 +02:00
Alexander Begoon
7cad7d3864
Improve pio config.
Fix Nimble pin code issue.
Address some PR comments.
2025-04-19 11:56:55 +02:00
Alexander Begoon
5c2ee2bb9d
Merge remote-tracking branch 'upstream/master' into xiao_esp32c6_with_ble 2025-04-19 09:46:12 +02:00
Thomas Göttgens
6e012f4774
Merge branch 'master' into xiao_esp32c6_with_ble 2025-04-18 00:12:05 +02:00
Thomas Göttgens
2fb7cc7900
Merge branch 'master' into xiao_esp32c6_with_ble 2025-04-18 00:11:11 +02:00
Thomas Göttgens
3dbc5715d1
Merge branch 'master' into xiao_esp32c6_with_ble 2025-04-07 10:05:08 +02:00
Ben Meadors
d0b6a76119
Merge branch 'master' into xiao_esp32c6_with_ble 2025-03-31 05:59:49 -05:00
Thomas Göttgens
4678059779
Merge branch 'master' into xiao_esp32c6_with_ble 2025-03-31 11:21:33 +02:00
Alexander Begoon
1e2b92d1a0
Merge remote-tracking branch 'upstream/master' into xiao_esp32c6_with_ble 2025-03-29 11:10:48 +01:00
Alexander Begoon
5336a1d747
Merge remote-tracking branch 'upstream/master' into xiao_esp32c6_with_ble 2025-03-10 13:25:30 +01:00
Alexander Begoon
53b5a59115
bump deps version 2025-03-06 13:29:48 +01:00
Alexander Begoon
cb96a9eba4
Merge remote-tracking branch 'upstream/master' into xiao_esp32c6_with_ble
Conflicts:
	bin/platformio-custom.py
	src/main.cpp
2025-03-06 13:10:47 +01:00
Alexander Begoon
09222fde96
Fix conflicts 2025-03-05 15:32:28 +01:00
40 changed files with 493 additions and 33 deletions

9
.gitignore vendored
View File

@ -41,3 +41,12 @@ src/mesh/raspihttp/private_key.pem
# Ignore logo (set at build time with platformio-custom.py)
data/boot/logo.*
managed_components
dependencies.lock
log_*
sdkconfig
sdkconfig.*
!sdkconfig.defaults

6
CMakeLists.txt Normal file
View File

@ -0,0 +1,6 @@
# This file supports the ESP-IDF framework only.
# Specifically, it targets the ESP32-C6 due to limited support in PlatformIO (see: https://github.com/platformio/platform-espressif32/issues/1225).
# Currently, we need to compile NimBLE CPP manually to enable BLE, and possibly WiFi, for ESP32-C6 targets.
cmake_minimum_required(VERSION 3.16.0)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(firmware)

View File

@ -17,9 +17,7 @@ build_flags =
-DMESHTASTIC_EXCLUDE_WEBSERVER
;-DDEBUG_HEAP
; TEMP
-DHAS_BLUETOOTH=0
-DMESHTASTIC_EXCLUDE_PAXCOUNTER
-DMESHTASTIC_EXCLUDE_BLUETOOTH
lib_deps =
${arduino_base.lib_deps}
@ -33,6 +31,8 @@ lib_deps =
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
# renovate: datasource=github-tags depName=esp-nimble-cpp packageName=h2zero/esp-nimble-cpp
https://github.com/h2zero/esp-nimble-cpp/archive/2.2.1.zip
build_src_filter =
${esp32_base.build_src_filter} -<mesh/http>

37
sdkconfig.defaults Normal file
View File

@ -0,0 +1,37 @@
# # This file configures the ESP-IDF framework for the ESP32 platform.
# It enables BLE functionality using NimBLE and optimizes for minimal power consumption and size.
# Refer to the ESP-IDF Kconfig documentation for more details: https://docs.espressif.com/projects/esp-idf/en/v5.1.6/esp32c6/api-reference/kconfig.html
# CONFIG_AUTOSTART_ARDUINO is not set
# CONFIG_WS2812_LED_ENABLE is not set
CONFIG_FREERTOS_HZ=1000
CONFIG_MBEDTLS_PSK_MODES=y
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
# Override some defaults so BT stack is enabled
# in this example
#
# BT config
#
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
#
# Arduino Configuration
#
#
# Disable all Arduino included BLE libraries
#
CONFIG_ARDUINO_SELECTIVE_COMPILATION=y
# CONFIG_ARDUINO_SELECTIVE_WiFiProv is not set
# CONFIG_ARDUINO_SELECTIVE_BLE is not set
# CONFIG_ARDUINO_SELECTIVE_BluetoothSerial is not set
# CONFIG_ARDUINO_SELECTIVE_SimpleBLE is not set
# end of Arduino Configuration

14
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,14 @@
# This file supports the ESP-IDF framework only.
# Specifically, it targets the ESP32-C6 due to limited support in PlatformIO (see: https://github.com/platformio/platform-espressif32/issues/1225).
# Currently, we need to compile NimBLE CPP manually to enable BLE, and possibly WiFi, for ESP32-C6 targets.
FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
FILE(GLOB_RECURSE platform_sources ${CMAKE_SOURCE_DIR}/src/platform/**/*.*)
list(REMOVE_ITEM app_sources ${platform_sources})
FILE(GLOB_RECURSE esp32_sources ${CMAKE_SOURCE_DIR}/src/platform/esp32/*.*)
list(APPEND app_sources ${esp32_sources})
FILE(GLOB_RECURSE esp32_sources ${CMAKE_SOURCE_DIR}/src/platform/esp32/**/*.*)
list(APPEND app_sources ${esp32_sources})
list(REMOVE_ITEM app_sources ${CMAKE_SOURCE_DIR}/src/mesh/eth/ethClient.cpp)
# Register the component with ESP-IDF
idf_component_register(SRCS ${app_sources} INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/src)

View File

@ -1,8 +1,8 @@
#include "RedirectablePrint.h"
#include "NodeDB.h"
#include "RTC.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include "gps/RTC.h"
#include "main.h"
#include "mesh/generated/meshtastic/mesh.pb.h"
#include <assert.h>

View File

@ -28,6 +28,7 @@ class ScanI2C
INA219,
INA3221,
MAX17048,
MAX17261,
MCP9808,
SHT31,
SHT4X,

View File

@ -434,6 +434,19 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
#else
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031", (uint8_t)addr.address)
#endif
case MAX1704X_ADDR:
// Try to read the MAX17261 DevName register 0x21 first
// See:
// https://www.analog.com/media/en/technical-documentation/user-guides/max1726x-modelgauge-m5-ez-user-guide.pdf
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x21), 2);
if (registerValue == 0x3340) {
logFoundDevice("MAX17261", (uint8_t)addr.address);
type = MAX17261;
} else {
logFoundDevice("MAX17048", (uint8_t)addr.address);
type = MAX17048;
}
break;
case BMA423_ADDR: // this can also be LIS3DH_ADDR_ALT
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
@ -464,7 +477,6 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address);

View File

@ -9,10 +9,10 @@
#include "GpioLogic.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "RTC.h"
#include "Throttle.h"
#include "buzz.h"
#include "concurrency/Periodic.h"
#include "gps/RTC.h"
#include "meshUtils.h"
#include "main.h" // pmu_found

View File

@ -1,7 +1,7 @@
#if !MESHTASTIC_EXCLUDE_GPS
#include "NMEAWPL.h"
#include "GeoCoord.h"
#include "RTC.h"
#include "gps/RTC.h"
#include <time.h>
/* -------------------------------------------

View File

@ -1,4 +1,4 @@
#include "RTC.h"
#include "gps/RTC.h"
#include "configuration.h"
#include "detect/ScanI2C.h"
#include "main.h"

View File

@ -13,13 +13,13 @@
#include "FSCommon.h"
#include "Led.h"
#include "RTC.h"
#include "SPILock.h"
#include "Throttle.h"
#include "concurrency/OSThread.h"
#include "concurrency/Periodic.h"
#include "detect/ScanI2C.h"
#include "error.h"
#include "gps/RTC.h"
#include "power.h"
#if !MESHTASTIC_EXCLUDE_I2C
@ -714,6 +714,7 @@ void setup()
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX17261, meshtastic_TelemetrySensorType_CUSTOM_SENSOR);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3);
@ -1612,3 +1613,15 @@ void loop()
}
}
#endif
#if !defined(CONFIG_AUTOSTART_ARDUINO) && (ESP_IDF_VERSION_MAJOR * 100 + ESP_IDF_VERSION_MINOR * 10 + ESP_IDF_VERSION_PATCH) > 512
// Define app_main to bridge Arduino and ESP-IDF
extern "C" void app_main(void)
{
setup();
while (1) {
loop();
vTaskDelay(1); // Allows FreeRTOS to manage tasks
}
}
#endif

View File

@ -9,8 +9,8 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "TypeConversions.h"
#include "gps/RTC.h"
#include "main.h"
#include "mesh-pb-constants.h"
#include "meshUtils.h"

View File

@ -12,12 +12,12 @@
#include "NodeDB.h"
#include "PacketHistory.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "Router.h"
#include "SPILock.h"
#include "SafeFile.h"
#include "TypeConversions.h"
#include "error.h"
#include "gps/RTC.h"
#include "main.h"
#include "mesh-pb-constants.h"
#include "meshUtils.h"

View File

@ -29,7 +29,7 @@
#include "mqtt/MQTT.h"
#endif
#include "Throttle.h"
#include <RTC.h>
#include "gps/RTC.h"
// Flag to indicate a heartbeat was received and we should send queue status
bool heartbeatReceived = false;

View File

@ -4,9 +4,9 @@
#include "MeshRadio.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "configuration.h"
#include "detect/LoRaRadioType.h"
#include "gps/RTC.h"
#include "main.h"
#include "mesh-pb-constants.h"
#include "meshUtils.h"

View File

@ -1,8 +1,8 @@
#include "StreamAPI.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "Throttle.h"
#include "configuration.h"
#include "gps/RTC.h"
#define START1 0x94
#define START2 0xc3

View File

@ -1,8 +1,8 @@
#include "mesh/eth/ethClient.h"
#include "NodeDB.h"
#include "RTC.h"
#include "concurrency/Periodic.h"
#include "configuration.h"
#include "gps/RTC.h"
#include "main.h"
#include "mesh/api/ethServerAPI.h"
#include "target_specific.h"

View File

@ -1,8 +1,8 @@
#include "configuration.h"
#if HAS_WIFI
#include "NodeDB.h"
#include "RTC.h"
#include "concurrency/Periodic.h"
#include "gps/RTC.h"
#include "mesh/wifi/WiFiAPClient.h"
#include "main.h"

View File

@ -3,9 +3,9 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "SPILock.h"
#include "input/InputBroker.h"
#include "gps/RTC.h"
#include "meshUtils.h"
#include <FSCommon.h>
#include <ctype.h> // for better whitespace handling

View File

@ -16,10 +16,10 @@
#include "ExternalNotificationModule.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "buzz/buzz.h"
#include "configuration.h"
#include "gps/RTC.h"
#include "main.h"
#include "mesh/generated/meshtastic/rtttl.pb.h"
#include <Arduino.h>

View File

@ -2,7 +2,7 @@
#include "Default.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "gps/RTC.h"
#include <Throttle.h>
NeighborInfoModule *neighborInfoModule;

View File

@ -2,9 +2,9 @@
#include "Default.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "configuration.h"
#include "gps/RTC.h"
#include "main.h"
#include <Throttle.h>

View File

@ -4,12 +4,12 @@
#include "GPS.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "TypeConversions.h"
#include "airtime.h"
#include "configuration.h"
#include "gps/GeoCoord.h"
#include "gps/RTC.h"
#include "main.h"
#include "mesh/compression/unishox2.h"
#include "meshUtils.h"

View File

@ -3,9 +3,9 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "RTC.h"
#include "Router.h"
#include "configuration.h"
#include "gps/RTC.h"
#include "main.h"
#include "sleep.h"
#include "target_specific.h"

View File

@ -13,12 +13,12 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "Router.h"
#include "SPILock.h"
#include "airtime.h"
#include "configuration.h"
#include "gps/GeoCoord.h"
#include "gps/RTC.h"
#include <Arduino.h>
#include <Throttle.h>

View File

@ -1,9 +1,9 @@
#include "RemoteHardwareModule.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "configuration.h"
#include "gps/RTC.h"
#include "main.h"
#include <Throttle.h>

View File

@ -3,9 +3,9 @@
#include "MeshService.h"
#include "NMEAWPL.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "configuration.h"
#include "gps/RTC.h"
#include <Arduino.h>
#include <Throttle.h>

View File

@ -15,11 +15,11 @@
#include "StoreForwardModule.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "Throttle.h"
#include "airtime.h"
#include "configuration.h"
#include "gps/RTC.h"
#include "memGet.h"
#include "mesh-pb-constants.h"
#include "mesh/generated/meshtastic/storeforward.pb.h"

View File

@ -8,9 +8,9 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "Router.h"
#include "detect/ScanI2CTwoWire.h"
#include "gps/RTC.h"
#include "main.h"
#include <Throttle.h>

View File

@ -4,10 +4,10 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "RadioLibInterface.h"
#include "Router.h"
#include "configuration.h"
#include "gps/RTC.h"
#include "main.h"
#include "memGet.h"
#include <OLEDDisplay.h>

View File

@ -8,12 +8,12 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "Router.h"
#include "UnitConversions.h"
#include "buzz.h"
#include "graphics/SharedUIDisplay.h"
#include "graphics/images.h"
#include "gps/RTC.h"
#include "main.h"
#include "modules/ExternalNotificationModule.h"
#include "power.h"

View File

@ -8,9 +8,9 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "Router.h"
#include "UnitConversions.h"
#include "gps/RTC.h"
#include "main.h"
#include "power.h"
#include "sleep.h"

View File

@ -0,0 +1,176 @@
#include "MAX17261Sensor.h"
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_STM32WL) && __has_include(<Adafruit_MAX1704X.h>)
MAX17048Singleton *MAX17048Singleton::GetInstance()
{
if (pinstance == nullptr) {
pinstance = new MAX17048Singleton();
}
return pinstance;
}
MAX17048Singleton::MAX17048Singleton() {}
MAX17048Singleton::~MAX17048Singleton() {}
MAX17048Singleton *MAX17048Singleton::pinstance{nullptr};
bool MAX17048Singleton::runOnce(TwoWire *theWire)
{
initialized = begin(theWire);
LOG_DEBUG("%s::runOnce %s", sensorStr, initialized ? "began ok" : "begin failed");
return initialized;
}
bool MAX17048Singleton::isBatteryCharging()
{
float volts = cellVoltage();
if (isnan(volts)) {
LOG_DEBUG("%s::isBatteryCharging not connected", sensorStr);
return 0;
}
MAX17048ChargeSample sample;
sample.chargeRate = chargeRate(); // charge/discharge rate in percent/hr
sample.cellPercent = cellPercent(); // state of charge in percent 0 to 100
chargeSamples.push(sample); // save a sample into a fifo buffer
// Keep the fifo buffer trimmed
while (chargeSamples.size() > MAX17048_CHARGING_SAMPLES)
chargeSamples.pop();
// Based on the past n samples, is the lipo charging, discharging or idle
if (chargeSamples.front().chargeRate > MAX17048_CHARGING_MINIMUM_RATE &&
chargeSamples.back().chargeRate > MAX17048_CHARGING_MINIMUM_RATE) {
if (chargeSamples.front().cellPercent > chargeSamples.back().cellPercent)
chargeState = MAX17048ChargeState::EXPORT;
else if (chargeSamples.front().cellPercent < chargeSamples.back().cellPercent)
chargeState = MAX17048ChargeState::IMPORT;
else
chargeState = MAX17048ChargeState::IDLE;
} else {
chargeState = MAX17048ChargeState::IDLE;
}
LOG_DEBUG("%s::isBatteryCharging %s volts: %.3f soc: %.3f rate: %.3f", sensorStr, chargeLabels[chargeState], volts,
sample.cellPercent, sample.chargeRate);
return chargeState == MAX17048ChargeState::IMPORT;
}
uint16_t MAX17048Singleton::getBusVoltageMv()
{
float volts = cellVoltage();
if (isnan(volts)) {
LOG_DEBUG("%s::getBusVoltageMv is not connected", sensorStr);
return 0;
}
LOG_DEBUG("%s::getBusVoltageMv %.3fmV", sensorStr, volts);
return (uint16_t)(volts * 1000.0f);
}
uint8_t MAX17048Singleton::getBusBatteryPercent()
{
float soc = cellPercent();
LOG_DEBUG("%s::getBusBatteryPercent %.1f%%", sensorStr, soc);
return clamp(static_cast<uint8_t>(round(soc)), static_cast<uint8_t>(0), static_cast<uint8_t>(100));
}
uint16_t MAX17048Singleton::getTimeToGoSecs()
{
float rate = chargeRate(); // charge/discharge rate in percent/hr
float soc = cellPercent(); // state of charge in percent 0 to 100
soc = clamp(soc, 0.0f, 100.0f); // clamp soc between 0 and 100%
float ttg = ((100.0f - soc) / rate) * 3600.0f; // calculate seconds to charge/discharge
LOG_DEBUG("%s::getTimeToGoSecs %.0f seconds", sensorStr, ttg);
return (uint16_t)ttg;
}
bool MAX17048Singleton::isBatteryConnected()
{
float volts = cellVoltage();
if (isnan(volts)) {
LOG_DEBUG("%s::isBatteryConnected is not connected", sensorStr);
return false;
}
// if a valid voltage is returned, then battery must be connected
return true;
}
bool MAX17048Singleton::isExternallyPowered()
{
float volts = cellVoltage();
if (isnan(volts)) {
// if the battery is not connected then there must be external power
LOG_DEBUG("%s::isExternallyPowered battery is", sensorStr);
return true;
}
// if the bus voltage is over MAX17048_BUS_POWER_VOLTS, then the external power
// is assumed to be connected
LOG_DEBUG("%s::isExternallyPowered %s connected", sensorStr, volts >= MAX17048_BUS_POWER_VOLTS ? "is" : "is not");
return volts >= MAX17048_BUS_POWER_VOLTS;
}
#if (HAS_TELEMETRY && (!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR || !MESHTASTIC_EXCLUDE_POWER_TELEMETRY))
MAX17048Sensor::MAX17048Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_MAX17048, "MAX17048") {}
int32_t MAX17048Sensor::runOnce()
{
if (isInitialized()) {
LOG_INFO("Init sensor: %s is already initialised", sensorName);
return true;
}
LOG_INFO("Init sensor: %s", sensorName);
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
// Get a singleton instance and initialise the max17048
if (max17048 == nullptr) {
max17048 = MAX17048Singleton::GetInstance();
}
status = max17048->runOnce(nodeTelemetrySensorsMap[sensorType].second);
return initI2CSensor();
}
void MAX17048Sensor::setup() {}
bool MAX17048Sensor::getMetrics(meshtastic_Telemetry *measurement)
{
LOG_DEBUG("MAX17048 getMetrics id: %i", measurement->which_variant);
float volts = max17048->cellVoltage();
if (isnan(volts)) {
LOG_DEBUG("MAX17048 getMetrics battery is not connected");
return false;
}
float rate = max17048->chargeRate(); // charge/discharge rate in percent/hr
float soc = max17048->cellPercent(); // state of charge in percent 0 to 100
soc = clamp(soc, 0.0f, 100.0f); // clamp soc between 0 and 100%
float ttg = (100.0f - soc) / rate; // calculate hours to charge/discharge
LOG_DEBUG("MAX17048 getMetrics volts: %.3fV soc: %.1f%% ttg: %.1f hours", volts, soc, ttg);
if ((int)measurement->which_variant == meshtastic_Telemetry_power_metrics_tag) {
measurement->variant.power_metrics.has_ch1_voltage = true;
measurement->variant.power_metrics.ch1_voltage = volts;
} else if ((int)measurement->which_variant == meshtastic_Telemetry_device_metrics_tag) {
measurement->variant.device_metrics.has_battery_level = true;
measurement->variant.device_metrics.has_voltage = true;
measurement->variant.device_metrics.battery_level = static_cast<uint32_t>(round(soc));
measurement->variant.device_metrics.voltage = volts;
}
return true;
}
uint16_t MAX17048Sensor::getBusVoltageMv()
{
return max17048->getBusVoltageMv();
};
#endif
#endif

View File

@ -0,0 +1,111 @@
#pragma once
#ifndef MAX17261_SENSOR_H
#define MAX17261_SENSOR_H
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_STM32WL) && __has_include(<Adafruit_MAX1704X.h>)
// Samples to store in a buffer to determine if the battery is charging or discharging
#define MAX17048_CHARGING_SAMPLES 3
// Threshold to determine if the battery is on charge, in percent/hour
#define MAX17048_CHARGING_MINIMUM_RATE 1.0f
// Threshold to determine if the board has bus power
#define MAX17048_BUS_POWER_VOLTS 4.195f
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include "VoltageSensor.h"
#include "meshUtils.h"
#include <Adafruit_MAX1704X.h>
#include <queue>
struct MAX17048ChargeSample {
float cellPercent;
float chargeRate;
};
enum MAX17048ChargeState { IDLE, EXPORT, IMPORT };
// Singleton wrapper for the Adafruit_MAX17048 class
class MAX17048Singleton : public Adafruit_MAX17048
{
private:
static MAX17048Singleton *pinstance;
bool initialized = false;
std::queue<MAX17048ChargeSample> chargeSamples;
MAX17048ChargeState chargeState = IDLE;
const String chargeLabels[3] = {F("idle"), F("export"), F("import")};
const char *sensorStr = "MAX17048Sensor";
protected:
MAX17048Singleton();
~MAX17048Singleton();
public:
// Create a singleton instance (not thread safe)
static MAX17048Singleton *GetInstance();
// Singletons should not be cloneable.
MAX17048Singleton(MAX17048Singleton &other) = delete;
// Singletons should not be assignable.
void operator=(const MAX17048Singleton &) = delete;
// Initialise the sensor (not thread safe)
virtual bool runOnce(TwoWire *theWire = &Wire);
// Get the current bus voltage
uint16_t getBusVoltageMv();
// Get the state of charge in percent 0 to 100
uint8_t getBusBatteryPercent();
// Calculate the seconds to charge/discharge
uint16_t getTimeToGoSecs();
// Returns true if the battery sensor has started
inline virtual bool isInitialised() { return initialized; };
// Returns true if the battery is currently on charge (not thread safe)
bool isBatteryCharging();
// Returns true if a battery is actually connected
bool isBatteryConnected();
// Returns true if there is bus or external power connected
bool isExternallyPowered();
};
#if (HAS_TELEMETRY && (!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR || !MESHTASTIC_EXCLUDE_POWER_TELEMETRY))
class MAX17048Sensor : public TelemetrySensor, VoltageSensor
{
private:
MAX17048Singleton *max17048 = nullptr;
protected:
virtual void setup() override;
public:
MAX17048Sensor();
// Initialise the sensor
virtual int32_t runOnce() override;
// Get the current bus voltage and state of charge
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
// Get the current bus voltage
virtual uint16_t getBusVoltageMv() override;
};
#endif
#endif
#endif

View File

@ -4,8 +4,8 @@
#include "FSCommon.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "gps/RTC.h"
/*
AudioModule

View File

@ -119,9 +119,14 @@ void esp32Setup()
LOG_DEBUG("Free heap: %d", ESP.getFreeHeap());
LOG_DEBUG("Total PSRAM: %d", ESP.getPsramSize());
LOG_DEBUG("Free PSRAM: %d", ESP.getFreePsram());
esp_log_level_set("gpio", ESP_LOG_WARN);
auto res = nvs_flash_init();
assert(res == ESP_OK);
nvs_stats_t nvs_stats;
auto res = nvs_get_stats(NULL, &nvs_stats);
res = nvs_get_stats(NULL, &nvs_stats);
assert(res == ESP_OK);
LOG_DEBUG("NVS: UsedEntries %d, FreeEntries %d, AllEntries %d, NameSpaces %d", nvs_stats.used_entries, nvs_stats.free_entries,
nvs_stats.total_entries, nvs_stats.namespace_count);
@ -172,8 +177,9 @@ void esp32Setup()
#ifdef CONFIG_IDF_TARGET_ESP32C6
esp_task_wdt_config_t *wdt_config = (esp_task_wdt_config_t *)malloc(sizeof(esp_task_wdt_config_t));
wdt_config->timeout_ms = APP_WATCHDOG_SECS * 1000;
wdt_config->idle_core_mask = 0;
wdt_config->trigger_panic = true;
res = esp_task_wdt_init(wdt_config);
res = esp_task_wdt_reconfigure(wdt_config);
assert(res == ESP_OK);
#else
res = esp_task_wdt_init(APP_WATCHDOG_SECS, true);
@ -185,6 +191,17 @@ void esp32Setup()
#ifdef HAS_32768HZ
enableSlowCLK();
#endif
#ifdef USE_XIAO_ESP32C6_EXTERNAL_ANTENNA
#warning "Connect an external antenna to your XIAO ESP32C6; otherwise, it may be damaged!"
gpio_reset_pin(GPIO_NUM_3);
gpio_set_direction(GPIO_NUM_3, GPIO_MODE_OUTPUT);
gpio_set_level(GPIO_NUM_3, LOW);
gpio_reset_pin(GPIO_NUM_14);
gpio_set_direction(GPIO_NUM_14, GPIO_MODE_OUTPUT);
gpio_set_level(GPIO_NUM_14, HIGH);
#endif
}
/// loop code specific to ESP32 targets

View File

@ -1,5 +1,5 @@
#include "RTC.h"
#include "configuration.h"
#include "gps/RTC.h"
#include <stm32wle5xx.h>
#include <stm32wlxx_hal.h>

View File

@ -0,0 +1,20 @@
[env:seeed-xiao-esp32c6]
extends = esp32c6_base
framework = arduino, espidf
board = esp32-c6-devkitm-1
board_check = true
board_build.partitions = partition-table.csv
upload_protocol = esptool
upload_speed = 921600
extra_scripts = pre:bin/platformio-custom.py
build_flags =
${esp32c6_base.build_flags}
-D PRIVATE_HW
-I variants/seeed_xiao_esp32c6
-D ARDUINO_USB_CDC_ON_BOOT=1
-D ARDUINO_USB_MODE=1
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/esp32c3"
-D HAS_BLUETOOTH=1
-D MESHTASTIC_EXCLUDE_WEBSERVER
-D MESHTASTIC_EXCLUDE_MQTT
-D CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT=1

View File

@ -0,0 +1,44 @@
#define LED_PIN 15
#define LED_STATE_ON 0 // State when LED is lit
#define BUTTON_PIN 21 // This is the Program Button
#define BUTTON_NEED_PULLUP
#define I2C_SDA 22
#define I2C_SCL 23
// #define USE_RF95
#define USE_SX1262
#define LORA_MISO 20
#define LORA_SCK 19
#define LORA_MOSI 18
#ifdef USE_RF95
#define LORA_CS 17
#define LORA_RESET 1
#define LORA_DIO0 0
#define LORA_DIO1 16
#endif
#ifdef USE_SX1262
#define LORA_CS 21
#define LORA_DIO1 7
#define LORA_BUSY 6
#define LORA_RESET 2
#define SX126X_CS LORA_CS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_BUSY
#define SX126X_RESET LORA_RESET
#define SX126X_RXEN 4
#define SX126X_TXEN RADIOLIB_NC
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif
#define HAS_GPS 0
#undef GPS_RX_PIN
#undef GPS_TX_PIN
// For BLE/WiFi connectivity
// #define USE_XIAO_ESP32C6_EXTERNAL_ANTENNA