SparkFun Forums 

Where electronics enthusiasts find answers.

Topics pertaining to the Arduino Core & software used with the Artemis module and Artemis development boards.
User avatar
By baqjosue
#245268
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
2. SparkFun Photodetector Breakout - MAX30101 (Qwiic)
https://www.sparkfun.com/products/16474
3. 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:
Code: Select all
#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.
By paulvha
#245269
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.
User avatar
By baqjosue
#245480
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
User avatar
By baqjosue
#245488
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);
}
By paulvha
#245491
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.
You do not have the required permissions to view the files attached to this post.
User avatar
By baqjosue
#245509
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
2. 3.7V 522332 400mAh Lipo battery Rechargeable Lithium Polymer ion Battery Pack with PH2.0mm JST Connector
https://www.amazon.com/Battery-Recharge ... B07BTWMM8H
3. 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.
You do not have the required permissions to view the files attached to this post.
User avatar
By baqjosue
#245512
Paul, yes I followed your example, but I am just getting "0.00" reading.
Please check the attached code
You do not have the required permissions to view the files attached to this post.
By paulvha
#245518
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.
 Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum