You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python准确检测电池电压时间序列的循环次数?

电池循环次数统计的替代方法

核心思路

电池充放电循环对应电压上升(充电)+ 电压下降(放电)的完整过程,单纯检测峰值无法覆盖完整循环逻辑,建议结合趋势判断(充放电状态转换)或峰谷配对的方式统计。


方法一:基于充放电状态转换的状态机统计

通过计算电压变化趋势,跟踪充放电状态的切换,每完成一次「充电→放电」的完整过程即计为一个循环(可根据实际循环定义调整判断逻辑)。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 加载并预处理数据(确保时间序列有序)
df = pd.read_csv("your_data.csv")
df['datetime'] = pd.to_datetime(df['datetime'])
df = df.sort_values('datetime').reset_index(drop=True)

# 计算电压差分,过滤噪声后判断趋势
diff_threshold = 0.01  # 根据数据波动调整,过滤微小噪声
df['voltage_diff'] = df['voltage'].diff()
df['trend'] = np.where(
    df['voltage_diff'] > diff_threshold, 'charging',
    np.where(df['voltage_diff'] < -diff_threshold, 'discharging', 'stable')
)

# 状态机跟踪循环次数
current_state = df['trend'].iloc[0]
cycle_count = 0
cycle_end_times = []

for idx, row in df.iterrows():
    # 当状态从充电转为放电时,视为完成一次完整充放循环
    if current_state == 'charging' and row['trend'] == 'discharging':
        cycle_count += 1
        cycle_end_times.append(row['datetime'])
    current_state = row['trend']

print(f"统计到的电池循环次数:{cycle_count}")

# 可视化验证
plt.figure(figsize=(19, 8))
plt.plot(df['datetime'], df['voltage'], label='电池电压')
for time in cycle_end_times:
    plt.axvline(x=time, color='r', linestyle='--', label='循环结束' if time == cycle_end_times[0] else "")
plt.xlabel('时间')
plt.ylabel('电压')
plt.legend()
plt.show()

方法二:峰谷配对检测循环

结合峰值(充电最高点)和谷值(放电最低点)的检测,通过时间顺序配对峰谷,每一对有效「谷值→峰值→谷值」或「峰值→谷值→峰值」计为一个循环。

import pandas as pd
import matplotlib.pyplot as plt
from scipy.signal import find_peaks

# 加载并预处理数据
df = pd.read_csv("your_data.csv")
df = df.sort_values('datetime').reset_index(drop=True)

# 先平滑电压数据,减少噪声干扰
df['voltage_smoothed'] = df['voltage'].rolling(window=50).mean().dropna()

# 检测峰值(充电最高点)
peaks, _ = find_peaks(
    df['voltage_smoothed'],
    prominence=0.5,  # 峰与周围的高度差,根据数据调整
    height=51        # 峰值最低阈值
)

# 检测谷值(放电最低点,通过反转电压找峰值实现)
valleys, _ = find_peaks(
    -df['voltage_smoothed'],
    prominence=0.5,
    height=-48       # 谷值最高阈值(反转后为负,对应原电压最低值)
)

# 按时间顺序配对峰谷,统计循环次数
cycle_count = 0
last_valley_idx = None

for peak_idx in peaks:
    # 找到当前峰值之前的最近谷值
    preceding_valleys = valleys[valleys < peak_idx]
    if len(preceding_valleys) > 0 and (last_valley_idx is None or preceding_valleys[-1] > last_valley_idx):
        cycle_count += 1
        last_valley_idx = preceding_valleys[-1]

print(f"统计到的电池循环次数:{cycle_count}")

# 可视化验证
plt.figure(figsize=(19, 8))
plt.plot(df['voltage_smoothed'], label='平滑后电压')
plt.plot(peaks, df['voltage_smoothed'].iloc[peaks], 'x', color='r', label='充电峰值')
plt.plot(valleys, df['voltage_smoothed'].iloc[valleys], 'o', color='g', label='放电谷值')
plt.xlim(0, 45000)
plt.xlabel('数据点索引')
plt.ylabel('电压')
plt.legend()
plt.show()

关键调整提示

  1. 噪声处理:如果数据波动大,先通过滚动平均(rolling.mean)或高斯滤波平滑数据,避免误判趋势。
  2. 阈值参数:diff_threshold、prominence、height等参数需要根据你的实际电压范围和波动幅度调整,可通过可视化逐步优化。
  3. 循环定义:根据电池实际使用场景调整循环判断逻辑(比如部分场景下「放电→充电」也可视为一个循环)。

内容的提问来源于stack exchange,提问作者aparna podili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 04:15:42