MPU6050 i2c subclass and Core 0 Panic on Dev Kit C


#1

I write this driver for MPU-6050:

import i2c

MPU6050_AUX_VDDIO =0x01
MPU6050_SELF_TEST_X =0x0D # BIT [7-5] ACC_X :: [4-0] GYRO_X R/W
MPU6050_SELF_TEST_Y =0x0E # BIT [7-5] ACC_Y :: [4-0] GYRO_Y R/W
MPU6050_SELF_TEST_Z =0x0F # BIT [7-5] ACC_Z :: [4-0] GYRO_Z R/W
MPU6050_SELF_TEST_A =0x10 # BIT [7-6] RESERVED :: [5-4] ACC_X_TEST :: [3-2] ACC_Y_TEST :: [1-0] ACC_Z_TEST R/W
MPU6050_SMPLRT_DIV =0x19
MPU6050_CONFIG =0x1A
MPU6050_GYRO_CONFIG =0x1B
MPU6050_ACCEL_CONFIG =0x1C
MPU6050_FF_THR =0x1D
MPU6050_FF_DUR =0x1E
MPU6050_MOT_THR =0x1F
MPU6050_MOT_DUR =0x20
MPU6050_ZRMOT_THR =0x21
MPU6050_ZRMOT_DUR =0x22
MPU6050_FIFO_EN =0x23
MPU6050_I2C_MST_CTRL =0x24
MPU6050_I2C_SLV0_ADDR =0x25
MPU6050_I2C_SLV0_REG =0x26
MPU6050_I2C_SLV0_CTRL =0x27
MPU6050_I2C_SLV1_ADDR =0x28
MPU6050_I2C_SLV1_REG =0x29
MPU6050_I2C_SLV1_CTRL =0x2A
MPU6050_I2C_SLV2_ADDR =0x2B
MPU6050_I2C_SLV2_REG =0x2C
MPU6050_I2C_SLV2_CTRL =0x2D
MPU6050_I2C_SLV3_ADDR =0x2E
MPU6050_I2C_SLV3_REG =0x2F
MPU6050_I2C_SLV3_CTRL =0x30
MPU6050_I2C_SLV4_ADDR =0x31
MPU6050_I2C_SLV4_REG =0x32
MPU6050_I2C_SLV4_DO =0x33
MPU6050_I2C_SLV4_CTRL =0x34
MPU6050_I2C_SLV4_DI =0x35
MPU6050_I2C_MST_STATUS =0x36
MPU6050_INT_PIN_CFG =0x37
MPU6050_INT_ENABLE =0x38
MPU6050_INT_STATUS =0x3A
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
MPU6050_TEMP_OUT_H =0x41
MPU6050_TEMP_OUT_L =0x42
MPU6050_GYRO_XOUT_H =0x43
MPU6050_GYRO_XOUT_L =0x44
MPU6050_GYRO_YOUT_H =0x45
MPU6050_GYRO_YOUT_L =0x46
MPU6050_GYRO_ZOUT_H =0x47
MPU6050_GYRO_ZOUT_L =0x48
MPU6050_EXT_SENS_DATA_00 =0x49
MPU6050_EXT_SENS_DATA_01 =0x4A
MPU6050_EXT_SENS_DATA_02 =0x4B
MPU6050_EXT_SENS_DATA_03 =0x4C
MPU6050_EXT_SENS_DATA_04 =0x4D
MPU6050_EXT_SENS_DATA_05 =0x4E
MPU6050_EXT_SENS_DATA_06 =0x4F
MPU6050_EXT_SENS_DATA_07 =0x50
MPU6050_EXT_SENS_DATA_08 =0x51
MPU6050_EXT_SENS_DATA_09 =0x52
MPU6050_EXT_SENS_DATA_10 =0x53
MPU6050_EXT_SENS_DATA_11 =0x54
MPU6050_EXT_SENS_DATA_12 =0x55
MPU6050_EXT_SENS_DATA_13 =0x56
MPU6050_EXT_SENS_DATA_14 =0x57
MPU6050_EXT_SENS_DATA_15 =0x58
MPU6050_EXT_SENS_DATA_16 =0x59
MPU6050_EXT_SENS_DATA_17 =0x5A
MPU6050_EXT_SENS_DATA_18 =0x5B
MPU6050_EXT_SENS_DATA_19 =0x5C
MPU6050_EXT_SENS_DATA_20 =0x5D
MPU6050_EXT_SENS_DATA_21 =0x5E
MPU6050_EXT_SENS_DATA_22 =0x5F
MPU6050_EXT_SENS_DATA_23 =0x60
MPU6050_MOT_DETECT_STATUS =0x61
MPU6050_I2C_SLV0_DO =0x63
MPU6050_I2C_SLV1_DO =0x64
MPU6050_I2C_SLV2_DO =0x65
MPU6050_I2C_SLV3_DO =0x66
MPU6050_I2C_MST_DELAY_CTRL =0x67
MPU6050_SIGNAL_PATH_RESET =0x68
MPU6050_MOT_DETECT_CTRL =0x69
MPU6050_USER_CTRL =0x6A
MPU6050_PWR_MGMT_1 =0x6B
MPU6050_PWR_MGMT_2 =0x6C
MPU6050_FIFO_COUNTH =0x72
MPU6050_FIFO_COUNTL =0x73
MPU6050_FIFO_R_W =0x74
MPU6050_WHO_AM_I =0x75
MPU6050_I2C_ADDRESS =0x68

