基于摩擦纳米发电 TENG 的刹车检测系统开发文档

目的

针对近几年经常出现的刹车失灵事件,市面上出现了一些针对踏板(刹车、油门/电门)的监控设备,主要对驾驶员的脚下操作进行记录,但市面上的设备大多都是基于摄像头来捕获驾驶员的动作,如下图所示产品:

刹车记录仪

可以说这类产品继承了摄像头的所有缺点,包括但不限于遮挡、光线、发热、存储等问题。

该项目基于这些痛点,借助摩擦纳米发电机(TENG)类似于压电效应的特性,通过驾驶员对踏板的踩踏,敏感单元将其产生的机械信号转化为电信号,

硬件开发

结构

市面上大多数汽车的踏板可分为两种 —— “地板式”(右)和“悬挂式”(左),如下图所示:

两种踏板

同时,不同的车型其踏板设计也必然不同,因此就需要该产品必须模块化,我们将产品分为以下几个模块:

  1. 结构单元:根据具体车型的踏板进行设计外壳(可参考国标),外壳主要功能为保护敏感单元;
  2. 敏感单元:主要功能为将驾驶员踩踏的机械信号转化为电信号;
  3. 电路单元:主要功能为采集敏感单元输出的电信号并将其无线传输到终端设备。

综上,可知,结构单元需要根据实际车型的不同来进行适配,即所谓定制化。

材料

聚甲醛 1.3 - 1.4 (接左栏)
乙基纤维素 聚酯(Dacron)
聚酰胺(尼龙)- 11 聚异丁烯
聚酰胺(尼龙)- 66 聚氨酯,柔性海绵
三聚氰胺 聚对苯二甲酸乙二醇酯(PET)
编织的羊毛 聚乙烯醇缩丁醛
编制的蚕丝 氯丁橡胶
自然橡胶
纸张 聚丙烯腈
纺织的棉花 腈氯纶
聚碳酸双酚
木材 聚 2,2 - 双(氢甲基)丁氧环
硬橡胶 聚偏二氯乙烯(Saran)
镍,铜 聚苯乙烯
聚乙烯
黄铜,银 聚丙烯
酷酸纤维,人造纤维 聚酰亚胺(Kapton)
聚甲基丙烯酸甲酯(Lucite) 聚氯乙烯(PVC)
聚乙烯醇 聚二甲基硅氧烷(PDMS)
(转右栏) 聚四氟乙烯(Teflon)

左上显正电性最强、右下显负电性最强。

电路

电路部分主要分为整流和放大两个模块。

整流

该电路模块主要作用为将摩擦纳米发电机(TENG)即敏感单元产生的交流电转化为直流电。

整流电路

放大

该电路模块主要作用为放大整流后的直流电压,使其能够被单片机准确的检测到且不易被外部干扰。

放大电路

软件开发

嵌入式

主控板选用 ESP32 S3 DevkitC-1,可采用 ESP-IDF 或 Arduino 框架进行开发,主要功能有:

  1. 读取经由 PCB 处理的输出信号;
  2. 将信号分解为以下几个维度;
    • 信号持续时间
    • 输出频率
    • 波峰数量
    • 波峰间隔时间(应当为数组)
    • 峰峰值
  3. 将数据通过 WIFI 传输到 PC 端进行后期处理;

深度学习

深度学习算法主要采用 CNN 卷积神经网络对数据进行预测,下面将从数据集准备、算法编写两个方面来介绍。

数据集

如前文所说,数据集需要准备信号持续时间、输出频率、波峰数量、波峰间隔时间和峰峰值这几列数据,然后加上一个标签,例如急刹、点刹等(该分类标准有待确定)。

综上,我们可以认为一组格式正确的数据应当如下:

标签 信号持续时间 波峰数量 波峰间隔时间 峰峰值
急刹 0.3 1 [] 10.3

而所谓数据集则是由大量的上述数据构成的集合。

算法

代码的整体思路是使用卷积神经网络(CNN)对汽车刹车信号进行分类。具体来说:

  1. 它首先读取 CSV 文件并对数据进行预处理;
  2. 然后将数据划分为训练集和测试集;
  3. 接下来,它使用 TensorBoard 可视化模型,并定义、编译和检查模型;
  4. 然后,它使用测试集对模型进行测试,并输出测试损失、测试准确率和预测标签列表;
  5. 最后,它使用 Keras 的 plot_model 函数将模型结构保存为 PNG 文件。

整个代码的目的是训练一个能够准确分类汽车刹车信号的模型,并对模型进行评估和可视化。

1
2
3
4
5
6
import pandas as pd
import numpy as np
import tensorflow as tf
from keras import layers, models
import os
import datetime

这里导入了一些必要的 Python 库,包括 Pandas 用于读取 CSV 文件,NumPy 用于数据处理,TensorFlow 用于构建和训练模型,Keras 用于定义模型,os 用于文件操作,datetime 用于记录时间。

1
2
3
4
def read_data(file_path):
"""读取CSV文件"""
data = pd.read_csv(file_path)
return data

这个函数用于读取 CSV 文件,它接受一个文件路径作为参数,并返回一个 Pandas DataFrame 对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def preprocess_data(data):
"""预处理数据"""
# 将"波峰间隔时间"列转换为列表
data['波峰间隔时间'] = data['波峰间隔时间'].apply(lambda x: [float(i) for i in x.strip('[]').split()])

# 将标签列转为数字编码
label_map = {'急刹': 0, '点刹': 1}
data['标签'] = data['标签'].map(label_map)

