The Things Node : new low power library development


Hi all,

I’m trying to get official the things node working for a descent time, my first tests have not been really successful.

Looking at this post seems I’m not the only one.

Here is the pdf of schematics of the Things Node

An idea would be to have a real sketch example for Low Power on this node. So may be we can post on this thread all trick and suggestion.

The first test I’ve done was to remove sending Lora frame on motion to preserve battery, but even with that (and node not moving) it survived only 2 weeks.

So I decided to tweak again the code to monitor battery, sending frame every 5 minutes or with button press. And of course disabling all sensors. We’ll see if it’s better, here is new code

#include <TheThingsNode.h>
#include <CayenneLPP.h>

// Set your AppEUI and AppKey
const char *appEui = "XXXXXXXXXXXXXXXX";

#define loraSerial Serial1
#define debugSerial Serial

// Replace REPLACE_ME with TTN_FP_EU868 or TTN_FP_US915
#define freqPlan TTN_FP_EU868

TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan);
TheThingsNode *node;
CayenneLPP lpp(32);

#define PORT_SETUP 1
#define PORT_MOTION 3
#define PORT_BUTTON 4

void interval()
  debugSerial.println(F("-- SEND: INTERVAL"));

void wake()

void sleep()

  // Just in case, disable all sensors
  // this couldn't hurt except time to do job

void onButtonRelease(unsigned long duration)
  uint16_t adc_value;


  debugSerial.print(F("-- SEND: BUTTON"));


void sendData(uint8_t port)
  // Read battery voltage
  uint16_t vbat = node->getBattery();


  // Just send battery voltage
  lpp.addAnalogInput(4, vbat/1000.0);
  ttn.sendBytes(lpp.getBuffer(), lpp.getSize(), port);

void setup()

  // Wait a maximum of 10s for Serial Monitor
  while (!debugSerial && millis() < 10000)

  // Config Node, Disable all sensors 
  // Check node schematics here
  node = TheThingsNode::setup();

  // Each 5 minutes
  node->configInterval(true, 300000); 

  // We monitor just button release

  // Test sensors and set LED to GREEN if it works

  debugSerial.println(F("-- TTN: STATUS"));

  debugSerial.println(F("-- TTN: JOIN"));
  ttn.join(appEui, appKey);

  debugSerial.println(F("-- SEND: SETUP"));

void loop()

Sad news, I measured current consumption, 3.2mA in sleep mode with 3 x 1.5V AA battery, what’s going on? Is there any sample sketch with real low power mode? I should have missed something.

Any tips or ideas are welcome (@BoRRoZ, @bluejedi, @ursm, @lex_ph2lb ) , I used to know perfectly how to low power a 328P but looks like for 32U4 things are different so I can’t use my ULPNode Ultra Low Power library without tweaking.

HowTo: Update RN2483 Firmware on 'The Things Node'

lets start by saying, everything (as promised by TTN) is open source and published

and that its possible to update the firmware to 1.0.3 - HowTo: Update RN2483 Firmware on 'The Things Node'



Of course I looked into, nice trick for battery measurement with mosfet :wink:

I could investigate time in looking schematics, datasheet, removing components so see where is the issue (if any), but I think the best answer could be given by designers.
What was the low power measurement done when they created The Things Node and how to achieve it?


No The Things Node here, sorry.


Forgot to mention, of course RN2483 is 1.0.3 :wink: I’m looking into 32U4 datasheet just to try


ok let’s have a look at the onboard sensors

  • MCP9804 tempsensor

  • MMA8652FC accelorometer

  • NOA1212 lightsensor

  • 32U4 processor

  • RN2483 loramodule

* will be updated / moet ff zoeken

(Remko) #12

Mine is that the node does not deliver the time the button is pressed


What do you mean. a delay?
Did you tried the code above, when I push the button, data are received in the second on TTN dashboard.


For quick reference on this post I added the schematics direct link on the 1st topic


Ok guys,

Anyone interested how to change this 3.2mA sleep mode to 280µA?

You won’t believe it, when you call sleep of the TheThingsNode library, the lib is not setting the RN2483 for sleeping, I changed that in the code and now sleep consumption is about 280µA, not the best we can do but far much better and usuable

I changed sendData() of the above sketch. You can’t do it in wake() or sleep() because wake and sleep are called on each watchdog wake (every 8s) and it would enable/disable the module each 8s. So the most efficient way, is to wake the module before send, and set it to sleep after send.

void sendData(uint8_t port)
  // Wake RN2483 

  // Read battery voltage
  uint16_t vbat = node->getBattery();

  debugSerial.print(F("Battery:\t"));  debugSerial.print(vbat);  debugSerial.println(F("mV"));

  // Just send battery voltage
  lpp.addAnalogInput(4, vbat/1000.0);
  ttn.sendBytes(lpp.getBuffer(), lpp.getSize(), port);

  // Set RN2483 to sleep mode
  // This delay is not optional, try to remove it
  // and say bye bye to your RN2483 sleep mode

I’ll do a PR of the lib, I think I can do some optimization in terms of low power.


great @Charles

i’ll try tomorrow, also I didn’t understand why didn’t they put the rn2483 in sleepmode and let it wake up the processor (like in the rocketscream node you have to)
maybe that can be done with one wire and a little software tweak, maybe even without a wire


Thnaks, Exactly what I wanted to do, sleep RN2483 and then RN2483 wake the 32U4 but I don’t know how it is possible? Would be great is RN2483 as a pin change on wake up (that we could put to an 32U4 I/O to wake it up) this would avoid us stupid watchdog wake every 8S :wink:


when the RN wakes up it always sends ok first so if you connect TX to the interrupt pin of the mcu


hey hey, TX of RN2483 is connected to RX1 of 32U4, I think I just need to set the interrupt on this pin, having played with 328P interrupts for I while, it should be possible, let me finish my pull request before :wink:


max 49 days without waking up the mcu every 8 seconds :sunglasses:


I’ve made a pull request for fix in the library, until merged, check the fixed version here

I’ve also created a new example to monitor node battery on mydevices

Next step, optimize sleep mode get get less consumption

(Remko) #26

Sorry for the confusion. The button release function in the original coude should provide the duration that the button was pressed. It now alwas says “0”. It seems as if the rise or fall is not detected correctly in processing the interrupt.

PS. I just read your comment on Github about this issue.


// If button pressed, send press duration
// please myDeviceCayenne add counter value type to
// avoid us using analog values to send counters

yep :rofl:


congrats to @Charles… you nailed it !


Thansk @BoRRoZ but still too much for me, got some other ideas, if you have time to help for measurement I’m your man, I’ll take care of Low Power Code optimization

What about trying with sensors enabled? Would you mind trying CayenneLPP.ino just to see?