2.15.26
This commit is contained in:
@@ -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):
|
||||
"""
|
||||
根据电压估算电池百分比(高密度查表插值 + 滤波)。
|
||||
|
||||
Reference in New Issue
Block a user