XIAO nrf52840 battery voltage not readable on PlatformIO

Hey community!

I can’t get a voltage reading from PIN_VBAT in PlatformIO no matter what. However it’s working just fine in the Arduino IDE… I already isolated the problem and created two minimal repro projects.
I’m using the XIAO nrf52840 v1.0

Working Arduino project:
ReadBattery.ino

#include "Adafruit_TinyUSB.h"

#define VREF 3.6
#define ADC_MAX 4096

void setup() {
  analogReadResolution(ADC_RESOLUTION);
  pinMode(PIN_VBAT, INPUT);
  pinMode(VBAT_ENABLE, OUTPUT);
  digitalWrite(VBAT_ENABLE, LOW);
}

void loop() {
  Serial.print("V Bat: ");
  Serial.println(getBatteryVoltage());
}

float getBatteryVoltage() {
  unsigned int adcCount = analogRead(PIN_VBAT);
  float adcVoltage = adcCount * VREF / ADC_MAX;
  return adcVoltage * 1510 / 510;
}

Non-working PlatformIO project:
platformio.ini

[env]
platform = https://github.com/maxgerhardt/platform-nordicnrf52

[env:xiaoble]
board = xiaoble
framework = arduino
monitor_speed = 115200

main.cpp

#include <Arduino.h>

#define VBAT_ENABLE 14 <-- not auto-defined in PlatformIO
#define VREF 3.6
#define ADC_MAX 4096

float getBatteryVoltage();

void setup() {
  analogReadResolution(ADC_RESOLUTION);
  pinMode(PIN_VBAT, INPUT);
  pinMode(VBAT_ENABLE, OUTPUT);
  digitalWrite(VBAT_ENABLE, LOW);
}

void loop() {
  Serial.print("V Bat: ");
  Serial.println(getBatteryVoltage());
}

float getBatteryVoltage() {
  unsigned int adcCount = analogRead(PIN_VBAT);
  float adcVoltage = adcCount * VREF / ADC_MAX;
  return adcVoltage * 1510 / 510;
}

As you can see there is no native support for the XIAO nrf52840 by PlatformIO, so I have to use the community implementation.
The issue arose from a ported Arduino project, everything ported fine except the battery monitoring. In the analogRead(PIN_VBAT) I only get 4095 as a result no matter what.

As I checked out the schematics I also saw that PIN_VBAT is marked as P0.31_AIN7_BAT which indicates pin 31, but in Arduino and PlatformIO PIN_VBAT is defined as 32.
I only find that strange and don’t understand it, but it still works on Arduino, so thats fine I guess.
I don’t have the expert knowladge to determine which parts may cause this behaviour on PlatformIO, all I did to this point is to compare all #defines if they are the same and I can say that they all match.

Hope someone can help me, since I already wasted my whole Sunday on this!

Greetings from Germany,
Nils Ole

I don’t see this sin your sketch?
analogReadResolution(12); //12bits
my 02
HTH
GL :non-potable_water:

Hey Glasso,

thx for the suggestion! But analogReadResolution(ADC_RESOLUTION); does exactly that. ADC_RESOLUTION seems to be a default define that evaluates to 12.

Maybe somone else has a suggestion? Its a basic sketch, so the issue probably has to be some config stuff that I know nothing about?

Best,
Nils Ole

Ah’ I didn’t see it…LOL ok well here is my .ini that works from this topic.

https://forum.seeedstudio.com/t/upload-working-great-in-arduino-no-device-found-on-com5-error-in-platformio/267696/7?u=pj_glasso

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:xiaoblesense]
platform = https://github.com/maxgerhardt/platform-nordicnrf52
board = xiaoblesense
framework = arduino
debug_tool = jlink

lib_extra_dirs = ~/Documents/Arduino/libraries
lib_deps = seeed-studio/Seeed Arduino LSM6DS3@^2.0.3
   arduino-libraries/ArduinoBLE@^1.3.2
   ;adafruit/Adafruit GFX Library
   adafruit/Adafruit BusIO
   Wire
   olikraus/U8g2@^2.34.4
   ;SPI

HTH
GL :-p

Thank you for providing your ini!
I tested it, but unfortunately got the same result: analogRead(PIN_VBAT) still reads 4095 :frowning:

Also I’m using the base nrf52840 not the sense, but it was worth a try. Also my board version is 1.0 instead of 1.1 for any future readers.

I stumbled upon this thread because I was having a similar issue. The issue with with the mbed framework. I’ll let this thread where speak for itself: XIAO_BLE_Sense(mbed 2.7.2) battery charge and voltage monitor, analogRead(P0_31) does not work - #2 by JeonLab

Actually, VBAT_ENABLE is defined in PlatformIO, it’s just called PIN_LSM6DS3TR_C_POWER (intuitive, I know). There’s also a pin for reading charge status, PIN_LSM6DS3TR_C_INT1. These are defined in something like “.platformio\packages\framework-arduino-mbed\variants\SEEED_XIAO_NRF52840_SENSE\pins_arduinio.h”:

#define PIN_VBAT (32u)
...
#define PIN_LSM6DS3TR_C_POWER (14u)
#define PIN_LSM6DS3TR_C_INT1 (17u)

The fun thing is, all of them except PIN_VBAT don’t work. The other forum thread explains it in detail but basically the integer value of the pins is not the same as their label (P0.14 =/= 14). My solution is to replace them with the proper value corresponding to an index from variant.cpp in the same folder:

#define VBAT_ENABLE (31u) // digital output: battery voltage enable
#define VBAT_CHG (22u) // digital input: charging status

Copy the above snippet into your code and you should be good to go.