Самый эффективный способ хранения данных с датчика при использовании Python на Raspberry Pi - PullRequest
4 голосов
/ 21 февраля 2020

Я использую данные чтения SPI из IMU LSM9DS1. Я хочу сохранить данные в файл. Я пытался сохранить как текстовый файл, используя with open as file и .write. скорость составляет 0,002 с.

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 раз, как и раньше .

Ответы [ 2 ]

0 голосов
/ 21 февраля 2020

Как я сказал в комментариях: "Ответ значительно отличается в зависимости от того, что вы пытаетесь сделать! Если гироскоп на дроне, и вы отправляете данные в P C для управления направлением необходимо получить последнее значение для P C с минимальной задержкой - это не требует хранения, и данные за 4 секунды go бесполезны. Если вы проводите эксперимент для Через 4 часа и проанализировав результаты, вы, вероятно, захотите прочитать гироскоп с максимальной скоростью, сохраняя все локально и передавая его в конце - это требует больше памяти. "

Самое быстрое место для хранить большое количество образцов в списке в ОЗУ:

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))

Тест

Запуск в I Python на моем рабочем столе, это может хранить 2,8 млн. кортежей в секунду, каждый из которых содержит время и 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)
0 голосов
/ 21 февраля 2020

Некоторые идеи, которые могут улучшить скорость и которые вы можете попробовать:

  1. использовать двоичный формат вместо текста - записать двоичное время (см .: Запись и чтение Datetime в двоичный формат в Python) и писать двоичные числа с плавающей точкой. Вы можете обработать их позже в автономном режиме.
  2. вызовите get_a cc и get_gyro параллельно
  3. сохраните некоторое количество измерений в памяти и запишите их целый буфер сразу, вместо того, чтобы вызывать запись много раз
  4. имеет отдельный поток для записи и отдельный поток для получения измерений
  5. переписать в C
...