MPU6050_I2C_SCL_FAST_MODE =400000 # Support I2C Fast Mode clock 400kHz
MPU6050_I2C_SCL =100000 # Standard I2C clock 100kHz

MPU6050_INTERNAL_CLOCK =0x00
MPU6050_PLL_X_GYROSCOPE =0x01
MPU6050_PLL_Y_GYROSCOPE =0x02
MPU6050_PLL_Z_GYROSCOPE =0x03
MPU6050_PLL_EXT_32KHZ =0x04
MPU6050_PLL_EXT_19MHZ =0x05
MPU6050_CLOCK_STOP =0x07 # Like “Register map and descriptions” document says, value 6 it’s RESERVED

_clock_mode = {
“internal” : MPU6050_INTERNAL_CLOCK,
“x_gyro” : MPU6050_PLL_X_GYROSCOPE,
“y_gyro” : MPU6050_PLL_Y_GYROSCOPE,
“z_gyro” : MPU6050_PLL_Z_GYROSCOPE,
“32KHz” : MPU6050_PLL_EXT_32KHZ,
“19MHz” : MPU6050_PLL_EXT_19MHZ,
“stop” : MPU6050_CLOCK_STOP

}

class MPU6050(i2c.I2C):
#Init
#
#From datasheet, standard i2c address value is 0x68 for access to MPU, standard i2c clock is 100Hz
#
def init(self,i2cdrv,addr=MPU6050_I2C_ADDRESS,clk=MPU6050_I2C_SCL):
i2c.I2C.init(self,i2cdrv,addr,clk)
self._addr = addr
self._mode = “x_gyro” # Default, like “Register map and descriptions” document says,
# it’s highly recommended that the device use one of the gyroscope
# as the clock reference to improve stability

def init(self):
    try:
        self.start()
    except PeripheralError as e:
        print("Error on start i2c bus")
    
    #Send Hard Reset
    #print("HARD RESET")
    self.write_bytes(MPU6050_PWR_MGMT_1,0x80)
    #print("SETTING")
    self.write_bytes(MPU6050_SIGNAL_PATH_RESET,0x07)
    # Set MPU to CYCLE Mode and CLKSEL to x asix gyroscope reference
    # BIT5 = BIT 1 = 1 => dec(33) => hex(0x21)
    self.write_bytes(MPU6050_PWR_MGMT_1,0x21)


# These write into register 104 
# SIGNAL_PATH_RESET, wich revert the signal path 
# analog to digital converters and filter to their 
# power up configuration 
# BIT0 = TEMP_RESET
# BIT1 = ACC_RESET
# BIT2 = GYRO_RESET
# Page 37 "Register Map and Descriptions" document

def reset_signal_path_sensors(self):
    self.write_bytes(MPU6050_SIGNAL_PATH_RESET,0x07)
    
def reset_signal_path_temp(self):
    self.write_bytes(MPU6050_SIGNAL_PATH_RESET,0x01)

def reset_signal_path_accel(self):
    self.write_bytes(MPU6050_SIGNAL_PATH_RESET,0x02)

def reset_signal_path_gyro(self):
    self.write_bytes(MPU6050_SIGNAL_PATH_RESET,0x04)


# These write into register 106 
# USER_CTRL
# BIT7 = RESERVED 
# BIT6 = FIFO_EN Enable (1) or disable (0) FIFO
# BIT5 = I2C_MASTER_ENABLE Enable (1) I2C Master Mode - 
# use with XDA e XCL otherwise XDA and XCL are logically driven by the i2c primary bus
# BIT4 Always set to 0 for mpu-6050
# BIT3 = RESERVED 
# BIT2 = FIFO_RESET Resets FIFO buffer when FIFO_EN disable (0)
# BIT1 = I2C_MASTER_RESET Reset I2c Master when I2C_MASTER_ENABLE disable (0)
# BIT0 = SIG_COND_RESET Equal to hard reset - reset signal path and register of sensors 
# Page 38 "Register Map and Descriptions" document

def enable_fifo_operation(self):
    self.write_bytes(MPU6050_USER_CTRL,0x40)

def enable_i2c_master_mode(self):
    self.write_bytes(MPU6050_USER_CTRL,0x20)

def reset_fifo_buffer(self):
    self.write_bytes(MPU6050_USER_CTRL,0x04)

def reset_i2c_master(self):
    self.write_bytes(MPU6050_USER_CTRL,0x02)
    
def soft_reset(self):
    self.write_bytes(MPU6050_USER_CTRL,0x01)


