diff --git a/arch/rp2040/rp2040.ini b/arch/rp2040/rp2040.ini
index edc4373ad..dd3a4d7ff 100644
--- a/arch/rp2040/rp2040.ini
+++ b/arch/rp2040/rp2040.ini
@@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
-platform = https://github.com/maxgerhardt/platform-raspberrypi.git#612de5399d68b359053f1307ed223d400aea975c
+platform = https://github.com/maxgerhardt/platform-raspberrypi.git#60d6ae81fcc73c34b1493ca9e261695e471bc0c2
extends = arduino_base
-platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.6.2
+platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.7.2
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
diff --git a/platformio.ini b/platformio.ini
index dbd15645f..c511587a6 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -78,7 +78,7 @@ lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
- https://github.com/meshtastic/TinyGPSPlus.git#2044b2c51e91ab4cd8cc93b15e40658cd808dd06
+ https://github.com/meshtastic/TinyGPSPlus.git#f9f4fef2183514aa52be91d714c1455dd6f26e45
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
nanopb/Nanopb@^0.4.7
erriez/ErriezCRC32@^1.0.1
diff --git a/protobufs b/protobufs
index cf25b390d..556e49ba6 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit cf25b390d65113980b1a239e16faa79c7730a736
+Subproject commit 556e49ba619e2f4d8fa3c2dee2a94129a43d5f08
diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp
index ed217c3ed..e17c8f99e 100644
--- a/src/SerialConsole.cpp
+++ b/src/SerialConsole.cpp
@@ -3,7 +3,11 @@
#include "PowerFSM.h"
#include "configuration.h"
+#ifdef RP2040_SLOW_CLOCK
+#define Port Serial2
+#else
#define Port Serial
+#endif
// Defaulting to the formerly removed phone_timeout_secs value of 15 minutes
#define SERIAL_CONNECTION_TIMEOUT (15 * 60) * 1000UL
@@ -31,6 +35,10 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), con
canWrite = false; // We don't send packets to our port until it has talked to us first
// setDestination(&noopPrint); for testing, try turning off 'all' debug output and see what leaks
+#ifdef RP2040_SLOW_CLOCK
+ Port.setTX(SERIAL2_TX);
+ Port.setRX(SERIAL2_RX);
+#endif
Port.begin(SERIAL_BAUD);
#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARCH_RP2040)
time_t timeout = millis();
@@ -64,7 +72,7 @@ bool SerialConsole::checkIsConnected()
/**
* we override this to notice when we've received a protobuf over the serial
- * stream. Then we shunt off debug serial output.
+ * stream. Then we shut off debug serial output.
*/
bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
{
diff --git a/src/configuration.h b/src/configuration.h
index ac8f9435a..ec32c72d1 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -111,6 +111,7 @@ along with this program. If not, see .
#define MCP9808_ADDR 0x18
#define INA_ADDR 0x40
#define INA_ADDR_ALTERNATE 0x41
+#define INA_ADDR_WAVESHARE_UPS 0x43
#define INA3221_ADDR 0x42
#define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index b6eca5fa4..146daa3dc 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -183,8 +183,13 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
case ATECC608B_ADDR:
- type = ATECC608B;
- if (atecc.begin(addr.address) == true) {
+#ifdef RP2040_SLOW_CLOCK
+ if (atecc.begin(addr.address, Wire, Serial2) == true)
+#else
+ if (atecc.begin(addr.address) == true)
+#endif
+
+ {
LOG_INFO("ATECC608B initialized\n");
} else {
LOG_WARN("ATECC608B initialization failed\n");
@@ -254,6 +259,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
case INA_ADDR:
case INA_ADDR_ALTERNATE:
+ case INA_ADDR_WAVESHARE_UPS:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
if (registerValue == 0x5449) {
diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp
index 849c38794..18932e066 100644
--- a/src/gps/GPS.cpp
+++ b/src/gps/GPS.cpp
@@ -290,6 +290,26 @@ bool GPS::setup()
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
_serial_gps->write("$PCAS11,3*1E\r\n");
delay(250);
+ } else if (gnssModel == GNSS_MODEL_MTK_L76B) {
+ // Waveshare Pico-GPS hat uses the L76B with 9600 baud
+ // Initialize the L76B Chip, use GPS + GLONASS
+ // See note in L76_Series_GNSS_Protocol_Specification, chapter 3.29
+ _serial_gps->write("$PMTK353,1,1,0,0,0*2B\r\n");
+ // Above command will reset the GPS and takes longer before it will accept new commands
+ delay(1000);
+ // only ask for RMC and GGA (GNRMC and GNGGA)
+ // See note in L76_Series_GNSS_Protocol_Specification, chapter 2.1
+ _serial_gps->write("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n");
+ delay(250);
+ // Enable SBAS
+ _serial_gps->write("$PMTK301,2*2E\r\n");
+ delay(250);
+ // Enable PPS for 2D/3D fix only
+ _serial_gps->write("$PMTK285,3,100*3F\r\n");
+ delay(250);
+ // Switch to Fitness Mode, for running and walking purpose with low speed (<5 m/s)
+ _serial_gps->write("$PMTK886,1*29\r\n");
+ delay(250);
} else if (gnssModel == GNSS_MODEL_UC6580) {
// The Unicore UC6580 can use a lot of sat systems, enable it to
// use GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS
@@ -625,17 +645,27 @@ void GPS::setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime)
return;
}
#endif
-#ifdef PIN_GPS_STANDBY // Specifically the standby pin for L76K and clones
+#ifdef PIN_GPS_STANDBY // Specifically the standby pin for L76B, L76K and clones
if (on) {
LOG_INFO("Waking GPS\n");
pinMode(PIN_GPS_STANDBY, OUTPUT);
+ // Some PCB's use an inverse logic due to a transistor driver
+ // Example for this is the Pico-Waveshare Lora+GPS HAT
+#ifdef PIN_GPS_STANDBY_INVERTED
+ digitalWrite(PIN_GPS_STANDBY, 0);
+#else
digitalWrite(PIN_GPS_STANDBY, 1);
+#endif
return;
} else {
LOG_INFO("GPS entering sleep\n");
// notifyGPSSleep.notifyObservers(NULL);
pinMode(PIN_GPS_STANDBY, OUTPUT);
+#ifdef PIN_GPS_STANDBY_INVERTED
+ digitalWrite(PIN_GPS_STANDBY, 1);
+#else
digitalWrite(PIN_GPS_STANDBY, 0);
+#endif
return;
}
#endif
@@ -916,7 +946,7 @@ GnssModel_t GPS::probe(int serialSpeed)
uint8_t buffer[768] = {0};
delay(100);
- // Close all NMEA sentences , Only valid for MTK platform
+ // Close all NMEA sentences , Only valid for L76K MTK platform
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
delay(20);
@@ -928,6 +958,18 @@ GnssModel_t GPS::probe(int serialSpeed)
return GNSS_MODEL_MTK;
}
+ // Close all NMEA sentences, valid for L76B MTK platform (Waveshare Pico GPS)
+ _serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
+ delay(20);
+
+ // Get version information
+ clearBuffer();
+ _serial_gps->write("$PMTK605*31\r\n");
+ if (getACK("Quectel-L76B", 500) == GNSS_RESPONSE_OK) {
+ LOG_INFO("L76B GNSS init succeeded, using L76B GNSS Module\n");
+ return GNSS_MODEL_MTK_L76B;
+ }
+
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
UBXChecksum(cfg_rate, sizeof(cfg_rate));
clearBuffer();
@@ -1109,7 +1151,6 @@ GPS *GPS::createGps()
LOG_DEBUG("Using GPIO%d for GPS RX\n", new_gps->rx_gpio);
LOG_DEBUG("Using GPIO%d for GPS TX\n", new_gps->tx_gpio);
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, new_gps->rx_gpio, new_gps->tx_gpio);
-
#else
_serial_gps->begin(GPS_BAUDRATE);
#endif
@@ -1168,7 +1209,16 @@ bool GPS::factoryReset()
// byte _message_CFG_RST_COLDSTART[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0xFF, 0xB9, 0x00, 0x00, 0xC6, 0x8B};
// _serial_gps->write(_message_CFG_RST_COLDSTART, sizeof(_message_CFG_RST_COLDSTART));
// delay(1000);
+ } else if (gnssModel == GNSS_MODEL_MTK) {
+ // send the CAS10 to perform a factory restart of the device (and other device that support PCAS statements)
+ LOG_INFO("GNSS Factory Reset via PCAS10,3\n");
+ _serial_gps->write("$PCAS10,3*1F\r\n");
+ delay(100);
} else {
+ // fire this for good measure, if we have an L76B - won't harm other devices.
+ _serial_gps->write("$PMTK104*37\r\n");
+ // No PMTK_ACK for this command.
+ delay(100);
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's UBLOX.
// Factory Reset
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
diff --git a/src/gps/GPS.h b/src/gps/GPS.h
index 77e1d8042..502763bb6 100644
--- a/src/gps/GPS.h
+++ b/src/gps/GPS.h
@@ -20,12 +20,7 @@ struct uBloxGnssModelInfo {
char extension[10][30];
};
-typedef enum {
- GNSS_MODEL_MTK,
- GNSS_MODEL_UBLOX,
- GNSS_MODEL_UC6580,
- GNSS_MODEL_UNKNOWN,
-} GnssModel_t;
+typedef enum { GNSS_MODEL_MTK, GNSS_MODEL_UBLOX, GNSS_MODEL_UC6580, GNSS_MODEL_UNKNOWN, GNSS_MODEL_MTK_L76B } GnssModel_t;
typedef enum {
GNSS_RESPONSE_NONE,
@@ -92,8 +87,11 @@ class GPS : private concurrency::OSThread
public:
/** If !NULL we will use this serial port to construct our GPS */
+#if defined(RPI_PICO_WAVESHARE)
+ static SerialUART *_serial_gps;
+#else
static HardwareSerial *_serial_gps;
-
+#endif
static uint8_t _message_PMREQ[];
static uint8_t _message_PMREQ_10[];
static const uint8_t _message_CFG_RXM_PSM[];
diff --git a/src/main.cpp b/src/main.cpp
index bb9b68631..fe5d455f8 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -223,7 +223,7 @@ void setup()
#if defined(TTGO_T_ECHO) && defined(PIN_POWER_EN)
pinMode(PIN_POWER_EN, OUTPUT);
digitalWrite(PIN_POWER_EN, HIGH);
- digitalWrite(PIN_POWER_EN1, INPUT);
+ // digitalWrite(PIN_POWER_EN1, INPUT);
#endif
#if defined(LORA_TCXO_GPIO)
@@ -965,4 +965,4 @@ void loop()
mainDelay.delay(delayMsec);
}
// if (didWake) LOG_DEBUG("wake!\n");
-}
\ No newline at end of file
+}
diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp
index 3e9c78241..93dec7e7d 100644
--- a/src/mesh/Channels.cpp
+++ b/src/mesh/Channels.cpp
@@ -7,6 +7,8 @@
#include
+#include "mqtt/MQTT.h"
+
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128)
static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01};
@@ -193,6 +195,10 @@ void Channels::onConfigChanged()
if (ch.role == meshtastic_Channel_Role_PRIMARY)
primaryIndex = i;
}
+ if (channels.anyMqttEnabled() && mqtt && !mqtt->isEnabled()) {
+ LOG_DEBUG("MQTT is enabled on at least one channel, so set MQTT thread to run immediately\n");
+ mqtt->start();
+ }
}
meshtastic_Channel &Channels::getByIndex(ChannelIndex chIndex)
@@ -237,6 +243,16 @@ void Channels::setChannel(const meshtastic_Channel &c)
old = c; // slam in the new settings/role
}
+bool Channels::anyMqttEnabled()
+{
+ for (int i = 0; i < getNumChannels(); i++)
+ if (channelFile.channels[i].role != meshtastic_Channel_Role_DISABLED && channelFile.channels[i].has_settings &&
+ (channelFile.channels[i].settings.downlink_enabled || channelFile.channels[i].settings.uplink_enabled))
+ return true;
+
+ return false;
+}
+
const char *Channels::getName(size_t chIndex)
{
// Convert the short "" representation for Default into a usable string
diff --git a/src/mesh/Channels.h b/src/mesh/Channels.h
index 0e11605c4..a1c4ba171 100644
--- a/src/mesh/Channels.h
+++ b/src/mesh/Channels.h
@@ -105,6 +105,9 @@ class Channels
// Returns true if we can be reached via a channel with the default settings given a region and modem preset
bool hasDefaultChannel();
+ // Returns true if any of our channels have enabled MQTT uplink or downlink
+ bool anyMqttEnabled();
+
private:
/** Given a channel index, change to use the crypto key specified by that index
*
diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp
index 270bf613f..e6b336d41 100644
--- a/src/mesh/PhoneAPI.cpp
+++ b/src/mesh/PhoneAPI.cpp
@@ -105,10 +105,17 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
break;
case meshtastic_ToRadio_mqttClientProxyMessage_tag:
LOG_INFO("Got MqttClientProxy message\n");
- if (mqtt && moduleConfig.mqtt.proxy_to_client_enabled) {
+ if (mqtt && moduleConfig.mqtt.proxy_to_client_enabled && moduleConfig.mqtt.enabled &&
+ (channels.anyMqttEnabled() || moduleConfig.mqtt.map_reporting_enabled)) {
mqtt->onClientProxyReceive(toRadioScratch.mqttClientProxyMessage);
+ } else {
+ LOG_WARN("MqttClientProxy received but proxy is not enabled, no channels have up/downlink, or map reporting "
+ "not enabled\n");
}
break;
+ case meshtastic_ToRadio_heartbeat_tag:
+ LOG_DEBUG("Got client heartbeat\n");
+ break;
default:
// Ignore nop messages
// LOG_DEBUG("Error: unexpected ToRadio variant\n");
diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h
index 79800d4b4..d6a2a0272 100644
--- a/src/mesh/generated/meshtastic/deviceonly.pb.h
+++ b/src/mesh/generated/meshtastic/deviceonly.pb.h
@@ -141,7 +141,8 @@ typedef struct _meshtastic_DeviceState {
NodeDB.cpp in the device code. */
uint32_t version;
/* Used only during development.
- Indicates developer is testing and changes should never be saved to flash. */
+ Indicates developer is testing and changes should never be saved to flash.
+ Deprecated in 2.3.1 */
bool no_save;
/* Some GPS receivers seem to have bogus settings from the factory, so we always do one factory reset. */
bool did_gps_reset;
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index 8f260589c..2f57f1ae2 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -819,7 +819,7 @@ typedef struct _meshtastic_ToRadio {
/* MQTT Client Proxy Message (for client / phone subscribed to MQTT sending to device) */
meshtastic_MqttClientProxyMessage mqttClientProxyMessage;
/* Heartbeat message (used to keep the device connection awake on serial) */
- meshtastic_Heartbeat hearbeat;
+ meshtastic_Heartbeat heartbeat;
};
} meshtastic_ToRadio;
@@ -1066,7 +1066,7 @@ extern "C" {
#define meshtastic_ToRadio_disconnect_tag 4
#define meshtastic_ToRadio_xmodemPacket_tag 5
#define meshtastic_ToRadio_mqttClientProxyMessage_tag 6
-#define meshtastic_ToRadio_hearbeat_tag 7
+#define meshtastic_ToRadio_heartbeat_tag 7
/* Struct field encoding specification for nanopb */
#define meshtastic_Position_FIELDLIST(X, a) \
@@ -1247,13 +1247,13 @@ X(a, STATIC, ONEOF, UINT32, (payload_variant,want_config_id,want_config_i
X(a, STATIC, ONEOF, BOOL, (payload_variant,disconnect,disconnect), 4) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket), 5) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttClientProxyMessage), 6) \
-X(a, STATIC, ONEOF, MESSAGE, (payload_variant,hearbeat,hearbeat), 7)
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,heartbeat,heartbeat), 7)
#define meshtastic_ToRadio_CALLBACK NULL
#define meshtastic_ToRadio_DEFAULT NULL
#define meshtastic_ToRadio_payload_variant_packet_MSGTYPE meshtastic_MeshPacket
#define meshtastic_ToRadio_payload_variant_xmodemPacket_MSGTYPE meshtastic_XModem
#define meshtastic_ToRadio_payload_variant_mqttClientProxyMessage_MSGTYPE meshtastic_MqttClientProxyMessage
-#define meshtastic_ToRadio_payload_variant_hearbeat_MSGTYPE meshtastic_Heartbeat
+#define meshtastic_ToRadio_payload_variant_heartbeat_MSGTYPE meshtastic_Heartbeat
#define meshtastic_Compressed_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, portnum, 1) \
diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp
index 5177af33a..6b4289970 100644
--- a/src/modules/NodeInfoModule.cpp
+++ b/src/modules/NodeInfoModule.cpp
@@ -58,8 +58,8 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
meshtastic_MeshPacket *NodeInfoModule::allocReply()
{
uint32_t now = millis();
- // If we sent our NodeInfo less than 1 min. ago, don't send it again as it may be still underway.
- if (lastSentToMesh && (now - lastSentToMesh) < 60 * 1000) {
+ // If we sent our NodeInfo less than 5 min. ago, don't send it again as it may be still underway.
+ if (lastSentToMesh && (now - lastSentToMesh) < (5 * 60 * 1000)) {
LOG_DEBUG("Sending NodeInfo will be ignored since we just sent it.\n");
ignoreRequest = true; // Mark it as ignored for MeshModule
return NULL;
diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp
index 820e1fb62..1dee42a8d 100644
--- a/src/modules/SerialModule.cpp
+++ b/src/modules/SerialModule.cpp
@@ -126,8 +126,13 @@ int32_t SerialModule::runOnce()
uint32_t baud = getBaudRate();
if (moduleConfig.serial.override_console_serial_port) {
+#ifdef RP2040_SLOW_CLOCK
+ Serial2.flush();
+ serialPrint = &Serial2;
+#else
Serial.flush();
serialPrint = &Serial;
+#endif
// Give it a chance to flush out 💩
delay(10);
}
@@ -151,8 +156,13 @@ int32_t SerialModule::runOnce()
Serial2.begin(baud, SERIAL_8N1);
Serial2.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
} else {
+#ifdef RP2040_SLOW_CLOCK
+ Serial2.begin(baud, SERIAL_8N1);
+ Serial2.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
+#else
Serial.begin(baud, SERIAL_8N1);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
+#endif
}
#else
Serial.begin(baud, SERIAL_8N1);
diff --git a/src/modules/Telemetry/Sensor/INA219Sensor.cpp b/src/modules/Telemetry/Sensor/INA219Sensor.cpp
index 5a1faa99f..ecb564368 100644
--- a/src/modules/Telemetry/Sensor/INA219Sensor.cpp
+++ b/src/modules/Telemetry/Sensor/INA219Sensor.cpp
@@ -4,6 +4,10 @@
#include "configuration.h"
#include
+#ifndef INA219_MULTIPLIER
+#define INA219_MULTIPLIER 1.0f
+#endif
+
INA219Sensor::INA219Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_INA219, "INA219") {}
int32_t INA219Sensor::runOnce()
@@ -26,7 +30,7 @@ void INA219Sensor::setup() {}
bool INA219Sensor::getMetrics(meshtastic_Telemetry *measurement)
{
measurement->variant.environment_metrics.voltage = ina219.getBusVoltage_V();
- measurement->variant.environment_metrics.current = ina219.getCurrent_mA();
+ measurement->variant.environment_metrics.current = ina219.getCurrent_mA() * INA219_MULTIPLIER;
return true;
}
diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp
index c518bc4b5..0d99a3cfd 100644
--- a/src/mqtt/MQTT.cpp
+++ b/src/mqtt/MQTT.cpp
@@ -371,22 +371,9 @@ void MQTT::sendSubscriptions()
bool MQTT::wantsLink() const
{
- bool hasChannelorMapReport = false;
+ bool hasChannelorMapReport =
+ moduleConfig.mqtt.enabled && (moduleConfig.mqtt.map_reporting_enabled || channels.anyMqttEnabled());
- if (moduleConfig.mqtt.enabled) {
- hasChannelorMapReport = moduleConfig.mqtt.map_reporting_enabled;
- if (!hasChannelorMapReport) {
- // No need for link if no channel needed it
- size_t numChan = channels.getNumChannels();
- for (size_t i = 0; i < numChan; i++) {
- const auto &ch = channels.getByIndex(i);
- if (ch.settings.uplink_enabled || ch.settings.downlink_enabled) {
- hasChannelorMapReport = true;
- break;
- }
- }
- }
- }
if (hasChannelorMapReport && moduleConfig.mqtt.proxy_to_client_enabled)
return true;
@@ -401,7 +388,7 @@ bool MQTT::wantsLink() const
int32_t MQTT::runOnce()
{
- if (!moduleConfig.mqtt.enabled)
+ if (!moduleConfig.mqtt.enabled || !(moduleConfig.mqtt.map_reporting_enabled || channels.anyMqttEnabled()))
return disable();
bool wantConnection = wantsLink();
@@ -915,4 +902,4 @@ bool MQTT::isValidJsonEnvelope(JSONObject &json)
(json["from"]->AsNumber() == nodeDB.getNodeNum()) && // only accept message if the "from" is us
(json.find("type") != json.end()) && json["type"]->IsString() && // should specify a type
(json.find("payload") != json.end()); // should have a payload
-}
+}
\ No newline at end of file
diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h
index eeeb00d92..dbc0c77b3 100644
--- a/src/mqtt/MQTT.h
+++ b/src/mqtt/MQTT.h
@@ -71,6 +71,10 @@ class MQTT : private concurrency::OSThread
void onClientProxyReceive(meshtastic_MqttClientProxyMessage msg);
+ bool isEnabled() { return this->enabled; };
+
+ void start() { setIntervalFromNow(0); };
+
protected:
PointerQueue mqttQueue;
diff --git a/src/platform/rp2040/main-rp2040.cpp b/src/platform/rp2040/main-rp2040.cpp
index 283b801f1..af3aeadc3 100644
--- a/src/platform/rp2040/main-rp2040.cpp
+++ b/src/platform/rp2040/main-rp2040.cpp
@@ -1,4 +1,7 @@
#include "configuration.h"
+#include
+#include
+#include
#include
#include
@@ -35,9 +38,56 @@ void rp2040Setup()
Taken from CPU cycle counter and ROSC oscillator, so should be pretty random.
*/
randomSeed(rp2040.hwrand32());
+
+#ifdef RP2040_SLOW_CLOCK
+ uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY);
+ uint f_pll_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_USB_CLKSRC_PRIMARY);
+ uint f_rosc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC);
+ uint f_clk_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS);
+ uint f_clk_peri = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_PERI);
+ uint f_clk_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_USB);
+ uint f_clk_adc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_ADC);
+ uint f_clk_rtc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC);
+
+ LOG_INFO("Clock speed:\n");
+ LOG_INFO("pll_sys = %dkHz\n", f_pll_sys);
+ LOG_INFO("pll_usb = %dkHz\n", f_pll_usb);
+ LOG_INFO("rosc = %dkHz\n", f_rosc);
+ LOG_INFO("clk_sys = %dkHz\n", f_clk_sys);
+ LOG_INFO("clk_peri = %dkHz\n", f_clk_peri);
+ LOG_INFO("clk_usb = %dkHz\n", f_clk_usb);
+ LOG_INFO("clk_adc = %dkHz\n", f_clk_adc);
+ LOG_INFO("clk_rtc = %dkHz\n", f_clk_rtc);
+#endif
}
void enterDfuMode()
{
reset_usb_boot(0, 0);
-}
\ No newline at end of file
+}
+
+/* Init in early boot state. */
+#ifdef RP2040_SLOW_CLOCK
+void initVariant()
+{
+ /* Set the system frequency to 18 MHz. */
+ set_sys_clock_khz(18 * KHZ, false);
+ /* The previous line automatically detached clk_peri from clk_sys, and
+ attached it to pll_usb. We need to attach clk_peri back to system PLL to keep SPI
+ working at this low speed.
+ For details see https://github.com/jgromes/RadioLib/discussions/938
+ */
+ clock_configure(clk_peri,
+ 0, // No glitchless mux
+ CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, // System PLL on AUX mux
+ 18 * MHZ, // Input frequency
+ 18 * MHZ // Output (must be same as no divider)
+ );
+ /* Run also ADC on lower clk_sys. */
+ clock_configure(clk_adc, 0, CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, 18 * MHZ, 18 * MHZ);
+ /* Run RTC from XOSC since USB clock is off */
+ clock_configure(clk_rtc, 0, CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC, 12 * MHZ, 47 * KHZ);
+ /* Turn off USB PLL */
+ pll_deinit(pll_usb);
+}
+#endif
\ No newline at end of file
diff --git a/src/sleep.cpp b/src/sleep.cpp
index bfacffeb9..6d8e4f3cc 100644
--- a/src/sleep.cpp
+++ b/src/sleep.cpp
@@ -203,7 +203,7 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
#ifdef TTGO_T_ECHO
#ifdef PIN_POWER_EN
pinMode(PIN_POWER_EN, INPUT); // power off peripherals
- pinMode(PIN_POWER_EN1, INPUT_PULLDOWN);
+ // pinMode(PIN_POWER_EN1, INPUT_PULLDOWN);
#endif
#endif
diff --git a/variants/rpipico-slowclock/platformio.ini b/variants/rpipico-slowclock/platformio.ini
new file mode 100644
index 000000000..e583c4b0d
--- /dev/null
+++ b/variants/rpipico-slowclock/platformio.ini
@@ -0,0 +1,28 @@
+[env:pico_slowclock]
+extends = rp2040_base
+board = rpipico
+upload_protocol = jlink
+# debug settings for external openocd with RP2040 support (custom build)
+debug_tool = custom
+debug_init_cmds =
+ target extended-remote localhost:3333
+ $INIT_BREAK
+ monitor reset halt
+ $LOAD_CMDS
+ monitor init
+ monitor reset halt
+
+# add our variants files to the include and src paths
+build_flags = ${rp2040_base.build_flags}
+ -DRPI_PICO
+ -Ivariants/rpipico_slowclock
+ -DDEBUG_RP2040_PORT=Serial2
+ -DHW_SPI1_DEVICE
+ -L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus"
+ -g
+ -DNO_USB
+lib_deps =
+ ${rp2040_base.lib_deps}
+debug_build_flags = ${rp2040_base.build_flags}
+ -g
+ -DNO_USB
\ No newline at end of file
diff --git a/variants/rpipico-slowclock/variant.h b/variants/rpipico-slowclock/variant.h
new file mode 100644
index 000000000..fb97ec0fb
--- /dev/null
+++ b/variants/rpipico-slowclock/variant.h
@@ -0,0 +1,87 @@
+#define ARDUINO_ARCH_AVR
+
+// Build with slow system clock enabled to reduce power consumption.
+#define RP2040_SLOW_CLOCK
+
+#ifdef RP2040_SLOW_CLOCK
+// Redefine UART1 serial log output to avoid collision with UART0 for GPS.
+#define SERIAL2_TX 4
+#define SERIAL2_RX 5
+// Reroute log output in SensorLib when USB is not available
+#define log_e(...) Serial2.printf(__VA_ARGS__)
+#define log_i(...) Serial2.printf(__VA_ARGS__)
+#define log_d(...) Serial2.printf(__VA_ARGS__)
+#endif
+
+// Expecting the Waveshare Pico GPS hat
+#define HAS_GPS 1
+
+// Enable OLED Screen
+#define HAS_SCREEN 1
+#define USE_SH1106 1
+#define RESET_OLED 13
+
+// Redefine I2C0 pins to avoid collision with UART1/Serial2.
+#define I2C_SDA 8
+#define I2C_SCL 9
+
+// Redefine Waveshare UPS-A/B I2C_1 pins:
+#define I2C_SDA1 6
+#define I2C_SCL1 7
+// Waveshare UPS-A/B uses a 0.01 Ohm shunt for the INA219 sensor
+#define INA219_MULTIPLIER 10.0f
+
+// Waveshare Pico GPS L76B pins:
+#define GPS_RX_PIN 1
+#define GPS_TX_PIN 0
+
+// Wakeup from backup mode
+// #define PIN_GPS_FORCE_ON 14
+// No GPS reset available
+#undef PIN_GPS_RESET
+/*
+ * For PPS output the resistor R20 needs to be populated with 0 Ohm
+ * on the Waveshare Pico GPS board.
+ */
+#define PIN_GPS_PPS 16
+/*
+ * For standby mode switching the resistor R18 needs to be populated
+ * with 0 Ohm on the Waveshare Pico GPS board.
+ */
+#define PIN_GPS_STANDBY 17
+
+#define BUTTON_PIN 18
+#define EXT_NOTIFY_OUT 22
+#define LED_PIN PIN_LED
+
+#define BATTERY_PIN 26
+// ratio of voltage divider = 3.0 (R17=200k, R18=100k)
+#define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic
+#define BATTERY_SENSE_RESOLUTION_BITS ADC_RESOLUTION
+
+#define USE_SX1262
+
+#undef LORA_SCK
+#undef LORA_MISO
+#undef LORA_MOSI
+#undef LORA_CS
+
+#define LORA_SCK 10
+#define LORA_MISO 12
+#define LORA_MOSI 11
+#define LORA_CS 3
+
+#define LORA_DIO0 RADIOLIB_NC
+#define LORA_RESET 15
+#define LORA_DIO1 20
+#define LORA_DIO2 2
+#define LORA_DIO3 RADIOLIB_NC
+
+#ifdef USE_SX1262
+#define SX126X_CS LORA_CS
+#define SX126X_DIO1 LORA_DIO1
+#define SX126X_BUSY LORA_DIO2
+#define SX126X_RESET LORA_RESET
+#define SX126X_DIO2_AS_RF_SWITCH
+#define SX126X_DIO3_TCXO_VOLTAGE 1.8
+#endif
\ No newline at end of file
diff --git a/variants/t-echo/variant.h b/variants/t-echo/variant.h
index 19a66719f..13f74d303 100644
--- a/variants/t-echo/variant.h
+++ b/variants/t-echo/variant.h
@@ -158,7 +158,7 @@ External serial flash WP25R1635FZUIL0
// Controls power for all peripherals (eink + GPS + LoRa + Sensor)
#define PIN_POWER_EN (0 + 12)
-#define PIN_POWER_EN1 (0 + 13)
+// #define PIN_POWER_EN1 (0 + 13)
#define USE_EINK