XIAO Sense - charging a LiPo battery

The XIAO Sense has at the bottom of the board connectors for a LiPO battery.

I connected a 3.7V LiPo battery, but its been only discharging.

Problem - How can I charge the battery?
The example: Motion Recognition has no code for charging or measurement of battery voltage

The Example Getting started - charging throws an error that HiCHG is not defined

So I need to know how to

  • Measure the battery voltage
  • Switch to charging when the battery level is low and the unit is connected to USB
  • Switch off/low power consumption when the battery level is low
  • Enable the actual functions when not connected to USB and the battery level is high
  • Do all this above using the IMU and BLE (Other posts indicate that measuring voltage drops BLE)

For a board that provides all of the above without any extensions that is IMHO not an unreasonable request and the existing documentation seems to lack vital information.

while on this subject i think seeed has the positive and negitive side of the charging port backwards on XIAO Expansion board, every 3.7v lipo i try to use has opposite connector

currently i have a sky viper lipo from a drone i want to use, but the connector male with flat on bottom pressing toward female connector is red on right

on XIOA this appears to be oppositly wrong

please check and let us know what battery this will work with

also please let us know which battery for RTC

Hi there,
I am not using the expansion board. I wire a DK 3.7V 380mAh LiPo battery directly to the contacts on the underside of the XIAO Sense.

1 Like

i dont think any of this functionality is available on the chip alone

only low power mode which is a software capability

I would like to have these functions included in expansion board
currently i believe only charging an d discharging of battery is capable by way of expansion board charging chip

Hi Christopher,

the example: Motion Recognition shows exactly this scenario of a direct connection of the LiPo battery to XIAO.

My only question there would be why connect the display to the XIAO GND and 3.3V outputs and not the battery directly and avoid routing currents through the chip with power loss. If you power your circuit through USB that makes sense, but in my envisioned design USB is for charging only.

Ignore the incomplete XIAO example. Just connect the battery to the pins at the bottom. I charge my LiPo when connected, and the app runs when unplugged.

To measure the battery voltage, I use the code below which matches my volt meter.

