refine power module
This commit is contained in:
64
power.py
64
power.py
@@ -6,13 +6,36 @@
|
||||
"""
|
||||
import config
|
||||
from logger_manager import logger_manager
|
||||
from maix import time as maix_time
|
||||
|
||||
|
||||
_INA226_PRESENT = None
|
||||
|
||||
|
||||
def _ina226_ready() -> bool:
|
||||
"""
|
||||
是否允许访问 INA226。
|
||||
|
||||
重要:
|
||||
- 这里刻意不做任何 I2C 探测/读写。
|
||||
- 经验上,在 INA226 未供电/未响应时,I2C 的 readfrom_mem 可能直接触发底层崩溃(SIGSEGV),try/except 无法拦截。
|
||||
- 因此只在开机 init_ina226() 成功后才允许后续读电压/电流。
|
||||
"""
|
||||
return bool(getattr(config, "INA226_ENABLE", True)) and (_INA226_PRESENT is True)
|
||||
|
||||
|
||||
def write_register(reg, value):
|
||||
"""写入INA226寄存器"""
|
||||
from hardware import hardware_manager
|
||||
logger = logger_manager.logger
|
||||
data = [(value >> 8) & 0xFF, value & 0xFF]
|
||||
hardware_manager.bus.writeto_mem(config.INA226_ADDR, reg, bytes(data))
|
||||
# 某些底层驱动在失败时只打印 “write failed” 并返回 -1,而不是抛异常;
|
||||
# 为避免误判“初始化成功”导致后续 readfrom_mem SIGSEGV,这里把失败显式转成异常。
|
||||
ret = hardware_manager.bus.writeto_mem(config.INA226_ADDR, reg, bytes(data))
|
||||
if isinstance(ret, int) and ret < 0:
|
||||
if logger:
|
||||
logger.error(f"[INA226] writeto_mem 失败: addr=0x{config.INA226_ADDR:02X} reg=0x{reg:02X} ret={ret}")
|
||||
raise OSError(ret)
|
||||
|
||||
|
||||
def read_register(reg):
|
||||
@@ -24,14 +47,39 @@ def read_register(reg):
|
||||
|
||||
def init_ina226():
|
||||
"""初始化 INA226 芯片:配置模式 + 校准值"""
|
||||
write_register(config.REG_CONFIGURATION, 0x4527)
|
||||
write_register(config.REG_CALIBRATION, config.CALIBRATION_VALUE)
|
||||
global _INA226_PRESENT
|
||||
logger = logger_manager.logger
|
||||
if not getattr(config, "INA226_ENABLE", True):
|
||||
if logger:
|
||||
logger.info("[INA226] INA226_ENABLE=False,跳过初始化与 I2C 探测")
|
||||
# 显式标记不可用,避免后续误读
|
||||
_INA226_PRESENT = False
|
||||
return False
|
||||
try:
|
||||
# 仅通过“写寄存器成功”来判定可用,避免额外的读操作触发底层崩溃
|
||||
write_register(config.REG_CONFIGURATION, 0x4527)
|
||||
write_register(config.REG_CALIBRATION, config.CALIBRATION_VALUE)
|
||||
_INA226_PRESENT = True
|
||||
return True
|
||||
except Exception as e:
|
||||
_INA226_PRESENT = False
|
||||
if logger:
|
||||
logger.error(f"[INA226] 初始化失败:{e}")
|
||||
return False
|
||||
|
||||
|
||||
def get_bus_voltage():
|
||||
"""读取总线电压(单位:V)"""
|
||||
raw = read_register(config.REG_BUS_VOLTAGE)
|
||||
return raw * 1.25 / 1000
|
||||
"""读取总线电压(单位:V)。未探测到 INA226 或读失败时返回 0.0(上报用,避免 null)。"""
|
||||
logger = logger_manager.logger
|
||||
if not _ina226_ready():
|
||||
return 0.0
|
||||
try:
|
||||
raw = read_register(config.REG_BUS_VOLTAGE)
|
||||
return raw * 1.25 / 1000
|
||||
except Exception as e:
|
||||
if logger:
|
||||
logger.error(f"[INA226] 读取电压失败:{e}")
|
||||
return 0.0
|
||||
|
||||
|
||||
def get_current():
|
||||
@@ -44,6 +92,8 @@ def get_current():
|
||||
Current_LSB = 0.001 × CALIBRATION_VALUE / 4096
|
||||
"""
|
||||
try:
|
||||
if not _ina226_ready():
|
||||
return 0.0
|
||||
raw = read_register(config.REG_CURRENT)
|
||||
# INA226 电流寄存器是16位有符号整数
|
||||
# 最高位是符号位:0=正(充电),1=负(放电)
|
||||
@@ -92,6 +142,8 @@ def is_charging(threshold_ma=10.0):
|
||||
|
||||
def voltage_to_percent(voltage):
|
||||
"""根据电压估算电池百分比(查表插值)"""
|
||||
if voltage is None:
|
||||
return 0
|
||||
points = [
|
||||
(4.20, 100), (4.10, 95), (4.05, 85), (4.00, 75), (3.95, 65),
|
||||
(3.90, 55), (3.85, 45), (3.80, 35), (3.75, 25), (3.70, 15),
|
||||
|
||||
Reference in New Issue
Block a user