Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0c31cd6
Added getMCUTemperature
IoTThinks Nov 30, 2025
1068d9a
getMCUTemperature
IoTThinks Nov 30, 2025
d70bbbc
getMCUTemperature
IoTThinks Nov 30, 2025
280fdb6
A common parent for all NRF52 boards
IoTThinks Nov 30, 2025
28da9ae
To extend NRF52Board
IoTThinks Nov 30, 2025
3f0f193
To extend NRF52Board
IoTThinks Nov 30, 2025
9815e9d
To extend NRF52Board
IoTThinks Nov 30, 2025
c173a04
To extend NRF52Board
IoTThinks Nov 30, 2025
3908295
To extend NRF52Board
IoTThinks Nov 30, 2025
25e5329
To extend NRF52Board
IoTThinks Nov 30, 2025
4088f66
To extend NRF52Board
IoTThinks Nov 30, 2025
0271c9b
To extend NRF52Board
IoTThinks Nov 30, 2025
b870d74
To extend NRF52Board
IoTThinks Nov 30, 2025
0fa72b6
To extend NRF52Board
IoTThinks Nov 30, 2025
8fb7f64
To extend NRF52Board
IoTThinks Nov 30, 2025
fff34bb
To extend NRF52Board
IoTThinks Nov 30, 2025
2b94ff4
To extend NRF52Board
IoTThinks Nov 30, 2025
8e276b0
To extend NRF52Board
IoTThinks Nov 30, 2025
8331e40
To extend NRF52Board
IoTThinks Nov 30, 2025
841129a
To extend NRF52Board
IoTThinks Nov 30, 2025
f61811a
To extend NRF52Board
IoTThinks Nov 30, 2025
2581245
Removed unrelated libs
IoTThinks Nov 30, 2025
b92f63b
Compare temperature with NAN only
IoTThinks Dec 11, 2025
486656a
Return default NAN value to MCU Temperature
IoTThinks Dec 11, 2025
d9a02b2
To wait 1ms only to get temperature from NRF52 MCU
IoTThinks Dec 11, 2025
8f3150d
Added getMCUTemperature
IoTThinks Nov 30, 2025
6816009
Merge branch 'MCdev-MCUTemperature-for-repeaters' of https://github.c…
IoTThinks Dec 12, 2025
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
6 changes: 6 additions & 0 deletions examples/simple_repeater/MyMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,12 @@ int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t

telemetry.reset();
telemetry.addVoltage(TELEM_CHANNEL_SELF, (float)board.getBattMilliVolts() / 1000.0f);

float temperature = (float)board.getMCUTemperature();
if(!isnan(temperature)) { // Supported boards with built-in temperature sensor. ESP32-C3 may return NAN
telemetry.addTemperature(TELEM_CHANNEL_SELF, (float)board.getMCUTemperature()); // Built-in MCU Temperature
}

// query other sensors -- target specific
if ((sender->permissions & PERM_ACL_ROLE_MASK) == PERM_ACL_GUEST) {
perm_mask = 0x00; // just base telemetry allowed
Expand Down
4 changes: 3 additions & 1 deletion src/MeshCore.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <stdint.h>
#include <math.h>

#define MAX_HASH_SIZE 8
#define PUB_KEY_SIZE 32
Expand Down Expand Up @@ -42,6 +43,7 @@ namespace mesh {
class MainBoard {
public:
virtual uint16_t getBattMilliVolts() = 0;
virtual float getMCUTemperature() { return NAN; }
virtual bool setAdcMultiplier(float multiplier) { return false; };
virtual float getAdcMultiplier() const { return 0.0f; }
virtual const char* getManufacturerName() const = 0;
Expand Down Expand Up @@ -88,4 +90,4 @@ class RTCClock {
}
};

}
}
4 changes: 4 additions & 0 deletions src/helpers/ESP32Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ class ESP32Board : public mesh::MainBoard {
#endif
}

float getMCUTemperature() override {
return temperatureRead(); // // The default is from the built-in temperature sensor of MCU
}

uint8_t getStartupReason() const override { return startup_reason; }

#if defined(P_LORA_TX_LED)
Expand Down
25 changes: 25 additions & 0 deletions src/helpers/NRF52Board.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#if defined(NRF52_PLATFORM)
#include "NRF52Board.h"

