BQ27220

The BQ27220 is a Texas Instruments I2C battery fuel gauge (gas gauge) for single-cell lithium-ion batteries. It uses TI’s Impedance Track™ algorithm to report the battery state-of-charge, state-of-health, remaining and full-charge capacity, voltage, instantaneous and average current, average power, temperature, cycle count, and time-to-empty / time-to-full estimates over I2C.

The espp::Bq27220 component provides a simple interface to read these quantities. All values are 16-bit little-endian standard commands.

API Reference

Header File

Classes

class Bq27220 : public espp::BasePeripheral<>

Class to interface with the BQ27220 battery fuel gauge.

This class is used to interface with the Texas Instruments BQ27220 I2C battery fuel gauge (gas gauge). It is used to get the battery voltage, current, state of charge, state of health, temperature, capacity, and time-to-empty / time-to-full estimates.

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();

Note

All data values reported by the BQ27220 are 16-bit little-endian.

Public Types

typedef std::function<bool(uint8_t)> probe_fn

Function to probe the peripheral

Param address:

The address to probe

Return:

True if the peripheral is found at the given address

Public Functions

inline explicit Bq27220(const Config &config)

Construct a new Bq27220 object.

Parameters:

config – Configuration for the BQ27220.

inline void initialize(std::error_code &ec)

Initialize the BQ27220.

Performs a communications sanity check by reading the battery status register. This does not perform any data-memory or subcommand access.

Parameters:

ec – Error code set if an error occurs during initialization.

inline uint16_t get_voltage_mv(std::error_code &ec)

Get the battery voltage.

Parameters:

ec – Error code set if an error occurs.

Returns:

The battery voltage in mV.

inline int16_t get_current_ma(std::error_code &ec)

Get the instantaneous battery current.

A positive value indicates charging. A negative value indicates discharging.

Parameters:

ec – Error code set if an error occurs.

Returns:

The battery current in mA (signed).

inline int16_t get_average_current_ma(std::error_code &ec)

Get the average battery current.

A positive value indicates charging. A negative value indicates discharging.

Parameters:

ec – Error code set if an error occurs.

Returns:

The average battery current in mA (signed).

inline int16_t get_average_power_mw(std::error_code &ec)

Get the average power.

A positive value indicates charging. A negative value indicates discharging.

Parameters:

ec – Error code set if an error occurs.

Returns:

The average power in mW (signed).

inline float get_temperature_celsius(std::error_code &ec)

Get the battery temperature.

The BQ27220 reports temperature in units of 0.1 Kelvin. This is converted to degrees Celsius.

Parameters:

ec – Error code set if an error occurs.

Returns:

The battery temperature in degrees Celsius.

inline uint8_t get_state_of_charge(std::error_code &ec)

Get the battery state of charge.

This is the percentage of battery charge remaining.

Parameters:

ec – Error code set if an error occurs.

Returns:

The battery state of charge in % (0-100).

inline uint8_t get_state_of_health(std::error_code &ec)

Get the battery state of health.

Parameters:

ec – Error code set if an error occurs.

Returns:

The battery state of health in % (0-100).

inline uint16_t get_remaining_capacity_mah(std::error_code &ec)

Get the remaining battery capacity.

Parameters:

ec – Error code set if an error occurs.

Returns:

The remaining battery capacity in mAh.

inline uint16_t get_full_charge_capacity_mah(std::error_code &ec)

Get the full charge capacity.

Parameters:

ec – Error code set if an error occurs.

Returns:

The full charge capacity in mAh.

inline uint16_t get_design_capacity_mah(std::error_code &ec)

Get the design capacity.

Parameters:

ec – Error code set if an error occurs.

Returns:

The design capacity in mAh.

inline uint16_t get_time_to_empty_minutes(std::error_code &ec)

Get the estimated time until the battery is empty.

Parameters:

ec – Error code set if an error occurs.

Returns:

The time to empty in minutes.

inline uint16_t get_time_to_full_minutes(std::error_code &ec)

Get the estimated time until the battery is fully charged.

Parameters:

ec – Error code set if an error occurs.

Returns:

The time to full in minutes.

inline uint16_t get_cycle_count(std::error_code &ec)

Get the battery cycle count.

Parameters:

ec – Error code set if an error occurs.

Returns:

The number of charge cycles.

inline uint16_t get_battery_status(std::error_code &ec)

