Reading MPU6050 via Interrupts on NRF52840 and Bluetooth Connectivity Issue

I have successfully implemented an interrupt-driven method to read data from the MPU6050 sensor on the NRF52840, and it functions as expected. However, I encounter an issue where I am unable to establish a Bluetooth connection while the interrupt-based reading is active. I am working with the nrf connect sdk v2.6.1 and have configured the peripheral_uart example.

After I deleted that line, the Bluetooth connection became normal: 

mpu_read_n_reg(info, ACCEL_XOUT_H, info->sensor_data.raw_data, 14);

static void mpu6050_thread(void *p1, void *p2, void *p3)
{
	ARG_UNUSED(p2);
	ARG_UNUSED(p3);

	int ret = 0;
    uint16_t tmp[7];
	mpu6050_info_t *info = p1;
    struct sensor_value val[7];

	while (1) {
        
		k_sem_take(&info->gpio_sem, K_FOREVER);
		data_cnt++;
		
		mpu_read_n_reg(info, ACCEL_XOUT_H, info->sensor_data.raw_data, 14);
			
		gpio_pin_interrupt_configure_dt(info->int_gpio, 
		    GPIO_INT_EDGE_TO_ACTIVE);

		info->sensor_data.accel_x = sys_be16_to_cpu(info->sensor_data.raw_data[0]);
		info->sensor_data.accel_y = sys_be16_to_cpu(info->sensor_data.raw_data[1]);
		info->sensor_data.accel_z = sys_be16_to_cpu(info->sensor_data.raw_data[2]);
		info->sensor_data.temp = sys_be16_to_cpu(info->sensor_data.raw_data[3]);
		info->sensor_data.gyro_x = sys_be16_to_cpu(info->sensor_data.raw_data[4]);
		info->sensor_data.gyro_y = sys_be16_to_cpu(info->sensor_data.raw_data[5]);
		info->sensor_data.gyro_z = sys_be16_to_cpu(info->sensor_data.raw_data[6]);

		
	}
}

MPU6050 CONFIG:

static const uint8_t mpu6050_init_cmd[11][2] = {
    {PWR_MGMT_1, 0x80}, // PWR_MGMT_1, DEVICE_RESET  
    // need wait 
    {PWR_MGMT_1, 0x00}, // cleat SLEEP
    {GYRO_CONFIG, 0x18}, // Gyroscope Full Scale Range = ± 2000 °/s
    {ACCEL_CONFIG, 0x00}, // Accelerometer Full Scale Range = ± 2g 
    {INT_ENABLE, 0x01}, // Interrupt Enable.  DATA_RDY_EN
    {USER_CTRL, 0x00}, // User Control.auxiliary I2C are logically driven by the primary I2C bus
    {FIFO_EN, 0x00}, // FIFO Enable.disenable  
    {SMPLRT_DIV, 99}, // Sample Rate Divider.Sample Rate = 1KHz / (1 + 99)  
    {CONFIG, 0x23}, // EXT_SYNC_SET = GYRO_ZOUT_L[0]; Bandwidth = 3
    {PWR_MGMT_1, 0x01}, // Power Management 1.PLL with X axis gyroscope reference
    {PWR_MGMT_2, 0x00}  // Power Management 2
};