// Temperature from NRF52 MCU
float NRF52Board::getMCUTemperature() {
NRF_TEMP->TASKS_START = 1; // Start temperature measurement

long startTime = millis();
while (NRF_TEMP->EVENTS_DATARDY == 0) { // Wait for completion. Should complete in 50us
if(millis() - startTime > 1) { // To wait 1ms

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: if you're unlucky, millis returns 0 in the first call (while being internally at 0.9999999 ms) and then instantly rolls over to 1 in the next call, without 50us having passed.

Additionally, what happens if millis() rolls over (after 49 days)?

Copy link
Author

@IoTThinks IoTThinks Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@redfast00

  1. Well, a repeater takes several seconds even minutes to finish initiazliation.
    When you manage to do remote management to a repeater, it takes even a few minutes to get to this point.
    How possible this millis returns 0?

  2. The NRF_TEMP->EVENTS_DATARDY is expected to complete within 50us. This is a commitment fron NRF52.
    If this is happened, the NRF52 MCU is faulty and it should be replaced before we talk about this temperature.
    Furthermore, the timeout is an additional protection.
    The chance for both conditions to hold true in this case is much lower than winning a lottery in a lifetime.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@IoTThinks good point on point 2 :)

On point 1, I think I should have clarified further: the granularity of millis() is not enough if you want to be guaranteed to wait at least 50us by setting a timeout of 1ms. Another example: if you are at 50000.999999999 ms since boot, the first millis call will return 50000. Before 50us has passed, the next millis call will already return 50001.

This could be fixed by changing the timeout to 2 milliseconds instead, that way, you're guaranteed to wait at least 1 full millisecond instead of having no minimal guaranteed timeout.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point 1 actually wasn't as nitpicky as I though: if you keep the code as-is, you'll see the timeout code trigger before 50us 5% of all calls, on average.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@redfast00 How do you calculate the 5%?
Just keen to know.

1ms or even 10ms is fine for me.

The app is not required to be responsive at ms anyway.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did I calculate the 5%?

At the end of each millisecond real time, the millis() function return value will increase by one. If this happens before 50us of real time has passed, we say the code 'fails' (since it aborts the measurement without 50us having passed). So if the code starts at the end of n ms - 20 us real time for example, it fails, since it will already roll over at n ms. This roll-over happens every millisecond, and the unsafe window is between n ms - 50us to n ms - 0.0000000..1us. So for 50us every millisecond, we're 'unsafe', so this is 50us / 1ms = 5%.

NRF_TEMP->TASKS_STOP = 1;
return NAN;
}
}

NRF_TEMP->EVENTS_DATARDY = 0; // Clear event flag

int32_t temp = NRF_TEMP->TEMP; // In 0.25 *C units
NRF_TEMP->TASKS_STOP = 1;

return temp * 0.25f; // Convert to *C
}

#endif

13 changes: 13 additions & 0 deletions src/helpers/NRF52Board.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <MeshCore.h>
#include <Arduino.h>

#if defined(NRF52_PLATFORM)

class NRF52Board : public mesh::MainBoard {
public:
float getMCUTemperature() override;
};

#endif
3 changes: 2 additions & 1 deletion variants/heltec_mesh_solar/MeshSolarBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

#ifdef HELTEC_MESH_SOLAR
#include "meshSolarApp.h"
Expand All @@ -20,7 +21,7 @@
#define SX126X_DIO3_TCXO_VOLTAGE 1.8


