Nova Kwok's Awesome Blog

借助 pandas, numpy 自动化修正 Hondata AFM 曲线

在之前的文章 「什么是空燃比,燃油修正和 AFM 曲线——兼谈如何通过 Hondata Log 数据了解你的进气组件是否正常工作」 中我们知道,如果更换了进气套件或者滤芯的话,可以通过 Hondata 对 AFM 曲线进行修正。

例如,你录制了一段 Datalog,通过 Hondata 的 XY 图 Plot 出来 AFM.v 和 S.Trim 发现是下图这样的话,你就会知道在 1.1v 左右的位置有个坑(最低到了 -8%),说明标定中对应的电压值对应的进气量偏高(电脑会根据标定喷油,然后发现喷浓了 8%,于是通过 S.Trim 减少 8% 的喷油量)

这个时候我们需要找到 AFM 表格并修改对应区间的数据,减少 8% 左右来修正这个情况:

然后通过更多的不同工况的 Datalog 进行反复路试+修正,获得一个最平滑的 AFM.v - S.Trim 曲线,以上过程被称为——AFM 修正,这也是程序调整中非常重要的根基。

如果 AFM 修正不正确车辆的响应会比较奇怪,且在 WOT(全油门) 下由于不走 S.Trim 所以会导致 AF(实际空燃比) 没法稳定跟上 AFCMD(电脑请求空燃比)

如果上文内容你不太能理解的话,建议回顾一下我的「什么是空燃比,燃油修正和 AFM 曲线——兼谈如何通过 Hondata Log 数据了解你的进气组件是否正常工作」这篇文章。


好,目前我们已经知道了整个流程,但是手动修 AFM 曲线听上去就过于「匠人」了,我们仔细想一下 AFM.v - S.Trim 图,其实就是把 Datalog 中每一帧的 AFM.v 和 S.Trim 给放在了散点图上,且:

明白了上面的点之后我们就会发现,如果我们要用 Hondata 手动修正 AFM 曲线的话,我们需要有多段不同的 Datalog,或者一个 Datalog 中覆盖大量的场景,考虑到我们不是在台架上进行实验,更加真实的情况是有多段不同时间录制的 Datalog,那我们就需要手动一个个看对应 Datalog 的 XY 图,并尝试找出共性,并加以修正。

这太慢了!

Automated Calibration

我们需要一个可以自动化分析 Datalog 并给 AFM 修正的能力,流程分为如下几步:

Export to CSV

好在 Hondata 给我们提供了导出为 CSV 的功能:

导出之后的 CSV 除了行首有些垃圾行以外,每一行就是每一帧的所有传感器的数据:

这样我们便可以导出多个 Datalog 的 CSV 并合并在一起,获得大量不同时间,不同工况的 Datalog 数据。

CSV to Dataframe

在上一步中我们拥有了大量的数据,现在我们就可以尝试导入到 Dataframe 中进行分析了:

Fuel Status 为 2 表示闭环状态,我们只希望修正闭环(非 WOT(全油门))部分

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

df = pd.read_csv('exported.csv')

# Only reserve the rows with 'Fuel Status' = 2
df = df[df['Fuel Status'] == 2]

x = df['AFM.v']
y = df['S.TRIM']

plt.scatter(x, y, label='Data Points', color='blue', alpha=0.5)

bins = np.linspace(x.min(), x.max(), 100)
bin_centers = 0.5 * (bins[:-1] + bins[1:])
mean_values = [y[(x >= bins[i]) & (x < bins[i + 1])].mean() for i in range(len(bins) - 1)]

plt.plot(bin_centers, mean_values, label='Mean Curve', color='red', linewidth=2)

plt.xlabel('AFM.v')
plt.ylabel('S.TRIM')
plt.legend()
plt.title('Scatter Plot and Mean Curve of AFM.v vs S.TRIM')

plt.show()

这里我们使用 np.linspace 把数据分成 100 个分箱并计算平均值,然后画出平均值曲线

是不是看上去和 Hondata 的 XY 图一样?

