Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-加速度计以1 kHz的速率读取和写入CSV文件_Python_Csv_Raspberry Pi_Accelerometer_I2c - Fatal编程技术网

Python-加速度计以1 kHz的速率读取和写入CSV文件

Python-加速度计以1 kHz的速率读取和写入CSV文件,python,csv,raspberry-pi,accelerometer,i2c,Python,Csv,Raspberry Pi,Accelerometer,I2c,我试图使用MPU-6000加速计和Raspberry Pi Zero W记录挡风玻璃中的振动数据。我是Python的新手,所以请容忍我 我已经编写了一个python2脚本,它将MPU-6000配置为通过I2C进行通信,时钟配置为400khz。 当加速计寄存器中有新数据可用时,MPU-6000发出中断,该数据被读取、转换为2的补码,然后与时间戳一起写入CSV文件。加速计的输出速率配置为1 kHz 我发现,在对所有三个传感器轴进行采样时,脚本无法将所有数据点写入CSV文件。我得到的是大约650个数据

我试图使用MPU-6000加速计和Raspberry Pi Zero W记录挡风玻璃中的振动数据。我是Python的新手,所以请容忍我

我已经编写了一个python2脚本,它将MPU-6000配置为通过I2C进行通信,时钟配置为400khz。 当加速计寄存器中有新数据可用时,MPU-6000发出中断,该数据被读取、转换为2的补码,然后与时间戳一起写入CSV文件。加速计的输出速率配置为1 kHz

我发现,在对所有三个传感器轴进行采样时,脚本无法将所有数据点写入CSV文件。我得到的是大约650个数据点,而不是1000个数据点的轴公关秒。 我试着只写了一个axis,它以每秒1000个数据点的速度被证明是成功的。我知道MPU-6000有一个FIFO寄存器可用,我可能可以突发读取以获得1000个样本/秒而没有任何问题。问题是要为每个样本获取一个时间戳,所以我还没有尝试从FIFO寄存器实现读取

我很可能会在Matlab中完成大部分后处理,因此python脚本应该做的最重要的事情是以确定的速率将任何形式的传感器数据写入CSV文件,并带有时间戳

有没有办法进一步改进我的Python脚本,这样我就可以对所有三个轴进行采样,并以1 kHz的速率写入CSV文件

我的部分脚本如下所示:

#!/usr/bin/python
import smbus
import math
import csv
import time
import sys
import datetime

# Register addresses
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c
samlerate_divider = 0x19
accel_config = 0x1C
INT_Enable = 0x38



def read_byte(reg):
    return bus.read_byte_data(address, reg)

def read_word(reg):
    h = bus.read_byte_data(address, reg)
    l = bus.read_byte_data(address, reg+1)
    value = (h <<8)+l
    return value

def read_word_2c(reg):
    val = read_word(reg)

    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val



csvwriter = None

def csv_open():
    csvfile = open('accel-data.csv', 'a')

    csvwriter = csv.writer(csvfile)




def csv_write(timedelta, accelerometerx, accelerometery, accelerometerz):

    global csvwriter

    csvwriter.writerow([timedelta,  accelerometerx, accelerometery, 
    accelerometerz])



# I2C configs
bus = smbus.SMBus(1) 
address = 0x69       

#Power management configurations
bus.write_byte_data(address, power_mgmt_1, 0)
bus.write_byte_data(address, power_mgmt_2, 0x00)


#Configure sample-rate divider
bus.write_byte_data(address, 0x19, 0x07)


#Configure data ready interrupt:
bus.write_byte_data(address,INT_Enable, 0x01) 



#Opening csv file and getting ready for writing
csv_open()

csv_write('Time', 'X_Axis', 'Y_Axis', 'Z_Axis') 

print
print "Accelerometer"
print "---------------------"

print "Printing acccelerometer data: "

#starttime = datetime.datetime.now()

while True:


    data_interrupt_read =  bus.read_byte_data(address, 0x3A)

    if data_interrupt_read == 1:


        meas_time = datetime.datetime.now()
#       delta_time = meas_time - starttime


        accelerometer_xout = read_word_2c(0x3b)
        accelerometer_yout = read_word_2c(0x3d)
        accelerometer_zout = read_word_2c(0x3f)

#       accelerometer_xout = read_word(0x3b)
#       accelerometer_yout = read_word(0x3d)
#       accelerometer_zout = read_word(0x3f)

#       accelerometer_xout_scaled = accelerometer_xout / 16384.0
#       accelerometer_yout_scaled = accelerometer_yout / 16384.0
#       accelerometer_zout_scaled = accelerometer_zout / 16384.0



#       csv_write(meas_time, accelerometer_xout_scaled, 
        accelerometer_yout_scaled, accelerometer_zout_scaled)

        csv_write(meas_time, accelerometer_xout, accelerometer_yout, 
        accelerometer_zout) 


    continue
#/usr/bin/python
导入smbus
输入数学
导入csv
导入时间
导入系统
导入日期时间
#注册地址
电源管理1=0x6b
电源管理2=0x6c
samlerate_除法器=0x19
加速配置=0x1C
INT_Enable=0x38
def读取字节(reg):
返回总线。读取字节数据(地址,寄存器)
def读取字(reg):
h=总线读取字节数据(地址,寄存器)
l=总线读取字节数据(地址,reg+1)

值=(h如果您试图写入的数据是连续的,那么最好的方法是尽量减少写入数据所需的处理量,同时也尽量减少写入的数据量。为此,一个好的方法是将原始数据写入二进制格式的文件中。然后,每个数据字只需要写入2个字节datetime对象可以转换为需要4个字节的时间戳。因此,您可以使用以下格式:

[4 byte timestamp][2 byte x][2 byte y][2 byte z]
Python的
struct
库可用于将多个变量转换为一个可写入文件的二进制字符串。数据似乎是有符号的,如果是这种情况,您可以尝试按原样写入单词,然后使用内置的支持有符号值的库在以后将其读回

例如,可以使用以下命令将原始数据写入二进制文件:

#!/usr/bin/python
import smbus
import math
import csv
import time
import sys
import datetime
import struct

# Register addresses
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c
samlerate_divider = 0x19
accel_config = 0x1C
INT_Enable = 0x38


def read_byte(reg):
    return bus.read_byte_data(address, reg)


def read_word(reg):
    h = bus.read_byte_data(address, reg)
    l = bus.read_byte_data(address, reg+1)
    value = (h <<8)+l
    return value


# I2C configs
bus = smbus.SMBus(1) 
address = 0x69       

#Power management configurations
bus.write_byte_data(address, power_mgmt_1, 0)
bus.write_byte_data(address, power_mgmt_2, 0x00)

#Configure sample-rate divider
bus.write_byte_data(address, 0x19, 0x07)

#Configure data ready interrupt:
bus.write_byte_data(address, INT_Enable, 0x01) 


print
print "Accelerometer"
print "---------------------"

print "Printing accelerometer data: "

#starttime = datetime.datetime.now()
bin_format = 'L3H'

with open('accel-data.bin', 'ab') as f_output:
    while True:
        #data_interrupt_read =  bus.read_byte_data(address, 0x3A)
        data_interrupt_read = 1

        if data_interrupt_read == 1:
            meas_time = datetime.datetime.now()
            timestamp = time.mktime(meas_time.timetuple())

            accelerometer_xout = read_word(0x3b)
            accelerometer_yout = read_word(0x3d)
            accelerometer_zout = read_word(0x3f)

            f_output.write(struct.pack(bin_format, timestamp, accelerometer_xout, accelerometer_yout, accelerometer_zout))
!/usr/bin/python
导入smbus
输入数学
导入csv
导入时间
导入系统
导入日期时间
导入结构
#注册地址
电源管理1=0x6b
电源管理2=0x6c
samlerate_除法器=0x19
加速配置=0x1C
INT_Enable=0x38
def读取字节(reg):
返回总线。读取字节数据(地址,寄存器)
def读取字(reg):
h=总线读取字节数据(地址,寄存器)
l=总线读取字节数据(地址,reg+1)

value=(h请编辑您的问题以修复代码的缩进,因为它(我相信您知道)是Python语言的一部分,它的缺失会影响代码的含义!我建议您使用自己的二进制格式(而不是CSV)编写数据,这会快得多,因为写入文件的处理和字节会更少。如果需要,您可以在之后使用单独的脚本将二进制格式转换为CSV。查看struct库。一个好的测试可能是注释掉对CSV的写入,并查看您的代码是否以您希望的速率读取所有三个通道r、 您正在与读取同步写入-您可以使用python线程或多处理来分隔这两个活动-您可以“写入”csv转换为字符串,并且每秒只写入磁盘,或者您可以使用@MartinEvans建议写入二进制数据,稍后再转换为csv。是的,我知道Python中的代码缩进,现在已更正。缩进在我的文本编辑器中是正确的,但在我将代码导出到StackOverflow时丢失了。二进制格式可能是一个解决方案,也许我可以今天将对其进行测试。到目前为止,我确定采样率的方法是根据生成的csv文件中的行号查看时间戳。我可能会实现pin切换,以确定是否以我所需的速率读取所有三个通道。线程和多处理对我来说也是新课题,我必须进一步查看其文档。允许可变数据采样的另一种方法是用读数记录一个高分辨率的时间戳-这样你就不必猜测或假设1ms/样本。事实上,你可以在采样之前/之后记录时间戳,以获得更高的准确度,以确定实际采样的时间。
from datetime import datetime
import csv
import struct

bin_format = 'L3h'  # Read data as signed words
entry_size = struct.calcsize(bin_format)

with open('accel-data.bin', 'rb') as f_input, open('accel-data.csv', 'wb') as f_output:
    csv_output = csv.writer(f_output)
    csv_output.writerow(['Time', 'X_Axis', 'Y_Axis', 'Z_Axis'])

    while True:
        bin_entry = f_input.read(entry_size)

        if len(bin_entry) < entry_size:
            break

        entry = list(struct.unpack(bin_format, bin_entry))
        entry[0] = datetime.fromtimestamp(entry[0]).strftime('%Y-%m-%d  %H:%M:%S')
        csv_output.writerow(entry)