class MeshSolarBoard : public mesh::MainBoard {
class MeshSolarBoard : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/heltec_t114/T114Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

// built-ins
#define PIN_VBAT_READ 4
#define PIN_BAT_CTL 6
#define MV_LSB (3000.0F / 4096.0F) // 12-bit ADC with 3.0V input range

class T114Board : public mesh::MainBoard {
class T114Board : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/ikoka_nano_nrf/IkokaNanoNRFBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

#ifdef XIAO_NRF52

class IkokaNanoNRFBoard : public mesh::MainBoard {
class IkokaNanoNRFBoard : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/ikoka_stick_nrf/IkokaStickNRFBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

#ifdef XIAO_NRF52

class IkokaStickNRFBoard : public mesh::MainBoard {
class IkokaStickNRFBoard : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/lilygo_techo/TechoBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

// built-ins
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
Expand All @@ -12,7 +13,7 @@
#define PIN_VBAT_READ (4)
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)

class TechoBoard : public mesh::MainBoard {
class TechoBoard : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/lilygo_techo_lite/TechoBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

// built-ins
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
Expand All @@ -12,7 +13,7 @@
#define PIN_VBAT_READ (4)
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)

class TechoBoard : public mesh::MainBoard {
class TechoBoard : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/mesh_pocket/MeshPocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

#include <Arduino.h>
#include <MeshCore.h>
#include <helpers/NRF52Board.h>

// built-ins
#define PIN_VBAT_READ 29
#define PIN_BAT_CTL 34
#define MV_LSB (3000.0F / 4096.0F) // 12-bit ADC with 3.0V input range

class HeltecMeshPocket : public mesh::MainBoard {
class HeltecMeshPocket : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
5 changes: 3 additions & 2 deletions variants/minewsemi_me25ls01/MinewsemiME25LS01Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

// LoRa and SPI pins

Expand All @@ -20,7 +21,7 @@
#define ADC_MULTIPLIER (1.815f) // dependent on voltage divider resistors. TODO: more accurate battery tracking


class MinewsemiME25LS01Board : public mesh::MainBoard {
class MinewsemiME25LS01Board : public NRF52Board {
protected:
uint8_t startup_reason;
uint8_t btn_prev_state;
Expand Down Expand Up @@ -85,4 +86,4 @@ class MinewsemiME25LS01Board : public mesh::MainBoard {
}

bool startOTAUpdate(const char* id, char reply[]) override;
};
};
3 changes: 2 additions & 1 deletion variants/nano_g2_ultra/nano-g2.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <Arduino.h>
#include <MeshCore.h>
#include <helpers/NRF52Board.h>

// LoRa radio module pins
#define P_LORA_DIO_1 (32 + 10)
Expand Down Expand Up @@ -34,7 +35,7 @@
#define PIN_VBAT_READ (0 + 2)
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)

class NanoG2Ultra : public mesh::MainBoard {
class NanoG2Ultra : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/promicro/PromicroBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

#define P_LORA_NSS 13 //P1.13 45
#define P_LORA_DIO_1 11 //P0.10 10
Expand All @@ -19,7 +20,7 @@
#define PIN_VBAT_READ 17
#define ADC_MULTIPLIER (1.815f) // dependent on voltage divider resistors. TODO: more accurate battery tracking

class PromicroBoard : public mesh::MainBoard {
class PromicroBoard : public NRF52Board {
protected:
uint8_t startup_reason;
uint8_t btn_prev_state;
Expand Down
3 changes: 2 additions & 1 deletion variants/rak4631/RAK4631Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

// LoRa radio module pins for RAK4631
#define P_LORA_DIO_1 47
Expand All @@ -28,7 +29,7 @@
#define PIN_VBAT_READ 5
#define ADC_MULTIPLIER (3 * 1.73 * 1.187 * 1000)

class RAK4631Board : public mesh::MainBoard {
class RAK4631Board : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/rak_wismesh_tag/RAKWismeshTagBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

// built-ins
#define PIN_VBAT_READ 5
#define ADC_MULTIPLIER (3 * 1.73 * 1.187 * 1000)

class RAKWismeshTagBoard : public mesh::MainBoard {
class RAKWismeshTagBoard : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/sensecap_solar/SenseCapSolarBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

class SenseCapSolarBoard : public mesh::MainBoard {
class SenseCapSolarBoard : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
5 changes: 3 additions & 2 deletions variants/t1000-e/T1000eBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

class T1000eBoard : public mesh::MainBoard {
class T1000eBoard : public NRF52Board {
protected:
uint8_t startup_reason;
uint8_t btn_prev_state;
Expand Down Expand Up @@ -97,4 +98,4 @@ class T1000eBoard : public mesh::MainBoard {
}

// bool startOTAUpdate(const char* id, char reply[]) override;
};
};
3 changes: 2 additions & 1 deletion variants/thinknode_m1/ThinkNodeM1Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

// built-ins
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
Expand All @@ -12,7 +13,7 @@
#define PIN_VBAT_READ (4)
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)

class ThinkNodeM1Board : public mesh::MainBoard {
class ThinkNodeM1Board : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down
3 changes: 2 additions & 1 deletion variants/wio-tracker-l1/WioTrackerL1Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

class WioTrackerL1Board : public mesh::MainBoard {
class WioTrackerL1Board : public NRF52Board {
protected:
uint8_t startup_reason;
uint8_t btn_prev_state;
Expand Down
5 changes: 3 additions & 2 deletions variants/xiao_nrf52/XiaoNrf52Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

#ifdef XIAO_NRF52

class XiaoNrf52Board : public mesh::MainBoard {
class XiaoNrf52Board : public NRF52Board {
protected:
uint8_t startup_reason;

Expand Down Expand Up @@ -67,4 +68,4 @@ class XiaoNrf52Board : public mesh::MainBoard {
bool startOTAUpdate(const char* id, char reply[]) override;
};

#endif
#endif