This commit is contained in:
yrx
2026-08-11 13:38:27 +08:00
parent abbf30d7c0
commit 6556cfcf74
39 changed files with 678 additions and 58 deletions
+116 -5
View File
@@ -5,6 +5,8 @@
提供电压、电流监测和充电状态检测
"""
import config
import os
import subprocess
from logger_manager import logger_manager
from maix import time as maix_time
@@ -85,7 +87,7 @@ def get_bus_voltage():
def get_current():
"""
读取电流(单位:mA
正数表示电,负数表示放电
当前电源板实测:正数表示电,负数表示充电。
INA226 电流计算公式:
Current = (Current Register Value) × Current_LSB
@@ -96,13 +98,13 @@ def get_current():
return 0.0
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,表示负数(放电)
if raw & 0x8000:
signed_raw = raw - 0x10000 # 转换为有符号整数
else: # 最高位为0,表示正数(充电)
else:
signed_raw = raw
# 转换为毫安
current_ma = signed_raw * current_lsb * 1000
@@ -129,7 +131,7 @@ def is_charging(threshold_ma=10.0):
"""
try:
current = get_current()
is_charge = current > threshold_ma
is_charge = current < -abs(float(threshold_ma))
return is_charge
except Exception as e:
logger = logger_manager.logger
@@ -140,6 +142,115 @@ def is_charging(threshold_ma=10.0):
return False
def charging_shutdown_monitor():
"""独立监测 INA226;连续确认充电后通知服务器并退出应用。"""
logger = logger_manager.logger
shutdown_enabled = bool(getattr(config, "CHARGING_SHUTDOWN_ENABLED", False))
diagnostic_enabled = bool(getattr(config, "CHARGING_DIAGNOSTIC_LOG_ENABLED", False))
if not shutdown_enabled and not diagnostic_enabled:
if logger:
logger.info("[CHARGE] 充电退出监测已禁用")
return
interval_ms = max(100, int(getattr(config, "CHARGING_CHECK_INTERVAL_MS", 5000)))
threshold_ma = float(getattr(config, "CHARGING_CURRENT_THRESHOLD_MA", 10.0))
confirm_required = max(1, int(getattr(config, "CHARGING_CONFIRM_COUNT", 2)))
confirm_count = 0
if logger:
logger.info(
f"[CHARGE] 独立监测线程启动: interval={interval_ms}ms, "
f"threshold={threshold_ma:.1f}mA, confirm={confirm_required}, "
f"shutdown={'on' if shutdown_enabled else 'off'}"
)
while True:
current_ma = get_current()
if diagnostic_enabled and logger:
voltage = get_bus_voltage()
logger.info(
f"[CHARGE-DIAG] INA226 voltage={voltage:.3f}V, "
f"current={current_ma:.1f}mA"
)
if not shutdown_enabled:
maix_time.sleep_ms(interval_ms)
continue
if current_ma < -abs(threshold_ma):
confirm_count += 1
if logger:
logger.info(
f"[CHARGE] INA226 充电电流 {current_ma:.1f}mA "
f"({confirm_count}/{confirm_required})"
)
else:
confirm_count = 0
if confirm_count >= confirm_required:
script_path = getattr(
config,
"CHARGING_EXIT_SCRIPT",
config.APP_DIR + "/charging_exit.sh",
)
if not os.path.isfile(script_path):
if logger:
logger.error(f"[CHARGE] 退出脚本不存在: {script_path}")
confirm_count = 0
else:
if logger:
logger.warning(
f"[CHARGE] 已连续确认充电,通知服务器后退出应用: current={current_ma:.1f}mA"
)
try:
from network import network_manager
notify_timeout_ms = max(
0,
int(getattr(config, "CHARGING_NOTIFY_TIMEOUT_MS", 30000)),
)
notification_sent = network_manager.safe_enqueue_and_wait(
{"poweroff": "充电中"},
2,
high=True,
timeout_ms=notify_timeout_ms,
)
if notification_sent:
if logger:
logger.info("[CHARGE] 充电状态已发送到服务器")
elif logger:
logger.warning(
f"[CHARGE] 等待服务器发送超时({notify_timeout_ms}ms),继续执行退出"
)
except Exception as e:
if logger:
logger.error(f"[CHARGE] 充电状态上报失败,继续执行退出: {e}")
try:
from laser_manager import laser_manager
laser_manager.turn_off_laser()
if logger:
logger.info("[CHARGE] 激光关闭命令已发送")
except Exception as e:
if logger:
logger.error(f"[CHARGE] Python 关闭激光失败,交由退出脚本兜底: {e}")
try:
subprocess.Popen([
"/bin/sh",
script_path,
str(os.getpid()),
str(getattr(config, "DISTANCE_SERIAL_DEVICE", "/dev/ttyS1")),
str(getattr(config, "DISTANCE_SERIAL_BAUDRATE", 9600)),
])
return
except Exception as e:
if logger:
logger.error(f"[CHARGE] 调用退出脚本失败: {e}")
confirm_count = 0
maix_time.sleep_ms(interval_ms)
def voltage_to_percent(voltage):
"""
根据电压估算电池百分比(高密度查表插值 + 滤波)。