Skip to content
Merged
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
16 changes: 7 additions & 9 deletions lib/bq27441/bq27441/device.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from bq27441.const import *
from bq27441.exceptions import *

from utime import sleep_ms, ticks_ms
from machine import Pin, I2C
from time import sleep_ms, ticks_ms
from machine import Pin

import struct

Expand Down Expand Up @@ -70,22 +70,19 @@ def __init__(self, value):
self.value = value


DEFAULT_I2C_BUS = I2C(1)


class BQ27441:
"""BQ27441 class contains all major and minor functions use to read and control
the fuel gauge ic"""

def __init__(
self,
bus=DEFAULT_I2C_BUS,
i2c,
capacity_mAh=LIPO_BATTERY_CAPACITY,
address=BQ27441_I2C_ADDRESS,
gpout_pin=None,
):
self.address = address
self.bus = bus
self.i2c = i2c
self.gpout = None
self._shutdown_en = False
self._userConfigControl = False
Expand Down Expand Up @@ -597,12 +594,13 @@ def writeExtendedData(self, class_id, offset, data, length):

# I2C Read / Write Functions
def i2cReadBytes(self, subAddress, count):
result = self.bus.readfrom_mem(self.address, subAddress, count)
result = self.i2c.readfrom_mem(self.address, subAddress, count)
return list(result)

# Write a specified number of bytes over I2C to a given subAddress
def i2cWriteBytes(self, memAddress, buf, count):
self.bus.writeto_mem(self.address, memAddress, bytes(buf))
self.i2c.writeto_mem(self.address, memAddress, bytes(buf))
return True


def constrain(x, a, b):
Expand Down
4 changes: 2 additions & 2 deletions lib/bq27441/examples/fuel_gauge.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

from bq27441 import BQ27441

bus = I2C(1)
i2c = I2C(1)

fg = BQ27441(bus)
fg = BQ27441(i2c)

print("Fuel Gauge Test")
print("=====================")
Expand Down
4 changes: 3 additions & 1 deletion tests/fake_machine/i2c.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ class FakeI2C:
"""Simulates a MicroPython I2C bus with pre-loaded register values.

Args:
bus_id: optional I2C bus identifier (ignored, accepted for
MicroPython I2C constructor compatibility).
registers: dict mapping register addresses to bytes values.
Single-byte registers can use int values.
address: expected I2C device address for validation.
"""

def __init__(self, registers=None, address=None):
def __init__(self, bus_id=None, *, registers=None, address=None, **kwargs):
Comment thread
nedseb marked this conversation as resolved.
self._registers = {}
self._address = address
self._write_log = []
Expand Down
153 changes: 153 additions & 0 deletions tests/scenarios/bq27441.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
driver: bq27441
driver_class: BQ27441
i2c_address: 0x55

# I2C config for hardware tests (STeaMi board - STM32WB55)
i2c:
id: 1

# Register values for mock tests
# BQ27441 uses 2-byte little-endian registers read via struct.unpack("<h")
# The constructor calls power_up() -> set_capacity() -> writeExtendedData()
# which enters config mode (needs CFGUPMODE flag in FLAGS register).
mock_registers:
# CONTROL (0x00): status word (unsealed, INITCOMP set)
0x00: [0x80, 0x00]
# FLAGS (0x06): CFGUPMODE | BAT_DET | DSG — needed for enterConfig/exitConfig
0x06: [0x19, 0x00]
# VOLTAGE (0x04): 3700 mV
0x04: [0x74, 0x0E]
# REM_CAPACITY (0x0C): 600 mAh
0x0C: [0x58, 0x02]
# FULL_CAPACITY (0x0E): 650 mAh
0x0E: [0x8A, 0x02]
# AVG_CURRENT (0x10): 50 mA
0x10: [0x32, 0x00]
# AVG_POWER (0x18): 185 mW
0x18: [0xB9, 0x00]
# SOC (0x1C): 92%
0x1C: [0x5C, 0x00]
# SOH (0x20): 99% (low byte = percent, high byte = status)
0x20: [0x63, 0x00]

tests:
- name: "Read voltage"
action: call
method: voltage
expect: 3700
mode: [mock]

- name: "Read state of charge"
action: call
method: state_of_charge
expect: 92
mode: [mock]

- name: "Read remaining capacity"
action: call
method: capacity_remaining
expect: 600
mode: [mock]

- name: "Read full capacity"
action: call
method: capacity_full
expect: 650
mode: [mock]

- name: "Read average current"
action: call
method: current_average
expect: 50
mode: [mock]

- name: "Read average power"
action: call
method: power
expect: 185
mode: [mock]

- name: "Read state of health"
action: call
method: state_of_health
expect: 99
mode: [mock]

- name: "Battery connected check"
action: manual
prompt: "Une batterie est-elle connectée à la carte ?"
expect_true: true
mode: [hardware]

- name: "Device type is BQ27441"
action: call
method: is_valid_device
expect: true
mode: [hardware]

- name: "Voltage in plausible range"
action: call
method: voltage
expect_range: [3000, 4300]
mode: [hardware]

- name: "State of charge in valid range"
action: call
method: state_of_charge
expect_range: [0, 100]
mode: [hardware]

- name: "Remaining capacity positive"
action: call
method: capacity_remaining
expect_range: [0, 2000]
mode: [hardware]

- name: "Full capacity positive"
action: call
method: capacity_full
expect_range: [100, 2000]
mode: [hardware]

- name: "Average current readable"
action: call
method: current_average
expect_not_none: true
mode: [hardware]

- name: "Average power readable"
action: call
method: power
expect_not_none: true
mode: [hardware]

- name: "State of health in valid range"
action: call
method: state_of_health
expect_range: [0, 100]
mode: [hardware]

- name: "Battery info summary"
action: manual
display:
- method: voltage
label: "Tension"
unit: "mV"
- method: state_of_charge
label: "Charge"
unit: "%"
- method: capacity_remaining
label: "Capacité restante"
unit: "mAh"
- method: capacity_full
label: "Capacité totale"
unit: "mAh"
- method: current_average
label: "Courant moyen"
unit: "mA"
- method: state_of_health
label: "Santé batterie"
unit: "%"
prompt: "Ces valeurs sont-elles cohérentes avec l'état de la batterie ?"
expect_true: true
mode: [hardware]
Loading