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
相关产品推荐
相关产品推荐

