在 Raspberry Pi 上使用 Python 从传感器存储数据的最有效方法

Posted

技术标签:

【中文标题】在 Raspberry Pi 上使用 Python 从传感器存储数据的最有效方法【英文标题】:The most efficient way to store data from sensor using Python on Raspberry Pi 【发布时间】:2020-02-21 11:57:03 【问题描述】:

我正在使用 SPI 从 IMU LSM9DS1 读取数据。我想将数据存储到文件中。我尝试使用with open as file.write 保存为txt 文件。速度为0.002s。

while flag:
    file_path_g = '/home/pi/Desktop/LSM9DS1/gyro.txt'
    with open(file_path_g, 'a') as out_file_g:
        dps = dev.get_gyro()
        out_file_g.write(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
        out_file_g.write(" 0:0.3f, 1:0.3f, 2:0.3f\n".format(dps[0], dps[1], dps[2]))

    file_path_a = '/home/pi/Desktop/LSM9DS1/accel.txt'
    with open(file_path_a, 'a') as out_file_a:
        acc = dev.get_acc()
        out_file_a.write(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
        out_file_g.write(" 0:0.3f, 1:0.3f, 2:0.3f\n".format(acc[0], acc[1], acc[2]))
    # time.sleep(0.2)

print("interrupt occured")

dev.close()

我还尝试使用 pandas 将数据保存为 .csv 文件。速度比第一个慢。

while flag:
    t = time.time()
    acc = dev.get_acc()
    dps = dev.get_gyro()
    ax = acc[0]
    ay = acc[1]
    az = acc[2]
    gx = dps[0]
    gy = dps[1]
    gz = dps[2]
    result = pd.DataFrame('time':t, 'ax':ax,'ay':ay,'az':az,'gx':gx,'gy':gy,'gz':gz,index=[0])
    result.to_csv('/home/pi/Desktop/LSM9DS1/result.csv', mode='a', float_format='%.6f',
    header=False, index=0)

dev.close()

如何提高阅读速度?

我更新了路径之外的代码。

file_path = '/home/pi/Desktop/LSM9DS1/result.txt'
while flag:
    with open(file_path, 'a') as out_file:
        acc = dev.get_acc()
        dps = dev.get_gyro()
        out_file.write(datetime.datetime.now().strftime('%S.%f'))
        out_file.write(" 0:0.3f, 1:0.3f, 2:0.3f".format(acc[0], acc[1], acc[2]))
        out_file.write(" 0:0.3f, 1:0.3f, 2:0.3f\n".format(dps[0], dps[1], dps[2]))

这是另一种方式

while flag:
    t = time.time()
    acc = dev.get_acc()
    dps = dev.get_gyro()
    arr = [t, acc[0], acc[1], acc[2], dps[0], dps[1],dps[2]],
    np_data = np.array(arr)
    result = pd.DataFrame(np_data,index=[0])
    result.to_csv('/home/pi/Desktop/LSM9DS1/result.csv', mode='a', float_format='%.6f', header=False, index=0)

感谢马克的回答。我照他说的做了,改代码如下。

samples=[]
for i in range(100000):
    t = time.time()
    acc = dev.get_acc()
    dps = dev.get_gyro()
    # Append a tuple (containing time, acc and dps) onto sample list
    samples.append((t, acc, dps))

name = ['t','acc','dps']
f = pd.DataFrame(columns=name,data=samples)
f.to_csv('/home/pi/Desktop/LSM9DS1/result.csv', mode='a', float_format='%.6f', header=False, index=0)
print('done')

我计算了时间空间(前600个数据),平均值为0.000265,比以前快了很多,几乎是以前的10倍。

【问题讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 我的回答解决了您的问题吗?如果是这样,请考虑接受它作为您的答案 - 通过单击计票旁边的空心对勾/复选标记。如果没有,请说出什么不起作用,以便我或其他人可以进一步为您提供帮助。谢谢。 meta.stackexchange.com/questions/5234/… 【参考方案1】:

正如我在 cmets 中所说的:“答案非常不同,具体取决于您要做什么!如果陀螺仪在无人机上,并且您将数据发送到电脑控制方向,你需要以最小的延迟将最新的读数送到电脑上——这不需要存储,4秒前的数据是没有用的。如果你运行一个实验4个小时,然后再分析结果,您可能希望以最大速率读取陀螺仪,将其全部存储在本地并在最后传输 - 这需要更多存储空间。”

存储大量样本最快的地方是在 RAM 中的列表中:

samples=[]
while flag:
    t = time.time()
    acc = dev.get_acc()
    dps = dev.get_gyro()
    # Append a tuple (containing time, acc and dps) onto sample list
    samples.append((t, acc, dps))

基准测试

在我的桌面上在 IPython 中运行,每秒可以存储 280 万个元组,每个元组包含时间和 2 个列表,每个列表包含 3 个元素:

In [92]: %%timeit 
...:  
...: samples=[] 
...: for i in range(2800000): 
...:     t = time.time() 
...:     acc = [1,2,3] 
...:     dps = [4,5,6] 
...:     # Append a tuple (containing time, acc and dps) onto sample list 
...:     samples.append((t, acc, dps))

1.05 s ± 7.13 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

你好马克,我想知道将数据保存到文件的速度是否有影响。当保存速度比读取慢时,我们会不会丢失一些数据? 我展示的代码没有写入文件。它将样本存储在内存 (RAM) 中的 Python 列表中。 如果我想将“样本”存储到文件中该怎么办,另一个答案说最好保存为二进制格式的文件。我尝试使用“struct”,TypeError 说“需要一个类似字节的对象,而不是 'tuple'” 我建议您在实验期间将数据存储在内存中,因为您说您希望尽可能快地进行,并且内存比磁盘快 1000 倍。然后,我建议您在实验结束时将数据写入磁盘,无论需要 12 秒还是 15 秒都没有关系。所以磁盘上的格式并不重要。 非常感谢!我试图将数据保存为 csv 文件,但第二列和第三列中的值也是一个列表。如何在 MATLAB 中读取数据。【参考方案2】:

一些可以提高速度的想法,您可以尝试一下:

    使用二进制格式而不是文本 - 写入二进制时间(参见: Write and read Datetime to binary format in Python) 并写二进制浮点数。您可以稍后离线处理它们。 并行调用 get_acc 和 get_gyro 在内存中存储一​​些测量值并写入整个缓冲区 一次调用而不是多次调用 write 有单独的线程用于写入和单独的线程用于获取 测量 用 C 重写

【讨论】:

感谢您的建议,我先尝试使用二进制格式,之后我可以将其更改为浮动。

以上是关于在 Raspberry Pi 上使用 Python 从传感器存储数据的最有效方法的主要内容,如果未能解决你的问题,请参考以下文章

在Raspberry Pi上安装mitmproxy时出现python问题

在 Raspberry PI 上使用 Python 和 OpenCV 进行图像处理 [关闭]

如何使用 Python 在 Raspberry Pi 上杀死 omxplayer 播放器

并行计算Python / Raspberry Pi

在 Raspberry Pi 上使用 Python 从传感器存储数据的最有效方法

从 Apache Laravel PHP 控制器在 Raspberry PI 上执行 python 脚本