How to get batter level in a Artemis Thing Plus

Hi, I have the following setup:

  1. SparkFun Artemis Thing Plus

https://www.sparkfun.com/products/15574

1.1 3.7V 522332 400mAh Lipo battery Rechargeable Lithium Polymer ion Battery Pack with PH2.0mm JST Connector

https://www.amazon.com/Battery-Recharge … B07BTWMM8H

  1. SparkFun Photodetector Breakout - MAX30101 (Qwiic)

https://www.sparkfun.com/products/16474

  1. SparkFun Micro OLED Breakout (Qwiic)

https://www.sparkfun.com/products/22495

The Artemis Thing Plus is the main board, the Lipo battery is connected to the JST connector, and it works perfectly. The MAX30101 is a light sensor, and the Micro OLED Breakout is the display. All parts work beautifully together, BUT now I want to add to my code to read the battery level. The battery works perfectly for ours, and it is charged via USB-C.

I want to see the battery level percentage displayed on my OLED.

This is my current code:

#include <SFE_MicroOLED.h>
#include <Wire.h>

#include "MAX30105.h"

#define PIN_RESET 9
#define DC_JUMPER 1

MAX30105 particleSensor;
MicroOLED oled(PIN_RESET, DC_JUMPER);

long unblockedValue;  // Average IR at power up

String multiplyChar(char c, int n) {
  String result = "";
  for (int i = 0; i < n; i++) {
    result += c;
  }
  return result;
}

void displayMeasurement(int rLevel) {
  oled.clear(PAGE);
  oled.setCursor(0, 0);

  int calibratedReading = f(rLevel);
  int centerPadding = 4 - String(calibratedReading).length();
  String paddingText = multiplyChar(' ', centerPadding);

  if (rLevel == 0) {
    oled.setFontType(1);
    oled.print("Please load   sample!");
    oled.display();
    return;
  }

  oled.setFontType(3);
  oled.print(paddingText);
  oled.print(calibratedReading);

  Serial.println("real:" + String(rLevel));
  Serial.println("agtron:" + String(calibratedReading));
  Serial.println("===========================");

  oled.display();
}

int f(int x) {
  int intersectionPoint = 117;
  float deviation = 0.165;

  return round(x - (intersectionPoint - x) * deviation);
}

void setup() {
  Serial.begin(9600);

  Wire.begin();
  oled.begin();      // Initialize the OLED
  oled.clear(ALL);   // Clear the display's internal memory
  oled.clear(PAGE);  // Clear the buffer.

  delay(100);  // Delay 100 ms
  oled.setFontType(3);

  // Initialize sensor
  if (particleSensor.begin(Wire, I2C_SPEED_FAST) == false)  // Use default I2C port, 400kHz speed
  {
    Serial.println("MAX30105 was not found. Please check wiring/power. ");
    while (1)
      ;
  }

  // The variable below calibrates the LED output on your hardware.
  byte ledBrightness = 135;

  byte sampleAverage = 4;  // Options: 1, 2, 4, 8, 16, --32--
  byte ledMode = 2;        // Options: 1 = Red only, --2 = Red + IR--, 3 = Red + IR + Green
  int sampleRate = 50;     // Options: 50, 100, 200, 400, 800, 1000, 1600, --3200--
  int pulseWidth = 411;    // Options: 69, 118, 215, --411--
  int adcRange = 16384;    // Options: 2048, --4096--, 8192, 16384

  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);  // Configure sensor with these settings

  particleSensor.setPulseAmplitudeRed(0);
  particleSensor.setPulseAmplitudeGreen(0);

  particleSensor.disableSlots();
  particleSensor.enableSlot(2, 0x02);  // Enable only SLOT_IR_LED = 0x02

  // Update to ignore readings under 30.000
  unblockedValue = 30000;
}

void loop() {
  int rLevel = particleSensor.getIR();
  long currentDelta = rLevel - unblockedValue;

  if (currentDelta > (long)100) {
    displayMeasurement(rLevel / 1000);
  } else {
    displayMeasurement(0);
  }
  delay(100);
}

Please, anything would help. I’ve read about this, but I’m unsure how to proceed. If it helps, forget about what the light sensor does. I want to be able to display the battery level percentage.

you will need to connect the VBAT pin to one of the ADC pins with a voltage divider. The ADC can only handle up to 2V reference. So make a voltage divider with 2 x 100K resistors and take the middle point to the ADC pin. Take the result you read with analogRead() and multiply by 2: ((analogRead(PIN) * 2 ) / 1023) * 2 = Battery Voltage. You can then add that to your OLED output.

Hi Paul - Thanks for the reply. Would you happen to know where the ADC pins are located in the Artemis thing plus? Thank you.

Josue

It says on the board A0 to A5…

Hi Paul,

Thank you for your advice, I’m having a problem because my code is not reading any changes from the battery; I would like to check something with you first.

I connected the VBAT pin to the ADC A0 pin with a voltage divider , 2 x 100K resistors.

Then, I took the middle point to A0 and the end to the GND pin.

So it looks like:

  1. VBAT

  2. Middle point - A0

  3. GND

Is that correct? Please let me know what you think.

Josue

that is what I would do.

What results do you get?

what sketch are you using ?

All I get on my display is “Bat: 0%” and it doesn’t move from that.

Here is my code:

#include <SFE_MicroOLED.h>

#include <Wire.h>

#include “MAX30105.h”

#define PIN_RESET 9

#define DC_JUMPER 1

MAX30105 particleSensor;

MicroOLED oled(PIN_RESET, DC_JUMPER);

long unblockedValue; // Average IR at power up

// Battery reading setup

