Reading the battery voltage of the supply battery


As the MKR1300 is designed to run on battery, it conveniently includes a voltage divider on board attached to PB08 with a 680k/330k so it should be measurable against the internal 1v ref.

However if you try

int sensorValue = analogRead(ADC_BATTERY);

It fails as ADC_BATTERY is undefined.

Is there a declared variable (in MKRWAN.h) that lets me read the PB08 value or an equivalent?

It seems reducndant to have to add another resister divider to A0 or A1 when it is built in.


I needed the same thing and I did not know how, however your code is functioning for me (thanks!). Do you have everything up to date? ADC_BATTERY seems equal to 32 (tried analogRead(32) and gives the same result).

Hi NeilE, you need to include pins_arduino.h

#include <pins_arduino.h>

Thanks MITEL and sslupsky, it works fine now.

I just wanted to clarifiy the reading. As the VBATT input is divided with a 680K/330K pair it is using the internal 1.1V reference value to measure against so i need to scale up the result. x 3.3 as per the code examples.

I read elsewhere the the 1.1 ref is not that accurate so in the end i measured VBATT with a multimeter and added a scale up factor to give me a genuine VBATT. In real terms this was about 2.93 to get a match rather than 3.3.

Is my thinking correct here?

I am trying to figure out which reference to use, to be declared with analogReference(type). In fact, without any analogReference declaration (this means default reference=3.3V), I am measuring 300 and something for 2 AA batteries. This would be about 1.1V vs. the reference, then multiplied by 3 for the real battery voltage. However, I am not able to understand how stable is the default reference if it is provided by the battery. Better a lower one? Looking here: , it seems there is no INTERNAL1V1 reference on MKR WAN , just AR_INTERNAL1V0, but this would be too low to compare with the 1.1 expected. Thus I am using AR_INTERNAL1V65, and scaling according to it. It is below minimum voltage, so it should be always usable. (and all of this without considering errors).

By the way, I did not have to include pins_arduino.h (it is already included somewhere in the core).

Follow-up on this: I thought again at reference, and as suggested in a different thread for MKRFOX 1200 , I went back to the 1.0V version. For my needs, that is, communicate when battery is almost depleted, it does not matter if voltages greater than 3V are reported as 100%. By the way, here there is also the implementation of references, and likely all depend on 3V3 except 1.0 (if I understood well).

Thanks MITEL, I agree with your point about ref voltages. 1V0 seems to be a good reference point.

WRT to battery levels, since we are all struggling with sleep consumption I was trying to track the decay from the cells (I am using 'C' cells for longevity at the moment) in order to predict battery life with the 1.15mA sleep consumption.

With that in mind, I can't find a minimum working VBATT specified anywhere. Do you know what the minimum working voltage is? I saw elsewhere the SAMD can run at 2V, but I suspect the Murata ship won't transmit at this level.

NeilE: With that in mind, I can't find a minimum working VBATT specified anywhere. Do you know what the minimum working voltage is? I saw elsewhere the SAMD can run at 2V, but I suspect the Murata ship won't transmit at this level.

In the Murata data sheet you can find 2.2-3.6V as voltage range, but 2.4V minimum if transmitting at 20Dbm. The latter case should not occur - I think- when using it as a node in EU. By the way, thanks for having reminded this, it is useful for me too (I was considering 1.8, which is not correct at this point).

Hi Mitel, do you know if the transmitter actually puts out 20 dBm at Vcc = 2.4V?

Also, is the receive sensitivity is affected by lower supply voltage? The specification only provides data for Vcc = 3.3V.

Sslupsky, sorry but I do not know. From how is written, it seems like it outputs 20dDm from 2.4V, but who knows. Regarding sensitivity, I am curious too. I have a Rpi + Dragino that often shows the undervoltage sign, and I hope it is not influencing sensitivity...

try this:

float battery_voltage = 3.01; // use voltmeter

  analogReference(AR_INTERNAL1V0); //AR_DEFAULT: the default analog reference of 3.3V // 
AR_INTERNAL1V0: a built-in 1.0V reference
  // read the input on analog pin 0:
  int sensorValue = analogRead(ADC_BATTERY);
  // Convert the analog reading (which goes from 0 - 1023) 
  float voltage = sensorValue * (battery_voltage / 1023.0);
  // print out the value you read:
  Serial.print("Voltage: ");

  float battery_percentage = ((voltage * 100) / battery_voltage);

  Serial.print("Batery Percentage: ");