113 lines
3.4 KiB
Python
113 lines
3.4 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
"""
|
|||
|
|
电源管理模块(INA226)
|
|||
|
|
提供电压、电流监测和充电状态检测
|
|||
|
|
"""
|
|||
|
|
import config
|
|||
|
|
from logger_manager import logger_manager
|
|||
|
|
|
|||
|
|
|
|||
|
|
def write_register(reg, value):
|
|||
|
|
"""写入INA226寄存器"""
|
|||
|
|
from hardware import hardware_manager
|
|||
|
|
data = [(value >> 8) & 0xFF, value & 0xFF]
|
|||
|
|
hardware_manager.bus.writeto_mem(config.INA226_ADDR, reg, bytes(data))
|
|||
|
|
|
|||
|
|
|
|||
|
|
def read_register(reg):
|
|||
|
|
"""读取INA226寄存器"""
|
|||
|
|
from hardware import hardware_manager
|
|||
|
|
data = hardware_manager.bus.readfrom_mem(config.INA226_ADDR, reg, 2)
|
|||
|
|
return (data[0] << 8) | data[1]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def init_ina226():
|
|||
|
|
"""初始化 INA226 芯片:配置模式 + 校准值"""
|
|||
|
|
write_register(config.REG_CONFIGURATION, 0x4527)
|
|||
|
|
write_register(config.REG_CALIBRATION, config.CALIBRATION_VALUE)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_bus_voltage():
|
|||
|
|
"""读取总线电压(单位:V)"""
|
|||
|
|
raw = read_register(config.REG_BUS_VOLTAGE)
|
|||
|
|
return raw * 1.25 / 1000
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_current():
|
|||
|
|
"""
|
|||
|
|
读取电流(单位:mA)
|
|||
|
|
正数表示充电,负数表示放电
|
|||
|
|
|
|||
|
|
INA226 电流计算公式:
|
|||
|
|
Current = (Current Register Value) × Current_LSB
|
|||
|
|
Current_LSB = 0.001 × CALIBRATION_VALUE / 4096
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
raw = read_register(config.REG_CURRENT)
|
|||
|
|
# INA226 电流寄存器是16位有符号整数
|
|||
|
|
# 最高位是符号位:0=正(充电),1=负(放电)
|
|||
|
|
# 计算 Current_LSB(根据 CALIBRATION_VALUE)
|
|||
|
|
current_lsb = 0.001 * config.CALIBRATION_VALUE / 4096 # 单位:A
|
|||
|
|
# 处理有符号数:如果最高位为1,转换为负数
|
|||
|
|
if raw & 0x8000: # 最高位为1,表示负数(放电)
|
|||
|
|
signed_raw = raw - 0x10000 # 转换为有符号整数
|
|||
|
|
else: # 最高位为0,表示正数(充电)
|
|||
|
|
signed_raw = raw
|
|||
|
|
# 转换为毫安
|
|||
|
|
current_ma = signed_raw * current_lsb * 1000
|
|||
|
|
return current_ma
|
|||
|
|
except Exception as e:
|
|||
|
|
logger = logger_manager.logger
|
|||
|
|
if logger:
|
|||
|
|
logger.error(f"[INA226] 读取电流失败: {e}")
|
|||
|
|
else:
|
|||
|
|
print(f"[INA226] 读取电流失败: {e}")
|
|||
|
|
return 0.0
|
|||
|
|
|
|||
|
|
|
|||
|
|
def is_charging(threshold_ma=10.0):
|
|||
|
|
"""
|
|||
|
|
检测是否在充电(通过电流方向判断)
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
threshold_ma: 电流阈值(毫安),超过此值认为在充电,默认10mA
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
True: 正在充电
|
|||
|
|
False: 未充电或读取失败
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
current = get_current()
|
|||
|
|
is_charge = current > threshold_ma
|
|||
|
|
return is_charge
|
|||
|
|
except Exception as e:
|
|||
|
|
logger = logger_manager.logger
|
|||
|
|
if logger:
|
|||
|
|
logger.error(f"[CHARGE] 检测充电状态失败: {e}")
|
|||
|
|
else:
|
|||
|
|
print(f"[CHARGE] 检测充电状态失败: {e}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
|
|||
|
|
def voltage_to_percent(voltage):
|
|||
|
|
"""根据电压估算电池百分比(查表插值)"""
|
|||
|
|
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),
|
|||
|
|
(3.65, 5), (3.60, 0)
|
|||
|
|
]
|
|||
|
|
if voltage >= points[0][0]:
|
|||
|
|
return 100
|
|||
|
|
if voltage <= points[-1][0]:
|
|||
|
|
return 0
|
|||
|
|
for i in range(len(points) - 1):
|
|||
|
|
v1, p1 = points[i]
|
|||
|
|
v2, p2 = points[i + 1]
|
|||
|
|
if voltage >= v2:
|
|||
|
|
ratio = (voltage - v1) / (v2 - v1)
|
|||
|
|
percent = p1 + (p2 - p1) * ratio
|
|||
|
|
return max(0, min(100, int(round(percent))))
|
|||
|
|
return 0
|
|||
|
|
|