Battery Monitor Question

In the example sketch BatteryMonitor a comment reads

Read the current voltage level on the A0 analog input pin.
This is used here to simulate the charge level of a battery.

I realise that a lot has been asked and answered regarding this topic, but what eactly does the above comment mean? Is the voltage on pin A0 just a random voltage used to test the sketch is working, or is it an indication of the charge of the battery?

I am using a Nano 33 BLE Sense to transmit data over BLE. This Nano is powered by a (4.5v) battery connected to the USB port. I would like to be able to read the charge left in the battery and give a warning when the battery needs changing. How can I fairly accurately measure the battery's charge, or is A0 good enough?

You'd need to show the full context - give a link.

It sounds like that example - because it's just an example - is not actually reading the battery voltage, but just reading something else that is being used to simulate a battery voltage.

Maybe it's just reading a potentiometer?

What kind of battery is it?

Terminal voltage is a very poor indicator of remaining charge - especially for Lithium-based batteries.

To do that, you really need a so-called "Gas Gauge" or "Coulomb Counter" chip.

That depends on what you have connected to A0!

It can certainly be used to measure the battery voltage, and that could certainly tell you when it's "nearly dead" - which may be sufficient for your application?

Similar thread earlier today:

It's a common topic - try a forum search ...

Like most threads on this topic the thread you link to is just of people asking the OP for more information and then being silent when the information they asked for is given. I actually specified the Arduino type and battery voltage (actually three AAA batteries). Not much actual information on reading battery charge in the forum, which is probably why the question is asked so often.

And you also need to supply more information:

  • A link to the example you mentioned

  • You didn't say what type of battery - just that it was "4.5V";
    the size - AAA - also doesn't tell us what type it is.

I think they probably mean that the voltage on A0 is used to simulate the terminal voltage of the battery.

Does that example not come with a schematic showing what it expects to be wired to A0?

Here is the sketch copied from the IDE example sketches.

/*
  Battery Monitor

  This example creates a Bluetooth® Low Energy peripheral with the standard battery service and
  level characteristic. The A0 pin is used to calculate the battery level.

  The circuit:
  - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
    Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.

  You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
  nRF Connect (Android), to interact with the services and characteristics
  created in this sketch.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>

 // Bluetooth® Low Energy Battery Service
BLEService batteryService("180F");

// Bluetooth® Low Energy Battery Level Characteristic
BLEUnsignedCharCharacteristic batteryLevelChar("2A19",  // standard 16-bit characteristic UUID
    BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes

int oldBatteryLevel = 0;  // last battery level reading from analog input
long previousMillis = 0;  // last time the battery level was checked, in ms

void setup() {
  Serial.begin(9600);    // initialize serial communication
  while (!Serial);

  pinMode(LED_BUILTIN, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");

    while (1);
  }

  /* Set a local name for the Bluetooth® Low Energy device
     This name will appear in advertising packets
     and can be used by remote devices to identify this Bluetooth® Low Energy device
     The name can be changed but maybe be truncated based on space left in advertisement packet
  */
  BLE.setLocalName("BatteryMonitor");
  BLE.setAdvertisedService(batteryService); // add the service UUID
  batteryService.addCharacteristic(batteryLevelChar); // add the battery level characteristic
  BLE.addService(batteryService); // Add the battery service
  batteryLevelChar.writeValue(oldBatteryLevel); // set initial value for this characteristic

  /* Start advertising Bluetooth® Low Energy.  It will start continuously transmitting Bluetooth® Low Energy
     advertising packets and will be visible to remote Bluetooth® Low Energy central devices
     until it receives a new connection */

  // start advertising
  BLE.advertise();

  Serial.println("Bluetooth® device active, waiting for connections...");
}

void loop() {
  // wait for a Bluetooth® Low Energy central
  BLEDevice central = BLE.central();

  // if a central is connected to the peripheral:
  if (central) {
    Serial.print("Connected to central: ");
    // print the central's BT address:
    Serial.println(central.address());
    // turn on the LED to indicate the connection:
    digitalWrite(LED_BUILTIN, HIGH);

    // check the battery level every 200ms
    // while the central is connected:
    while (central.connected()) {
      long currentMillis = millis();
      // if 200ms have passed, check the battery level:
      if (currentMillis - previousMillis >= 200) {
        previousMillis = currentMillis;
        updateBatteryLevel();
      }
    }
    // when the central disconnects, turn off the LED:
    digitalWrite(LED_BUILTIN, LOW);
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
}

void updateBatteryLevel() {
  /* Read the current voltage level on the A0 analog input pin.
     This is used here to simulate the charge level of a battery.
  */
  int battery = analogRead(A0);
  int batteryLevel = map(battery, 0, 1023, 0, 100);

  if (batteryLevel != oldBatteryLevel) {      // if the battery level has changed
    Serial.print("Battery Level % is now: "); // print it
    Serial.println(batteryLevel);
    batteryLevelChar.writeValue(batteryLevel);  // and update the battery level characteristic
    oldBatteryLevel = batteryLevel;           // save the level for next comparison
  }
}

The batteries are the usual AAA alkaline batteries sold everywhere

No.

How very unhelpful of it.

Unfortunately, not untypical.

:roll_eyes:

As it says, its purpose is to demonstrate the standard BLE 'Battery' Service.
You don't need an actual battery to do that, so I guess it's just using any analogue input for the sake of some data - any data - to send.

It could equally have used a random number generator, or a lookup table of some test data.

AAA just tells the size - you can also get zinc-carbon, NiMH, NiCd, etc in AAA size.

You can even get lithium in AAA size:

image

https://cpc.farnell.com/gp-batteries/gppcl24lf000/battery-lithium-aaa-2pk

I guess you missed the "alkaline" in the sentence you quoted.

I can see this thread is going the way of all the others on this topic. Just requests for further information and then pick on a minor detail and expand on that rather than tackle the original question which was "How can I fairly accurately measure the battery's charge?

1 Like

I guess you missed the "also" in my reply?

See post #2.

If your serious about this then forget that useless tutorial and get a "Coulomb Counter" chip as suggested.

2 Likes

Yes I guess I will. But having forked out good money for the state-of-the-art Nano 33 BLE sense which is full of sensors of every kind (temp, humidity, pressure, gesture, motion etc.), I guess I was too optimistic expecting that it would be able to monitor its own battery level.

Again, it depends on what, exactly, you mean by "monitor its own battery level":

Now that we know you're using alkaline batteries, they have a discharge characteristic something like this:

image

Source: https://www.ti.com/lit/an/slva194/slva194.pdf

So you should be able to get something a bit better than just, "nearly dead" ...

1 Like

What is the minimum voltage your MCU can operate at safely?
That, + about 50mV should be your "low batt" warning level.

1 Like

That depends on what you want the "low batt" warning to indicate...

"Battery University" has a lot of good info; eg,

1 Like

Possibly because you made people drag the details out of you.

You could use a voltage divider to an analog pin, that'll just give you the current voltage. How accurate do you want/need this to be?

2 Likes

The datasheet of the board's processor will tell you the minimum voltage for the clock speed used. By low batt warning, I mean the voltage at which the batts must be replaced or charged before errors or data loss occurs.

1 Like

You got it, also the board needs a fixed ADC reference voltage below the minimum voltage level.