void loop () {

const double vRef = 3.3;
const unsigned int numReadings = 1024;
unsigned int adcCount = analogRead(PIN_VBAT);
double batteryVoltage = (adcCount * vRef) / numReadings;

Hi @aknoefel ,

I am using your code to read the battery voltage.
But it only works if I use the USB voltage in addition to the 2x AA battery.
That means, if both voltages are present, the battery voltage is read out correctly (currently approx. 2.90 volts), but if I remove the USB voltage, then approx. 3.2 volts are measured.
Am I doing something wrong?

This is my code:

void ManageBattery() {
  batvalue = analogRead(PIN_VBAT);
  voltage = (batvalue * 3.3) / 1024;
  if (voltage < 2.80) {
    //Power-Led Blinken lassen
    if ((millis() - lastblink) > 250){
      digitalWrite(pbPwLed, !digitalRead(pbPwLed)); // LED wird ein- bzw. ausgeschaltet
      lastblink = millis();
    digitalWrite(pbPwLed, HIGH);  // turn ON the LED
  Serial.print("Input Voltage = ");

Disclaimer: I am not an expert, just sharing my experiences

A few comments:

  1. I am using a LiPo battery, not 2x AA batteries as a power source
  2. I measured the actual voltage against the code when NOT connected to USB, and it’s close enough for my purposes. You may have to adjust your multiplier from “3.3” to match the ADC readings with your volt meter
  3. I also noticed that when ALSO connected to USB, the voltage at the battery connectors is higher.

Should not connect any non-lipo batteries to the battery terminals.

In short: the XIAO BLE has a lipo-charger circuit. When it detects a lipo connected and the lipo level is at least (about) 50-150mV below the charging voltage (4.2V) it will start charging with around 4.2V.

Turning pin 22 to OUTPUT and LOW in the code will increase charging from about 30-50mA to 80-100mA. Make sure you battery is rated at that. Most run of the mill lipo batteries are chargeable at 1C only. But safer at 0.5C. The C is the factory ampere rating of the battery. So a 200mA lipo can be safely charged at 200mA.


Can you please share a code for XIAO BLE SENSE BATTERY CHARGING?
Also, how do i make sure that the battery voltages can be read to make sure i know what the battery voltage is, is there a code for that also?

Appreciate your help…

There are several codes posted already. This is from one of those. I just added USB detection to it. Extracted from long code, you may need to tweak it… Careful with fixing long comment lines wrap around, if you copy it or will not compile!

//only for version 1.0 of XIAO BLE SENSE
//main codes are from posts at the XIAO forum
//added USB detection codes

#include <Arduino.h>

#define BAT_READ 14            // P0_14 = 14  Reads battery voltage from divider on signal board. (PIN_VBAT is reading voltage divider on XIAO and is program pin 32 / or P0.31)
#define CHARGE_LED 23          // P0_17 = 17  D23   YELLOW CHARGE LED
#define HICHG 22               // P0_13 = 13  D22   Charge-select pin for Lipo for 100 mA instead of default 50mA charge

const double vRef = 3.3; // Assumes 3.3V regulator output is ADC reference voltage
const unsigned int numReadings = 1024; // 10-bit ADC readings 0-1023, so the factor is 1024

volatile int BAT_CHRG; //is the battery connected and charging?   5V connected/charging = 0; disconnected = 1

void setup() {
  // put your setup code here, to run once:


  pinMode (CHARGE_LED, INPUT);  //sets to detetct if charge LED is on or off to see if USB is plugged in
  pinMode (HICHG, OUTPUT);  digitalWrite(HICHG, LOW);  //100 mA charging current if set to LOW and 50mA (actually about 20mA) if set to HIGH
  pinMode(BAT_READ, OUTPUT);  digitalWrite(BAT_READ, LOW);// This is pin P0_14 = 14 and by pullling low to GND it provices path to read on pin 32 (P0,31) PIN_VBAT the voltage from divider on XIAO board

    printf("\nBattery Test compiled by davekw7x on %s at %s\n",   __DATE__, __TIME__);
    printf("Note: PIN_VBAT = %u\n\n", PIN_VBAT);

///////////////////////////////////////////////////////////////////////READ LIPO BATTERY////////////////////////////////////////////////////////////////
void readBAT()  {
  unsigned int adcCount = analogRead(PIN_VBAT);//  PIN_VBAT is reading voltage divider on XIAO and is program pin 32 or P0.31??
  double adcVoltage = (adcCount * vRef) / numReadings;
  double vBat = adcVoltage * 1675.0 / 510.0; // Voltage divider from Vbat to ADC  // was set at 1510.0...set your own value to calibrate to actual voltage reading by your voltmeeter
  printf("adcCount = %3u = 0x%03X, adcVoltage = %.3fV, vBat = %.3f\n", adcCount, adcCount, adcVoltage, vBat);

///////////////////////////////////////////////////////////////////////END OF READ LIPO BATTERY////////////////////////////////////////////////////////////////

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

  BAT_CHRG = digitalRead(CHARGE_LED);  //

  if (BAT_CHRG == 1)  {  //if USB/charger IS NOT plugged in

    // Serial.print("  Battery Charge status =  "); Serial.println(BAT_CHRG);
    Serial.println(" USB -IS NOT- plugged in ");     //do whatever you want here once USB is detected, in order to make sure user knows that battery-read values are now USB-generate

  if (BAT_CHRG == 0) {   ////if USB/charger IS plugged in
     // Serial.print("  Battery Charge status =  "); Serial.println(BAT_CHRG);
     Serial.println(" USB -IS- plugged in ");     //do whatever you want here once USB is detected, in order to make sure user knows that battery-read values are now USB-generated
  readBAT();   // loops back to lipo BAT read routine
  delay(5000);//delays 5 sec betwen battery readings