const int BATTERY_PIN = A0; // ADC pin connected to battery voltage

const float FULL_BATTERY_VOLTAGE = 4.2; // Full charge voltage

const float EMPTY_BATTERY_VOLTAGE = 2.75; // Cut-off voltage

const float MAX_ADC_READING = 1023.0;

const float ADC_REFERENCE_VOLTAGE = 3.3; // Assuming the reference voltage is 3.3V

String multiplyChar(char c, int n) {

String result = “”;

for (int i = 0; i < n; i++) {

result += c;

}

return result;

}

float readBatteryVoltage() {

float adcValue = analogRead(BATTERY_PIN);

float batteryVoltage = (adcValue / MAX_ADC_READING) * ADC_REFERENCE_VOLTAGE * 2.0; // Adjust for voltage divider

return batteryVoltage;

}

int mapBatteryToPercentage(float voltage) {

voltage = constrain(voltage, EMPTY_BATTERY_VOLTAGE, FULL_BATTERY_VOLTAGE);

return (int)((voltage - EMPTY_BATTERY_VOLTAGE) / (FULL_BATTERY_VOLTAGE - EMPTY_BATTERY_VOLTAGE) * 100);

}

void displayBatteryPercentage(int percentage) {

oled.setFontType(0);

oled.print("Bat: ");

oled.print(percentage);

oled.print(“%”);

}

void displayMeasurement(int rLevel) {

oled.clear(PAGE);

oled.setCursor(0, 0);

if (rLevel == 0) {

oled.setFontType(1);

oled.print(“Load sample!”);

float batteryVoltage = readBatteryVoltage();

int batteryPercentage = mapBatteryToPercentage(batteryVoltage);

displayBatteryPercentage(batteryPercentage);

oled.display();

return;

}

int calibratedReading = f(rLevel);

int centerPadding = 4 - String(calibratedReading).length();

String paddingText = multiplyChar(’ ', centerPadding);

oled.setFontType(3);

oled.print(paddingText);

oled.print(calibratedReading);

Serial.println(“real:” + String(rLevel));

Serial.println(“agtron:” + String(calibratedReading));

Serial.println(“===========================”);

oled.display();

}

int f(int x) {

int intersectionPoint = 117;

float deviation = 0.165;

return round(x - (intersectionPoint - x) * deviation);

}

void setup() {

Serial.begin(9600);

Wire.begin();

oled.begin(); // Initialize the OLED

oled.clear(ALL); // Clear the display’s internal memory

oled.clear(PAGE); // Clear the buffer.

delay(100); // Delay 100 ms

oled.setFontType(3);

// Initialize sensor

if (particleSensor.begin(Wire, I2C_SPEED_FAST) == false) // Use default I2C port, 400kHz speed

{

Serial.println("MAX30105 was not found. Please check wiring/power. ");

while (1)

;

}

// The variable below calibrates the LED output on your hardware.

byte ledBrightness = 135;

byte sampleAverage = 4; // Options: 1, 2, 4, 8, 16, --32–

byte ledMode = 2; // Options: 1 = Red only, --2 = Red + IR–, 3 = Red + IR + Green

int sampleRate = 50; // Options: 50, 100, 200, 400, 800, 1000, 1600, --3200–

int pulseWidth = 411; // Options: 69, 118, 215, --411–

int adcRange = 16384; // Options: 2048, --4096–, 8192, 16384

particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); // Configure sensor with these settings

particleSensor.setPulseAmplitudeRed(0);

particleSensor.setPulseAmplitudeGreen(0);

particleSensor.disableSlots();

particleSensor.enableSlot(2, 0x02); // Enable only SLOT_IR_LED = 0x02

// Update to ignore readings under 30.000

unblockedValue = 30000;

pinMode(BATTERY_PIN, INPUT);

}

void loop() {

int rLevel = particleSensor.getIR();

long currentDelta = rLevel - unblockedValue;

if (currentDelta > (long)100) {

displayMeasurement(rLevel / 1000);

} else {

displayMeasurement(0);

}

delay(100);

}

just created a simple sketch (attached). Parallel to the 100K resistor between GND and central point I add a 2.2uF capacitor. (see top of sketch) Also I adjusted your reference voltage. This worked.

Battery_voltage.zip (727 Bytes)

Paul,

I adjusted my setup to it will be easier to make the battery percentage reading easier. I am currently just using:

  1. SparkFun Artemis Thing Plus

https://www.sparkfun.com/products/15574

  1. 3.7V 522332 400mAh Lipo battery Rechargeable Lithium Polymer ion Battery Pack with PH2.0mm JST Connector

https://www.amazon.com/Battery-Recharge … B07BTWMM8H

  1. SparkFun Micro OLED Breakout (Qwiic)

https://www.sparkfun.com/products/22495

The Artemis Thing Plus is the main board, the Lipo battery is connected to the JST connector. I also followed you recommendations and I connected the VBAT pin to the ADC A0 pin with a voltage divider , 2 x 100K resistors. Then, I took the middle point to A0 and the end to the GND pin. Finally, parallel to the 100K resistor between GND and central point I added a 1uF capacitor.

So i created a new simpler script, but the voltage comes as 0.00. Could you please take a look at my code?

Also the main purpose of this is to check the battery percentage.

batteryTest.zip (1.63 KB)

did my example work ? If not what results do you get?

Paul, yes I followed your example, but I am just getting “0.00” reading.

Please check the attached code

batteryTest.zip (1.63 KB)

I don’t see a direct problem in your example. However, if my example did not work unmodified you have a different problem. use my example and Instead of connecting to VBAT, connect the voltage divider to 3v3. If that does not work include some pictures.