MKRFOX1200 read battery voltage

Hi guys,

I saw on this page that it's possible to read battery voltage on the MKRZERO board with few lines of code :

  /*
  ReadBatteryVoltage
  Reads the analog input connected to the battery output on a MKRZero or MKR1000, converts it to voltage, and prints the result to the serial monitor.
  Graphical representation is available using serial plotter (Tools > Serial Plotter menu)

  This example code is in the public domain.
*/

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(ADC_BATTERY);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 4.3V):
  float voltage = sensorValue * (4.3 / 1023.0);
  // print out the value you read:
  Serial.print(voltage);
  Serial.println("V");
}

I tried to put this code in the MKRFOX1200 but the value returned are weird.
I've modified the formula by replacing 4.3 with 3.3 but same problem.

Do you know if it's possible to read battery voltage on this board ?

This one works:

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5 / 1023.0);
// print out the value you read:
Serial.print(voltage);
}

Did you check the constant ADC_BATTERY ?

Thanks for your answer ManfredDoetsch, i will check it in my next code upload.

Hi,

I've uploaded ManfredDoetsch code in my board but it doesn't seem to work as expected.
Here is a historical view of the voltage value since may 25 :

Do you have any idea ?

Have you advance on the function to read the battery life, I have a similar project.

For the mkrfox1200 maximun input 3.3v

Warning: Unlike most Arduino & Genuino boards, the MKRFOX1200 runs at 3.3V. The maximum voltage that the I/O pins can tolerate is 3.3V. Applying voltages higher than 3.3V to any I/O pin could damage the board. While output to 5V digital devices is possible, bidirectional communication with 5V devices needs proper level shifting.

Anyone got a solution to reliably read the battery voltage on a MKRFOX1200?
It is a must-have feature for my project.

In order to have an accurate battery measurement you need to compare the battery voltage to a reference voltage.
The MKRFOX1200 has an internal reference voltage of 1V.
The ADC_Battery pin is connected to a resistor network that divides the battery voltage. So in case the battery voltage is 3.3V, the voltage at battery equals 1V. You need to tell the ADC to compare the ADC_Battery with the internal reference voltage of 1V. I believe this can be done using the analogReference() instruction.

I have a project, where I also have to read the battery level, and I use the analogReference(), and it works fine....but I also have to use another analog pin to measure a distance, but that don't work when I use the analogReference().
What to do ?

Based on this thread.

void loop() {

  analogReadResolution(10);
  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) to a voltage (0 - 4.3V):
  float voltage = sensorValue * (3.25 / 1023.0);
  // print out the value you read:
  Serial.print(voltage);
  Serial.println("V");

}

Result: 3.25 volts for 3.25 volts battery

:wink:

Hi,
this code isn´t functioning for me.
Code resault is 4.3V and battery has exactly 3.51V
Whats is wrong?

I have MKRFOX1200 + 3.7V LiPo battery

Hi, I tried the code pasted above but didn't work for me.

I started measuring differents batteries, and I founded that analogRead(ADC_BATTERY) instruction give directly the voltage *100, I don't know the reason.

Due the measurement error (arduino or multimeter), I made an average and my correction factor is 103.06.

You don't need to change the analog resolution or the analog reference, all these values are by default.

I paste my code

in void loop

// read the battery:
int battread = analogRead(ADC_BATTERY);
// convert to a voltage:
float voltbatt = (battread / 103.06);

Opening an old topic.
There is something I can't explain when trying to measure the battery voltage from any battery on the MKRFox1200.
My code:

  analogReadResolution(12);//12bits
  analogReference(AR_INTERNAL1V65);

in the setup

and the following to perform the measurement

  // read the input on analog pin:
  int sensorValue = analogRead(ADC_BATTERY);
    float voltage = sensorValue * 0.1233211; //voltage in 1/100 Volt, 300 means 3.00V
  //(165 / 4095)  / (33/(68+33))

I rewrote all the code:

  • 12 bits resolution
  • Use reference AR_INTERNAL1V65. From the schematics, the ratio Input Voltage / Battery Voltage = (33/(68+33) = 0.326732673. This means that the battery voltage can be up to 1.65/0.326732673=5.05V. Above this value the input will saturate. Below this value everything will be fine
  • One bit represents (1.65/0.326732673)/(2^12-1)=0.001233211 Volt at the battery.

I don't know what I am doing wrong I always get a value close to 3.3V in the whole battery life. It sounds to me that the voltage divider is done at the voltage regulator output and not at the input as represented in the schematics.

I investigated further and I found something very interesting. It seems that the voltage read function only works when 5V power supply voltage is present on the micro USB port. This is unfortunate since the battery level is mainly important if the power source is a battery.

I tried this simple sketch:

void setup() {
  // put your setup code here, to run once:
  analogReadResolution(12);//12bits
  analogReference(AR_INTERNAL1V65);
  Serial1.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:

  int sensorValue = analogRead(ADC_BATTERY);
    float voltage = sensorValue * 0.00123321123; //voltage in 1/100 Volt, 300 means 3.00V
  //(165 / 4095)  / (33/(68+33))

  Serial1.print("Battery Voltage(V): ");
  Serial1.println(voltage);
  delay(100);
}

It should output the battery voltage on Serial1 whose Tx is pin 14 and not the micro USB port.
I used an adjustable power voltage applied on the battery terminal and observed the following behavior:

  • When the micro USB port is disconnected, the output is always around 3.3V whatever the input between 3V and 3.4V.
  • As soon as I connect the micro USB to a computer or just a 5V power supply then the output is correct and reflects the input value.
  • If I try to disconnect the USB then the value goes up to 4.35V and remains around this value.

So my conclusion is that we can read the battery voltage only if the MKRFox1200 is powered via USB.
I'd like to see other people doing the same test to figure out if this is a general problem or only my module that is defective.

Hi everyone, I tried the jot4p code and it worked.
To check what etimou says that it only works if it is connected by usb, I powered the MKRFOX1200 with two AA (3V) batteries without USB and uploaded the result to Sigfox and it kept giving correct values.

Greetings to all.

hi! What do you mean by correct values?
Are you getting values that are close to 3V? and not always 3.3V as I observed?

Hello.
I am really feeding with a power supply with which I can change the voltage if I give it 3V it gives me 3V if it goes down to 2.9V it gives me 2.9V, so I think it is giving the correct values.

Regards.

This is absolutely what it should do. I don't know what I am doing wrong. I tested with a second unit and I got the same problem. Always getting 3.3V when powered from the screw terminal. Is it possible that I have two faulty modules? Or that I did something that damaged them and cause this malfunction?

ok, working better with the 1.1V analog reference.
Now I can see some fluctuation but I am wondering how we shall calculate the theoretical multiplier.

voltage = (1.1/(2^10-1))*(68+33)/33 * analogRead(ADC_BATTERY)

Is it correct?

Since it really is powered by 3v I change

"float voltage = sensorValue * (3.25 / 1023.0);"

by

"float voltage = sensorValue * ( 3/ 1023.0);"