Parents
  • Hi

    Where is this mpu_read_n_reg() function defined? 

    Is this a blocking call? 

  • void mpu_read_n_reg(mpu6050_info_t *dev, uint8_t reg_addr, uint8_t* data, uint32_t len)
    {
    i2c_burst_read_dt(&dev->i2c_drv, reg_addr, data, len);
    }

    you can find i2c_burst_read_dt in v2.6.1\zephyr\include\zephyr\drivers\i2c.h

  • can you send your project to see what is blocking you from doing so?

    please mentions specifics like the ncs version you or using, or any sensor / overlay etc.

  • mpu6050.c

    static const uint8_t mpu6050_init_cmd[11][2] = {
        {PWR_MGMT_1, 0x80}, // PWR_MGMT_1, DEVICE_RESET  
        // need wait
        {PWR_MGMT_1, 0x00}, // cleat SLEEP
        {GYRO_CONFIG, 0x18}, // Gyroscope Full Scale Range = ± 2000 °/s
        {ACCEL_CONFIG, 0x00}, // Accelerometer Full Scale Range = ± 2g
        {INT_ENABLE, 0x01}, // Interrupt Enable.  DATA_RDY_EN
        {USER_CTRL, 0x00}, // User Control.auxiliary I2C are logically driven by the primary I2C bus
        {FIFO_EN, 0x00}, // FIFO Enable.disenable  
        {SMPLRT_DIV, 99}, // Sample Rate Divider.Sample Rate = 1KHz / (1 + 9)  
        {CONFIG, 0x23}, // EXT_SYNC_SET = GYRO_ZOUT_L[0]; Bandwidth = 3
        {PWR_MGMT_1, 0x01}, // Power Management 1.PLL with X axis gyroscope reference
        {PWR_MGMT_2, 0x00}  // Power Management 2
    };
     
    mpu6050_info_t mpu6050_dev = {
        .i2c = I2C_DT_SPEC_GET(DT_NODELABEL(mpu6050)),  
        .int_gpio = GPIO_DT_SPEC_GET(DT_NODELABEL(mpu6050), int_gpios),
    };
    
    static void mpu6050_gpio_callback(const struct device *dev,
                      struct gpio_callback *cb, uint32_t pins)
    {
        mpu6050_info_t *info = CONTAINER_OF(cb, mpu6050_info_t, gpio_cb);
     
        ARG_UNUSED(pins);
        gpio_pin_interrupt_configure_dt(&info->int_gpio, GPIO_INT_DISABLE);
        k_sem_give(&info->gpio_sem);
    
    }
    
    void mpu_read_reg(mpu6050_info_t *dev, uint8_t reg_addr, uint8_t *data)
    {
        i2c_reg_read_byte_dt(&dev->i2c, reg_addr, data);
    }
     
    
    void mpu_write_reg(mpu6050_info_t *dev, uint8_t reg_addr, uint8_t data)
    {
        i2c_reg_write_byte_dt(&dev->i2c, reg_addr, data);
    }
     
    void mpu_read_n_reg(mpu6050_info_t *dev, uint8_t start_reg, uint8_t* data, uint32_t len)
    {
        i2c_burst_read_dt(&dev->i2c, start_reg, data, len);
    }
    
    int mpu6050_init_interrupt(mpu6050_info_t *info)
    {
        if (!gpio_is_ready_dt(&info->int_gpio)) {
            LOG_ERR("GPIO device not ready");
            return -ENODEV;
        }
     
        gpio_pin_configure_dt(&info->int_gpio, GPIO_INPUT);
     
        gpio_init_callback(&info->gpio_cb,
                   mpu6050_gpio_callback,
                   BIT(info->int_gpio.pin));
     
        if (gpio_add_callback(info->int_gpio.port, &info->gpio_cb) < 0) {
            LOG_ERR("Failed to set gpio callback");
            return -EIO;
        }
     
    #if defined(MPU6050_TRIGGER_OWN_THREAD)
        k_sem_init(&info->gpio_sem, 0, K_SEM_MAX_LIMIT);
     
        k_thread_create(&info->thread, info->thread_stack,
                MPU6050_THREAD_STACK_SIZE,
                mpu6050_thread, &mpu6050_dev,
                NULL, NULL, K_PRIO_COOP(MPU6050_THREAD_PRIORITY),
                0, K_NO_WAIT);
    #elif defined(MPU6050_TRIGGER_GLOBAL_THREAD)
        info->work.handler = mpu6050_work_cb;
    #endif
     
        gpio_pin_interrupt_configure_dt(&info->int_gpio,
                        GPIO_INT_EDGE_FALLING);
     
        return 0;
    }
    
    static void mpu6050_thread(void *p1, void *p2, void *p3)
    {
        ARG_UNUSED(p2);
        ARG_UNUSED(p3);
     
        uint16_t tmp[7];
        mpu6050_info_t *info = p1;
        // struct sensor_value val[7];
     
        while (1) {
            //等待接收
            k_sem_take(&info->gpio_sem, K_FOREVER);
     
            //读取数据
            mpu_read_n_reg(info, ACCEL_XOUT_H, (uint8_t*)tmp, 14);
           
            //开中断
            gpio_pin_interrupt_configure_dt(&info->int_gpio,
                GPIO_INT_EDGE_FALLING);
     
            info->sensor_data.accel_x = sys_be16_to_cpu(tmp[0]);
            info->sensor_data.accel_y = sys_be16_to_cpu(tmp[1]);
            info->sensor_data.accel_z = sys_be16_to_cpu(tmp[2]);
            info->sensor_data.temp = sys_be16_to_cpu(tmp[3]);
            info->sensor_data.gyro_x = sys_be16_to_cpu(tmp[4]);
            info->sensor_data.gyro_y = sys_be16_to_cpu(tmp[5]);
            info->sensor_data.gyro_z = sys_be16_to_cpu(tmp[6]);
     
            //for(int i=0; i<7; i++) printk("%x ", tmp[i]);
            //printk("\r\n");
            // k_sleep(K_MSEC(100));
        }
    }
    
    int mpu6050_init(void)
    {
        int ret;
        int i=0;
        uint8_t tmp, id;
     
        mpu6050_dev.sensor_data.accel_sensitivity_shift = 14;   // 14 - bit(4,3)
        mpu6050_dev.sensor_data.gyro_sensitivity_x10 = mpu6050_gyro_sensitivity_x10[3];
       
        if (!device_is_ready(mpu6050_dev.i2c.bus)) {
            LOG_ERR("Bus device is not ready");
            return -ENODEV;
        }
       
        /* check chip ID */
        if (i2c_reg_read_byte_dt(&mpu6050_dev.i2c, MPU6050_REG_CHIP_ID, &id) < 0) {
            LOG_ERR("Failed to read chip ID.");
            return -EIO;
        }
    
        if ((id != MPU6050_CHIP_ID) && (id != MPU9250_CHIP_ID) && (id != MPU6880_CHIP_ID)) {
            LOG_ERR("Invalid chip ID.");
            return -EINVAL;
        }
    
    
    #ifdef  MPU6050_INT_ENABLE
        ret = mpu6050_init_interrupt(&mpu6050_dev);
        if(ret) LOG_ERR("mpu6050_init_interrupt ERROR %X", ret);
    #endif
     
        for (i=0; i < 11; i++){
            mpu_write_reg(&mpu6050_dev, mpu6050_init_cmd[i][0], mpu6050_init_cmd[i][1]);
            if (i == 0)
                k_sleep(K_MSEC(500));
        }
       
        for(i=0; i<11; i++){
            mpu_read_reg(&mpu6050_dev, mpu6050_init_cmd[i][0], &tmp);
            printk("tmp %02X\n\r", tmp);
        }
    
        return 0;
    }

  • app.overlay
    / {
        chosen {
            nordic,nus-uart = &uart0;
        };
    };
    
    &i2c1 {
        status = "okay";
        // clock-frequency = <400000>;
        mpu6050: mpu6050@68 {
            compatible = "invensense,mpu6050";
            reg = <0x68>; // I2C 地址
            int-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
        };
    };
     
    //é…Ťç˝®i2c1
    &i2c1_default {
        group1 {
            psels = <NRF_PSEL(TWIM_SDA, 0, 31)>, <NRF_PSEL(TWIM_SCL, 0, 30)>;
        };
    };
    main.c
    
    int main(void)
    {
        int blink_status = 0;
        int err = 0;
    
        configure_gpio();
    
        uart_init();
    
        ble_init();
    
        mpu6050_init();
    
        for (;;) {
            dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
            k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
        }
    }
    
    void ble_write_thread(void)
    {
        static uint8_t tmp[5] = "1234";
        k_sem_take(&ble_init_ok, K_FOREVER);
       
        for (;;) {
            if(current_conn){
                // indicate_send(current_conn, tmp, 5);
                bt_custom_send(current_conn, (uint8_t*)&mpu6050_dev.sensor_data.temp, 2);
            }
            tmp[0] ++;
            k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
        }
    }
    
    K_THREAD_DEFINE(ble_write_thread_id, BT_THREAD_STACKSIZE, ble_write_thread, NULL, NULL,
            NULL, BT_THREAD_PRIORITY, 0, 0);
    
    
  • I use nrf connect sdk v2.6.1. when I delete the mpu_read_n_reg() in mpu6050_thread, the ble can be connected.

  • I am sorry but I could not compile the project you have sent. It is missing definitions.

    What is ble_init()? Is this custom function? I see bt_enalbe() is not used.

    Please send a minimal but complete project as a zip file that could be compiled in ncs 2.6.1.

Reply Children
Related