Import AFM and adjust

有了上面的 Dataframe 和对应的平均值之后,我们可以导入目前已有的 AFM 表格的 电压-进气量 关系,在 Hondata 中,AFM 表格有 64 列,下面 k_values 为电压值,v_values 为标定进气量(g/s):

k_values = [
    0.00, 0.00, 0.35, 0.43, 0.51, 0.59, 0.66, 0.74, 0.82, 0.90, 0.98, 1.05, 1.13, 1.21, 1.29, 1.33, 1.37, 1.41, 1.45, 1.52,
    1.56, 1.60, 1.68, 1.72, 1.76, 1.84, 1.88, 1.91, 1.99, 2.03, 2.07, 2.15, 2.19, 2.23, 2.30, 2.34, 2.38, 2.46, 2.50, 2.54,
    2.62, 2.70, 2.77, 2.85, 2.93, 3.01, 3.09, 3.16, 3.24, 3.32, 3.40, 3.48, 3.55, 3.63, 3.71, 3.79, 3.87, 4.02, 4.18, 4.34,
    4.49, 4.65, 4.84, 5.00
]
v_values = [
    0.00, 0.00, 0.00, 0.00, 0.03, 0.08, 0.17, 0.28, 0.43, 0.62, 0.87, 1.16, 1.48, 1.93, 2.34, 2.60, 2.88, 3.25, 3.58, 4.31,
    4.70, 5.10, 5.98, 6.46, 6.97, 8.11, 8.55, 9.19, 10.54, 11.25, 12.00, 13.18, 14.00, 15.15, 17.04, 18.05, 19.44, 21.63,
    23.24, 24.45, 27.06, 29.89, 32.82, 35.89, 39.23, 42.77, 45.62, 49.55, 53.67, 57.47, 61.44, 66.23, 71.30, 76.67, 80.70,
    86.52, 92.63, 105.67, 119.80, 135.13, 151.92, 170.44, 196.45, 220.14
]

df_kv = pd.DataFrame({'AFM.v': k_values, 'AFM Intake': v_values})

然后我们使用线性插值的方式将上文提到的 Mean 曲线插值在 k_values 上,并找到和对应的 v_values 的差异:

expected_values = np.interp(df_kv['AFM.v'], bin_centers, mean_values)
expected_values = np.nan_to_num(expected_values, nan=0.0)

之后我们根据百分比计算需要调整的差异量即可:

df_kv['AFM Intake Adjusted'] = df_kv['AFM Intake'] * (expected_values/100 + 1)

print(df_kv.to_string())

看,这样就可以啦!

    AFM.v  AFM Intake  AFM Intake Adjusted
0    0.00        0.00             0.000000
1    0.00        0.00             0.000000
2    0.35        0.00             0.000000
3    0.43        0.00             0.000000
4    0.51        0.03             0.029600
5    0.59        0.08             0.078933
6    0.66        0.17             0.167733
7    0.74        0.28             0.276267
8    0.82        0.43             0.424267
...
43   2.85       35.89            35.015254
44   2.93       39.23            38.783246
45   3.01       42.77            41.663699
46   3.09       45.62            44.038772
47   3.16       49.55            48.285323
48   3.24       53.67            53.670000
49   3.32       57.47            55.442512
...

我们还可以将调整前后的曲线叠加在一起展示出来:

plt.plot(df_kv['AFM.v'], df_kv['AFM Intake'], label='Original', color='blue')
plt.plot(df_kv['AFM.v'], df_kv['AFM Intake Adjusted'], label='Adjusted', color='red')

Hondata Auto AFM Correction Website

有了这样的想法之后,我便想到制作一个简单的网站,用户只要上传 Datalog 的 CSV 文件和当前的 AFM 表格即可自动计算,于是继续和 WebP Cloud Services 的御用前端 Tuki Deng 合作,制作了 Hondata Auto AFM Correction 网站,域名是:https://hondata.nova.moe

欢迎大家来体验!

#Chinese #Car #Tuning