# These write into register 107 
# PWR_MGMT_1
# BIT7 = DEVICE_RESET Reset device and restore all internal register to their default value
# BIT6 = SLEEP put the MPU-6050 in sleep mode (refer to "Product Specification" document)
# BIT5 = CYCLE put the MPU-6050 in cycle mode (cycles between sleep and waking up mode)
# need to set the LP_WAKE_CTRL into register 108 (PWR_MGMT_2)
# BIT4 = RESERVED
# BIT3 = TEMP_DIS Enable(0) or disable(1) temperature sensor
# BIT[2-0] = CLKSEL Define clock source 
# Page 40 "Register Map and Descriptions" document

def device_reset(self):
    self.write_bytes(MPU6050_PWR_MGMT_1,0x80)

def low_power_mode(self):
    self.write_bytes(MPU6050_PWR_MGMT_1,0x40)

def cycle_mode(self):
    self.write_bytes(MPU6050_PWR_MGMT_1,0x20)

def clock_select(self,mode=MPU6050_INTERNAL_CLOCK):
    self.write_bytes(MPU6050_PWR_MGMT_1,mode)
    
# Read temp from sensor
# Datasheet say (pag30)
# Formula: t = readedValue/340+36.53
def read_temp(self):
    t=self.read(0x41,2)
    return (((t[1]<<8 | t[0])/340)+36.53)

# Set gyroscope Full Scale Range
# Datasheet say (pag 14)
# 0 = +/- 250°/s
# 1 = +/- 500°/s
# 2 = +/- 1000°/s
# 3 = +/- 2000°/s
# This value need to set to [4:3]
def setgyroscope(self,mode=0):
    if mode==0:
        self.write_bytes(0x1B,0)
    elif mode==1:
        self.write_bytes(0x1B,8)
    elif mode==2:
        self.write_bytes(0x1B,16)
    elif mode==3:
        self.write_bytes(0x1B,24)

# Set accelerometer Full Scale Range
# Datasheet say (pag 15)
# 0 = +/- 2g
# 1 = +/- 4g
# 2 = +/- 8g
# 3 = +/- 16g
# This value need to set to [4:3]
def setaccelerometer(self,mode=0):
    if mode==0:
        self.write_bytes(0x1C,0)
    elif mode==1:
        self.write_bytes(0x1C,8)
    elif mode==2:
        self.write_bytes(0x1C,16)
    elif mode==3:
        self.write_bytes(0x1C,24)

#Read status of accelerometer, gyroscope and temperature
def readstatus(self):
print(“READREG:AXH”,self.read(0x3B))
print(“READREG:AXL”,self.read(0x3C))
print(“READREG:AYH”,self.read(0x3D))
print(“READREG:AXL”,self.read(0x3E))
print(“READREG:AZH”,self.read(0x3F))
print(“READREG:AZL”,self.read(0x40))
print(“READREG:TH”,self.read(0x41))
print(“READREG:TL”,self.read(0x42))
print(“READREG:GXH”,self.read(0x43))
print(“READREG:GXL”,self.read(0x44))
print(“READREG:GYH”,self.read(0x45))
print(“READREG:GYL”,self.read(0x46))
print(“READREG:GZH”,self.read(0x47))
print(“READREG:GZL”,self.read(0x48))

#Simple method for read specific register
def readregister(self,addr):
    return self.read(addr)

#Writefunction
def write(self,value,timeout=-1):
    return self.write(value,timeout)

def _write_bytes(self,value,timeout=-1):
    return self.write_bytes(value,timeout)

#Id value
def chip_id(self):
    r = self.write_read(MPU6050_WHO_AM_I,1)
    print(r[0])

then i define a pwm thread for blink a led.
When i create a new mpu6050 in main

import i2c
import mpu6050
import status
import streams

streams.serial()

print(“INIT LED”)
#thread(status.statusOk,D23)
#thread(status.statusConnectedLow,D21)

mpu6050 = mpu6050.MPU6050(I2C0)
mpu6050.init()

i obtain this:

Guru Meditation Error: Core 0 panic’ed (LoadProhibited)

. Exception was unhandled.

Register dump:

PC : 0x4010aa51 PS : 0x00060330 A0 : 0x801146bd A1 : 0x3ffdc260

A2 : 0x00000000 A3 : 0x00000000 A4 : 0x00000030 A5 : 0x3ffd914c

A6 : 0x00000180 A7 : 0x00000003 A8 : 0x3ffd9260 A9 : 0x3ffd9254

A10 : 0x3ffd911c A11 : 0x00000003 A12 : 0x00000003 A13 : 0x00000000

A14 : 0x3ffd91a0 A15 : 0x00000000 SAR : 0x00000008 EXCCAUSE: 0x0000001c

EXCVADDR: 0x00000004 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000

Backtrace: 0x4010aa51:0x3ffdc260 0x401146ba:0x3ffdc280 0x4011092b:0x3ffdc2b0 0x4010c5aa:0x3ffdc2d0 0x40108071:0x3ffdc330 0x40108086:0x3ffdc350 0x400d1038:0x3ffdc370

Rebooting…
Really i can’t know how to resolve this


#2

Hi @Alessandro_Giaquinto,

it is not really easy to debug something like that. I would suggest to start with a simple I2C script where you init the I2C communication and test the channel using simple write/read operations.

Let me know :slight_smile: