You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过树莓派Pico读取MPU6050仅获100样本/秒,求提升至1kHz方案

问题描述

我需要采集MPU6050的加速度计、陀螺仪及温度原始数据,硬件配置为MPU6050与树莓派Pico焊接,Pico通过USB连接笔记本电脑。当前采样率仅约100样本/秒,但MPU6050 datasheet标称至少支持1kHz采样率。我使用Python的pyserial库接收数据,Pico侧采用UART通信(波特率115200),串口通信本身无问题,但Pico读取MPU6050数据的速度不足,serial.in_waiting()返回大量空字节。以下是现有代码,求提升采样率的解决方法:

现有代码

Pico侧代码(main.py)

from imu import MPU6050
import utime
import time
from machine import Pin, I2C, UART

i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
imu = MPU6050(i2c)

uart = UART(0, baudrate=115200)
print("UART Info : ", uart)

while True:
    ax = round(imu.accel.x, 2)
    ay = round(imu.accel.y, 2)
    az = round(imu.accel.z, 2)
    gx = round(imu.gyro.x)
    gy = round(imu.gyro.y)
    gz = round(imu.gyro.z)
    tem = round(imu.temperature, 2)
    print(ax, ay, az, gx, gy, gz, tem)

Python侧代码

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

ser = serial.Serial('COM4', 115200)
print(ser)

file = open("serial_sample.csv", "w")
start_time = time.time()
curr_time = time.time()
output_list = []
header_string = "X_accel" + "," + "Y_accel" + "," + "Z_accel" + "," + "X_Pos" + "," + "Y_Pos" + "," + "Z_Pos" \
     + "," + "Temperature" + "\n"

output_list.append(header_string)
while curr_time - start_time < 10:
    data = ser.readline()
    data = str(data).split("\\")[0].split(" ")
    output = data[0].split("'")[1] + "," + data[1] + "," + data[2] + "," + data[3] + "," + data[4] + "," + data[5] + "," + data[6] + "\n"
    output_list.append(output)
    curr_time = time.time()

file.writelines(output_list)
file.close()
优化方案

1. 提升Pico侧MPU6050读取效率

  • 减少I2C调用次数:原代码每次访问imu.accel.x、imu.gyro.x等属性都会单独发起I2C读取,改为一次性读取所有传感器数据,降低总线开销。
  • 跳过不必要的浮点运算:round()操作会占用Pico计算资源,将数据格式化逻辑转移到Python侧处理。
  • 强制设置1kHz采样率:MPU6050默认采样率可能未达1kHz,通过寄存器配置:采样率公式为Sample Rate = 8000Hz / (1 + SMPLRT_DIV),设置SMPLRT_DIV=7即可得到1kHz采样率。

2. 优化Pico侧UART输出

  • 替换print为uart.write:print函数会额外处理缓冲和换行逻辑,直接用uart.write发送字节串能大幅提升输出速度。
  • 使用紧凑文本格式:采用逗号分隔的单行字符串,减少数据传输的冗余内容。

3. 改进Python侧接收逻辑

  • 避免readline()阻塞:readline()会等待换行符导致采样延迟,改用批量读取串口缓冲区的可用字节。
  • 实时写入文件:取消将所有数据存入列表的操作,收到数据后立即写入文件,减少内存占用和批量写入耗时。
  • 简化字符串解析:原代码的字符串分割逻辑复杂低效,直接按原始格式解析即可。

修改后的代码示例

Pico侧优化代码

from imu import MPU6050
import utime
from machine import Pin, I2C, UART

# 初始化I2C(MPU6050最高支持400kHz)
i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
imu = MPU6050(i2c)

# 设置MPU6050采样率为1kHz(SMPLRT_DIV寄存器地址0x19,值7)
i2c.writeto_mem(0x68, 0x19, b'\x07')

uart = UART(0, baudrate=115200)

while True:
    # 一次性读取所有传感器数据,减少I2C调用
    accel_data = imu.accel
    gyro_data = imu.gyro
    temp_data = imu.temperature
    # 拼接为紧凑的逗号分隔字符串
    output_str = f"{accel_data.x},{accel_data.y},{accel_data.z},{gyro_data.x},{gyro_data.y},{gyro_data.z},{temp_data}\n"
    # 直接发送字节串
    uart.write(output_str.encode('utf-8'))

Python侧优化代码

import serial
import time

# 设置短超时,避免阻塞
ser = serial.Serial('COM4', 115200, timeout=0.001)
print(ser)

# 用with语句自动管理文件
with open("serial_sample.csv", "w") as file:
    # 修正表头(原表头中X_Pos/Y_Pos/Z_Pos应为陀螺仪数据)
    file.write("X_accel,Y_accel,Z_accel,X_gyro,Y_gyro,Z_gyro,Temperature\n")
    start_time = time.time()
    
    while time.time() - start_time < 10:
        # 批量读取缓冲区所有可用字节
        if ser.in_waiting > 0:
            raw_data = ser.read(ser.in_waiting).decode('utf-8')
            # 按换行分割处理多行数据
            for line in raw_data.split('\n'):
                if line.strip():  # 跳过空行
                    file.write(line + '\n')

内容的提问来源于stack exchange,提问作者Susmita Goswami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:20:25