Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ jobs:
target: esp32
- path: 'components/bmi270/example'
target: esp32p4
- path: 'components/bq27220/example'
target: esp32
- path: 'components/button/example'
target: esp32
- path: 'components/byte90/example'
Expand Down Expand Up @@ -141,6 +143,8 @@ jobs:
target: esp32
- path: 'components/led_strip/example'
target: esp32
- path: 'components/lilygo-t5-47/example'
target: esp32s3
- path: 'components/logger/example'
target: esp32
- path: 'components/lp5817/example'
Expand Down Expand Up @@ -177,6 +181,8 @@ jobs:
target: esp32s3
- path: 'components/odrive_ascii/example'
target: esp32
- path: 'components/pca9535/example'
target: esp32s3
- path: 'components/pcf85063/example'
target: esp32s3
- path: 'components/pi4ioe5v/example'
Expand Down
4 changes: 4 additions & 0 deletions components/bq27220/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
idf_component_register(
INCLUDE_DIRS "include"
REQUIRES "base_peripheral" "math"
)
22 changes: 22 additions & 0 deletions components/bq27220/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# BQ27220 I2C Battery Fuel Gauge Component

[![Badge](https://components.espressif.com/components/espp/bq27220/badge.svg)](https://components.espressif.com/components/espp/bq27220)

The Texas Instruments BQ27220 is a single-cell Li-Ion battery fuel gauge (gas
gauge) that uses the compensated end-of-discharge voltage (CEDV) algorithm to
provide accurate state-of-charge and remaining-capacity information without
requiring the host to maintain a battery-learn cycle.

The BQ27220 reports battery voltage, instantaneous and average current, average
power, temperature, state of charge, state of health, remaining and full-charge
capacity, cycle count, and time-to-empty / time-to-full estimates over the I2C
interface. All data values are 16-bit little-endian.

## Example

The [example](./example) shows how to use the BQ27220 driver to talk to the
BQ27220 and retrieve the current battery:
* Voltage (mV)
* Current (mA)
* State of Charge (%)
* Temperature (°C)
22 changes: 22 additions & 0 deletions components/bq27220/example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.20)

set(ENV{IDF_COMPONENT_MANAGER} "0")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

# add the component directories that we want to use
set(EXTRA_COMPONENT_DIRS
"../../../components/"
)

set(
COMPONENTS
"main esptool_py i2c task bq27220"
CACHE STRING
"List of components to include"
)

project(bq27220_example)

set(CMAKE_CXX_STANDARD 20)
34 changes: 34 additions & 0 deletions components/bq27220/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# BQ27220 Example

This example shows how to use the `espp::Bq27220` driver to talk to a TI BQ27220
battery fuel gauge over I2C and read the battery:
* Voltage (mV)
* Current (mA)
* State of charge (%)
* Temperature (°C)

## How to use example

### Hardware Required

This example requires a connection (via I2C) to a board with a BQ27220 battery
fuel gauge and an attached battery. Configure the I2C pins (SDA/SCL) via
`menuconfig` for your board.

### Build and Flash

Build the project and flash it to the board, then run the monitor tool to view
serial output:

```
idf.py -p PORT flash monitor
```

(Replace PORT with the name of the serial port to use.)

(To exit the serial monitor, type ``Ctrl-]``.)

## Example Output

The example logs the battery voltage, current, state of charge, and temperature
in a loop.
2 changes: 2 additions & 0 deletions components/bq27220/example/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS ".")
39 changes: 39 additions & 0 deletions components/bq27220/example/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
menu "Example Configuration"

choice EXAMPLE_HARDWARE
prompt "Hardware"
default EXAMPLE_HARDWARE_QTPYPICO
help
Select the hardware to run this example on.

config EXAMPLE_HARDWARE_QTPYPICO
depends on IDF_TARGET_ESP32
bool "Qt Py PICO"

config EXAMPLE_HARDWARE_QTPYS3
depends on IDF_TARGET_ESP32S3
bool "Qt Py S3"

config EXAMPLE_HARDWARE_CUSTOM
bool "Custom"
endchoice

config EXAMPLE_I2C_SCL_GPIO
int "SCL GPIO Num"
range 0 50
default 19 if EXAMPLE_HARDWARE_QTPYPICO
default 40 if EXAMPLE_HARDWARE_QTPYS3
default 19 if EXAMPLE_HARDWARE_CUSTOM
help
GPIO number for I2C Master clock line.