Get the battery status flags.

Parameters:

ec – Error code set if an error occurs.

Returns:

The battery status flags.

inline bool probe(std::error_code &ec) const

Probe the peripheral

Note

This function is thread safe

Note

If the probe function is not set, this function will return false and set the error code to operation_not_supported

Note

This function is only available if UseAddress is true

Parameters:

ec – The error code to set if there is an error

Returns:

True if the peripheral is found

inline void set_address(uint8_t address)

Set the address of the peripheral

Note

This function is thread safe

Note

This function is only available if UseAddress is true

Parameters:

address – The address of the peripheral

inline void set_probe(const probe_fn &probe)

Set the probe function

Note

This function is thread safe

Note

This should rarely be used, as the probe function is usually set in the constructor. If you need to change the probe function, consider using the set_config function instead.

Note

This function is only available if UseAddress is true

Parameters:

probe – The probe function

inline void set_write(const write_fn &write)

Set the write function

Note

This function is thread safe

Note

This should rarely be used, as the write function is usually set in the constructor. If you need to change the write function, consider using the set_config function instead.

Parameters:

write – The write function

inline void set_read(const read_fn &read)

Set the read function

Note

This function is thread safe

Note

This should rarely be used, as the read function is usually set in the constructor. If you need to change the read function, consider using the set_config function instead.

Parameters:

read – The read function

inline void set_read_register(const read_register_fn &read_register)

Set the read register function

Note

This function is thread safe

Note

This should rarely be used, as the read register function is usually set in the constructor. If you need to change the read register function, consider using the set_config function instead.

Parameters:

read_register – The read register function

inline void set_write_then_read(const write_then_read_fn &write_then_read)

Set the write then read function

Note

This function is thread safe

Note

This should rarely be used, as the write then read function is usually set in the constructor. If you need to change the write then

Parameters:

write_then_read – The write then read function

inline void set_separate_write_then_read_delay(const std::chrono::milliseconds &delay)

Set the delay between the write and read operations in write_then_read

Note

This function is thread safe

Note

This should rarely be used, as the delay is usually set in the constructor. If you need to change the delay, consider using the set_config function instead.

Note

This delay is only used if the write_then_read function is not set to a custom function and the write and read functions are separate functions.

Parameters:

delay – The delay between the write and read operations in write_then_read

inline void set_config(const Config &config)

Set the configuration for the peripheral

Note

This function is thread safe

Note

The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.

Parameters:

config – The configuration for the peripheral

inline void set_config(Config &&config)

Set the configuration for the peripheral

Note

This function is thread safe

Note

The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.

Parameters:

config – The configuration for the peripheral

inline const Config &config() const

Get the configuration for the peripheral

Returns:

The configuration for the peripheral

inline uint8_t address() const

Get the address of the peripheral

Returns:

The address of the peripheral

inline const std::string &get_name() const

Get the name of the component

Note

This is the tag of the logger

Returns:

A const reference to the name of the component

inline void set_log_tag(const std::string_view &tag)

Set the tag for the logger

Parameters:

tag – The tag to use for the logger

inline espp::Logger::Verbosity get_log_level() const

Get the log level for the logger

Returns:

The verbosity level of the logger

inline void set_log_level(espp::Logger::Verbosity level)

Set the log level for the logger

Parameters:

level – The verbosity level to use for the logger

inline void set_log_verbosity(espp::Logger::Verbosity level)

Set the log verbosity for the logger

See also

set_log_level

Note

This is a convenience method that calls set_log_level

Parameters:

level – The verbosity level to use for the logger

inline espp::Logger::Verbosity get_log_verbosity() const

Get the log verbosity for the logger

See also

get_log_level

Note

This is a convenience method that calls get_log_level

Returns:

The verbosity level of the logger

inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)

Set the rate limit for the logger

Note

Only calls to the logger that have _rate_limit suffix will be rate limited

Parameters:

rate_limit – The rate limit to use for the logger

Public Static Attributes

static constexpr uint8_t DEFAULT_ADDRESS = 0x55

Default address of the BQ27220.

struct Config

Configuration for the BQ27220.

Public Members

uint8_t device_address = {DEFAULT_ADDRESS}

Address of the BQ27220.

bool auto_init = {true}

Whether to automatically initialize the BQ27220.

Logger::Verbosity log_level = {Logger::Verbosity::WARN}

Log level for the BQ27220.