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

Raspberry Pi Pico搭配MPU6050输出全零问题求助

问题:Raspberry Pi Pico + MPU6050计步器上电后输出全零,I2C通信正常但传感器无数据

我正在使用Raspberry Pi Pico和MPU6050制作计步器,昨晚代码运行正常,今早重新上电后设备输出全零。接线配置为:VCC接3v3、GND接GND、SCL接GP1、SDA接GP0。已尝试更换MPU6050模块和线材、更换引脚并修改对应代码,还使用I2C扫描代码检测到MPU6050设备正常,但原计步代码仍输出全零。看到有资料提到需将PWR_MGMT_1寄存器的SLEEP位拉低,但我不理解其含义,特此求助。

原代码:

# import PIN and I2C from machine library 
from machine import Pin, I2C
import time

# Define I2C bus 
i2c = I2C(0, sda=Pin(0), scl=Pin(1))

# Device address on the I2C bus
MPU6050_ADDR = 0x68

# PWR_MGMT_1 memory address
MPU6050_PWR_MGMT_1 = 0x6B

# Accelerometer's high and low register for each axis
MPU6050_ACCEL_XOUT_H = 0x3B
MPU6050_ACCEL_XOUT_L = 0x3C
MPU6050_ACCEL_YOUT_H = 0x3D
MPU6050_ACCEL_YOUT_L = 0x3E
MPU6050_ACCEL_ZOUT_H = 0x3F
MPU6050_ACCEL_ZOUT_L = 0x40

# Accelerometer's LSB/g (least significant bits per gravitational force) sensitivity
MPU6050_LSBG = 16384.0

# Set all bits in the PWR_MGMT_1 register to 0
def mpu6050_init(i2c):
    i2c.writeto_mem(MPU6050_ADDR, MPU6050_PWR_MGMT_1, bytes([0])) # needs to be 0 to have device in 'awake' mode change to 1 for 'sleep' mode
    
# define x, y, and z values
def accel_x_value(h, l):
    if not h[0] & 0x80:
        return h[0] << 8 | l[0]
    return -((h[0] ^ 255) << 8) |  (l[0] ^ 255) + 1

def accel_y_value(h, l):
    if not h[0] & 0x80:
        return h[0] << 8 | l[0]
    return -((h[0] ^ 255) << 8) |  (l[0] ^ 255) + 1

def accel_z_value(h, l):
    if not h[0] & 0x80:
        return h[0] << 8 | l[0]
    return -((h[0] ^ 255) << 8) |  (l[0] ^ 255) + 1

# Get Accelerometer values
def get_accel_x(i2c):
    accel_x_h = i2c.readfrom_mem(MPU6050_ADDR, MPU6050_ACCEL_XOUT_H, 1)
    accel_x_l = i2c.readfrom_mem(MPU6050_ADDR, MPU6050_ACCEL_XOUT_L, 1)
    return accel_x_value(accel_x_h, accel_x_l) / MPU6050_LSBG        

def get_accel_y(i2c):
    accel_y_h = i2c.readfrom_mem(MPU6050_ADDR, MPU6050_ACCEL_YOUT_H, 1)
    accel_y_l = i2c.readfrom_mem(MPU6050_ADDR, MPU6050_ACCEL_YOUT_L, 1)
    return accel_y_value(accel_y_h, accel_y_l) / MPU6050_LSBG

def get_accel_z(i2c):
    accel_z_h = i2c.readfrom_mem(MPU6050_ADDR, MPU6050_ACCEL_ZOUT_H, 1)
    accel_z_l = i2c.readfrom_mem(MPU6050_ADDR, MPU6050_ACCEL_ZOUT_L, 1)
    return accel_z_value(accel_z_h, accel_z_l) / MPU6050_LSBG


steps = 0 # step counter
while True:
    if get_accel_x(i2c) > 0.6: # minimum x value for counter
        steps += 1
    elif get_accel_y(i2c) > 3: # minimum y value for counter
        steps += 1
    elif get_accel_z(i2c) > 3: # minimum z value for counter
        steps += 1
    print("steps:", steps)
    print("Accelerometer:	", get_accel_x(i2c), get_accel_y(i2c), get_accel_z(i2c), "g") 
    # Print Accelerometer values (X,Y,Z)
    time.sleep(0.75) # Delay between values in seconds