config EXAMPLE_I2C_SDA_GPIO
int "SDA GPIO Num"
range 0 50
default 22 if EXAMPLE_HARDWARE_QTPYPICO
default 41 if EXAMPLE_HARDWARE_QTPYS3
default 22 if EXAMPLE_HARDWARE_CUSTOM
help
GPIO number for I2C Master data line.

endmenu
83 changes: 83 additions & 0 deletions components/bq27220/example/main/bq27220_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <chrono>
#include <vector>

#include "bq27220.hpp"
#include "i2c.hpp"
#include "logger.hpp"
#include "task.hpp"

using namespace std::chrono_literals;

extern "C" void app_main(void) {

//! [bq27220 example]
espp::Logger logger({.tag = "Bq27220 example", .level = espp::Logger::Verbosity::INFO});
// make the I2C that we'll use to communicate
logger.info("initializing i2c driver...");
espp::I2c i2c({
.port = I2C_NUM_0,
.sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO,
.scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO,
});
std::error_code ec;
auto bq27220_device =
i2c.add_device<uint8_t>({.device_address = espp::Bq27220::DEFAULT_ADDRESS,
.timeout_ms = static_cast<int>(i2c.config().timeout_ms),
.scl_speed_hz = i2c.config().clk_speed,
.log_level = espp::Logger::Verbosity::WARN},
ec);
if (!bq27220_device) {
logger.error("BQ27220 I2C device initialization failed: {}", ec.message());
return;
}
// now make the bq27220 which handles the fuel gauge
espp::Bq27220 bq27220({.write = espp::make_i2c_addressed_write(bq27220_device),
.read = espp::make_i2c_addressed_read(bq27220_device),
.log_level = espp::Logger::Verbosity::WARN});

// and finally, make the task to periodically poll the bq27220 and print
// the state.
auto task_fn = [&](std::mutex &m, std::condition_variable &cv) {
// NOTE: sleeping in this way allows the sleep to exit early when the
// task is being stopped / destroyed
{
std::unique_lock<std::mutex> lk(m);
cv.wait_for(lk, 1s);
}
static auto start = std::chrono::high_resolution_clock::now();
auto now = std::chrono::high_resolution_clock::now();
auto seconds = std::chrono::duration<float>(now - start).count();
auto voltage = bq27220.get_voltage_mv(ec);
if (ec) {
return false;
}
auto current = bq27220.get_current_ma(ec);
if (ec) {
return false;
}
auto soc = bq27220.get_state_of_charge(ec);
if (ec) {
return false;
}
auto temperature = bq27220.get_temperature_celsius(ec);
if (ec) {
return false;
}
fmt::print("{:0.2f}, {}, {}, {}, {:0.2f}\n", seconds, voltage, current, soc, temperature);
// don't want to stop the task
return false;
};
auto task = espp::Task({.callback = task_fn,
.task_config =
{
.name = "Bq27220 Task",
.stack_size_bytes = 5 * 1024,
},
.log_level = espp::Logger::Verbosity::WARN});
fmt::print("%time(s), voltage (mV), current (mA), SoC (%), Temperature (C)\n");
task.start();
//! [bq27220 example]
while (true) {
std::this_thread::sleep_for(100ms);
}
}
11 changes: 11 additions & 0 deletions components/bq27220/example/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CONFIG_FREERTOS_HZ=1000

# ESP32-specific
#
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240

# Common ESP-related
#
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
22 changes: 22 additions & 0 deletions components/bq27220/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## IDF Component Manager Manifest File
license: "MIT"
description: "BQ27220 Battery Fuel Gauge component for ESP-IDF"
url: "https://github.com/esp-cpp/espp/tree/main/components/bq27220"
repository: "git://github.com/esp-cpp/espp.git"
maintainers:
- William Emfinger <waemfinger@gmail.com>
documentation: "https://esp-cpp.github.io/espp/battery/bq27220.html"
examples:
- path: example
tags:
- cpp
- Component
- Battery
- Fuel
- Gauge
- BQ27220
dependencies:
idf:
version: '>=5.0'
espp/base_peripheral: '>=1.0'
espp/math: '>=1.0'
Loading