# 将"波峰间隔时间"一栏单独填充
padded_intervals = tf.keras.preprocessing.sequence.pad_sequences(data['波峰间隔时间'].tolist(), maxlen=10, dtype='float32', padding='post', truncating='post')

# 将填充的"波间隔时间"列与其他列结合起来
data[['信号持续时间', '波峰数量', '峰峰值']] = data[['信号持续时间', '波峰数量', '峰峰值']].to_numpy(dtype='float32')
combined_data = np.hstack((data[['信号持续时间', '波峰数量', '峰峰值']].to_numpy(), padded_intervals))

return combined_data

这个函数用于对数据进行预处理,它接受一个 Pandas DataFrame 对象作为参数,并返回一个 NumPy 数组。在这个函数中,我们将波峰间隔时间列转换为列表,并将标签列转换为数字编码。然后,我们使用 Keras 的 pad_sequences 函数对波峰间隔时间列进行填充,使其长度为10。最后,我们将填充后的波峰间隔时间列与其他列合并,并返回一个 NumPy 数组。

1
2
3
4
5
def split_data(data, train_ratio=0.8):
"""划分训练集测试集"""
train_data = data[:int(len(data)*train_ratio)]
test_data = data[int(len(data)*train_ratio):]
return train_data, test_data

这个函数用于将数据划分为训练集和测试集,它接受一个 NumPy 数组作为参数,并返回两个 NumPy 数组,分别表示训练集和测试集。默认情况下,它将数据的80%用于训练,20%用于测试。

1
2
3
4
5
6
7
8
9
10
def create_model():
"""定义CNN模型"""
model = models.Sequential([
layers.Conv1D(32, 3, activation='relu', input_shape=(13, 1)),
layers.MaxPooling1D(2),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(2, activation='softmax')
])
return model

这个函数用于定义 CNN 模型,它返回一个 Keras 模型对象。在这个模型中,我们使用了一个卷积层,一个最大池化层,一个展平层,两个全连接层和一个 softmax 层。输入形状为(13,1),表示有 13 个特征和 1 个通道。

1
2
3
4
5
6
def compile_model(model):
"""编译模型"""
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model

这个函数用于编译模型,它接受一个 Keras 模型对象作为参数,并返回编译后的模型。在这个函数中,我们使用了 Adam 优化器,稀疏分类交叉熵损失和准确率指标。

1
2
3
4
5
6
7
8
9
10
def check_model_file(model, train_data, tensorboard_callback):
"""检查模型文件是否存在,如果存在则加载模型,否则训练模型并保存"""
if os.path.exists('model/model.h5'):
model.load_weights('model/model.h5')
else:
x_train = train_data[:, :, np.newaxis]
y_train = train_data[:, -1].astype(int)
model.fit(x_train, y_train, epochs=10, callbacks=[tensorboard_callback])
model.save_weights('model/model.h5')
return model

这个函数用于检查模型文件是否存在,如果存在则加载模型,否则训练模型并保存。它接受一个 Keras 模型对象、一个训练集 NumPy 数组和一个 TensorBoard 回调对象作为参数,并返回训练好的模型。如果模型文件存在,则加载模型权重;否则,将训练集输入到模型中进行训练,并保存模型权重。

1
2
3
4
5
6
def evaluate_model(model, test_data):
"""测试模型"""
x_test = test_data[:, :, np.newaxis]
y_test = test_data[:, -1].astype(int)
test_loss, test_acc = model.evaluate(x_test, y_test)
return test_loss, test_acc

这个函数用于测试模型,它接受一个 Keras 模型对象和一个测试集 NumPy 数组作为参数,并返回测试损失和测试准确率。

1
2
3
4
5
6
7
8
def predict_labels(model, test_data, label_map):
"""输出预测结果"""
x_test = test_data[:, :, np.newaxis]
predictions = model.predict(x_test)
predicted_labels = [list(label_map.keys())[list(label_map.values()).index(np.argmax(prediction))] for prediction in predictions]
print("模型的预测结果:", predictions)
print("标签映射:", label_map)
return predicted_labels

这个函数用于输出模型的预测结果,它接受一个 Keras 模型对象、一个测试集 NumPy 数组和一个标签映射字典作为参数,并返回预测标签列表。在这个函数中,我们使用模型对测试集进行预测,并将预测结果转换为标签列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def main():
file_path = 'data/1.csv'
data = read_data(file_path)
combined_data = preprocess_data(data)
train_data, test_data = split_data(combined_data)

# 使用TensorBoard可视化模型
log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)

model = create_model()
model = compile_model(model)
model = check_model_file(model, train_data, tensorboard_callback)

test_loss, test_acc = evaluate_model(model, test_data)
print("Test loss:", test_loss)
print("Test accuracy:", test_acc)

label_map = {'急刹': 0, '点刹': 1}
predicted_labels = predict_labels(model, test_data, label_map)
print(predicted_labels)

tf.keras.utils.plot_model(model, to_file='model/model.png', show_shapes=True)
return

if __name__ == '__main__':
main()

这个函数是主函数,它调用了前面定义的所有函数来完成模型的训练和测试。在这个函数中,我们首先读取 CSV 文件并对数据进行预处理,然后将数据划分为训练集和测试集。接下来,我们使用 TensorBoard 可视化模型,并定义、编译和检查模型。然后,我们使用测试集对模型进行测试,并输出测试损失、测试准确率和预测标签列表。最后,我们使用 Keras 的 plot_model 函数将模型结构保存为 PNG 文件。