解决方案与说明

1. PWR_MGMT_1寄存器与SLEEP位的含义

MPU6050的PWR_MGMT_1寄存器(地址0x6B)是电源控制核心:

  • 其中第0位(BIT0)为SLEEP位:
    • 当该位为1时,MPU6050进入睡眠模式,加速度计、陀螺仪全部停止工作,此时读取的传感器数据固定为0。
    • 当该位为0时,设备唤醒,传感器正常采集数据,输出有效数值。
  • MPU6050上电后,部分模块可能默认进入睡眠状态,必须主动写入寄存器唤醒。

2. 核心问题:初始化函数未调用

你的代码中定义了mpu6050_init函数用于唤醒设备,但从未执行过这个函数!这就是上电后输出全零的原因——设备一直处于睡眠模式,没有被唤醒。

3. 修正后的代码

只需在主循环前添加mpu6050_init(i2c)调用即可,同时优化计步阈值(原Y/Z轴3g阈值过高,正常走路时Z轴波动约1-2g)和重复读取传感器的问题:

# import PIN and I2C from machine library 
from machine import Pin, I2C
import time

# Define I2C bus 
i2c = I2C(0, sda=Pin(0), scl=Pin(1))

# Device address on the I2C bus
MPU6050_ADDR = 0x68

# PWR_MGMT_1 memory address
MPU6050_PWR_MGMT_1 = 0x6B

# Accelerometer's high and low register for each axis
MPU6050_ACCEL_XOUT_H = 0x3B
MPU6050_ACCEL_XOUT_L = 0x3C
MPU6050_ACCEL_YOUT_H = 0x3D
MPU6050_ACCEL_YOUT_L = 0x3E
MPU6050_ACCEL_ZOUT_H = 0x3F
MPU6050_ACCEL_ZOUT_L = 0x40

# Accelerometer's LSB/g (least significant bits per gravitational force) sensitivity
MPU6050_LSBG = 16384.0

# Set all bits in the PWR_MGMT_1 register to 0
def mpu6050_init(i2c):
    i2c.writeto_mem(MPU6050_ADDR, MPU6050_PWR_MGMT_1, bytes([0])) # 写入0唤醒设备,写入1进入睡眠
    
# 合并加速度值转换函数,减少重复代码
def convert_accel_value(h, l):
    if not h[0] & 0x80:
        return h[0] << 8 | l[0]
    return -((h[0] ^ 255) << 8) |  (l[0] ^ 255) + 1

# 获取三轴加速度数据,一次性读取减少I2C通信
def get_accel_data(i2c):
    # 连续读取6个字节(X_H, X_L, Y_H, Y_L, Z_H, Z_L)
    data = i2c.readfrom_mem(MPU6050_ADDR, MPU6050_ACCEL_XOUT_H, 6)
    x = convert_accel_value([data[0]], [data[1]]) / MPU6050_LSBG
    y = convert_accel_value([data[2]], [data[3]]) / MPU6050_LSBG
    z = convert_accel_value([data[4]], [data[5]]) / MPU6050_LSBG
    return x, y, z

# 初始化设备(关键步骤!)
mpu6050_init(i2c)

steps = 0 # 计步器计数器
# 记录上一次的加速度值,用于检测步数(简单的峰值检测)
last_z = 0
while True:
    x, y, z = get_accel_data(i2c)
    
    # 优化计步逻辑:检测Z轴的峰值变化(走路时Z轴会有明显上下波动)
    if z > 1.5 and last_z < 1.5:
        steps += 1
    last_z = z
    
    print("steps:", steps)
    print("Accelerometer:	", round(x, 2), round(y, 2), round(z, 2), "g") 
    time.sleep(0.1) # 缩短采样间隔,提高计步准确性

4. 额外说明

  • 若仍有问题,可尝试在初始化时同时写入PWR_MGMT_2寄存器(地址0x6C)为0,确保所有传感器都正常工作。
  • 计步逻辑可进一步优化(比如加入阈值防抖、过滤小幅度波动),上述代码采用了简单的Z轴峰值检测,更符合走路时的加速度变化规律。

内容的提问来源于stack exchange,提问作者Wyatt Shepherd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:40:50