diff --git a/components/flow3r_bsp/flow3r_bsp_imu.c b/components/flow3r_bsp/flow3r_bsp_imu.c index d2a020975d232ed3981c808307a8694329e552c4..a30a69b6e648e8f605d717e3dd18d370cb8b1dfa 100644 --- a/components/flow3r_bsp/flow3r_bsp_imu.c +++ b/components/flow3r_bsp/flow3r_bsp_imu.c @@ -25,14 +25,17 @@ static const char *TAG = "flow3r-imu"; static void bmi2_error_codes_print_result(int8_t rslt); static void bmp5_error_codes_print_result(const char api_name[], int8_t rslt); static int8_t set_accel_config(struct bmi2_dev *bmi); +static int8_t set_gyro_config(struct bmi2_dev *bmi); static int8_t set_bmp_config( struct bmp5_osr_odr_press_config *osr_odr_press_cfg, struct bmp5_dev *dev); static float lsb_to_mps(int16_t val, float g_range, uint8_t bit_width); +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); -// TODO: expose this, once we also expose the range of the acc +// TODO: expose this, once we also expose the range of the acc / gyro static esp_err_t flow3r_bsp_imu_read_acc(flow3r_bsp_imu_t *imu, int *x, int *y, int *z); - +static esp_err_t flow3r_bsp_imu_read_gyro(flow3r_bsp_imu_t *imu, int *x, int *y, + int *z); static BMI2_INTF_RETURN_TYPE bmi2_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) { flow3r_bsp_imu_t *imu = (flow3r_bsp_imu_t *)intf_ptr; @@ -150,11 +153,14 @@ esp_err_t flow3r_bsp_imu_init(flow3r_bsp_imu_t *imu) { if (rslt != BMI2_OK) return ESP_FAIL; rslt = set_accel_config(&(imu->bmi)); + bmi2_error_codes_print_result(rslt); + if (rslt != BMI2_OK) return ESP_FAIL; + rslt = set_gyro_config(&(imu->bmi)); bmi2_error_codes_print_result(rslt); if (rslt != BMI2_OK) return ESP_FAIL; - uint8_t sensor_list[] = { BMI2_ACCEL, BMI2_AUX }; + uint8_t sensor_list[] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; rslt = bmi2_sensor_enable(sensor_list, sizeof(sensor_list), &(imu->bmi)); bmi2_error_codes_print_result(rslt); if (rslt != BMI2_OK) return ESP_FAIL; @@ -252,6 +258,43 @@ esp_err_t flow3r_bsp_imu_read_acc_mps(flow3r_bsp_imu_t *imu, float *x, float *y, return res; } +static esp_err_t flow3r_bsp_imu_read_gyro(flow3r_bsp_imu_t *imu, int *x, int *y, + int *z) { + struct bmi2_sens_data sens_data = { + 0, + }; + + int8_t rslt = bmi2_get_sensor_data(&sens_data, &(imu->bmi)); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) { + if (sens_data.status & BMI2_DRDY_ACC) { + *x = sens_data.gyr.x; + *y = sens_data.gyr.y; + *z = sens_data.gyr.z; + return ESP_OK; + } + return ESP_ERR_NOT_FOUND; + } + return ESP_FAIL; +} + +esp_err_t flow3r_bsp_imu_read_gyro_dps(flow3r_bsp_imu_t *imu, float *x, + float *y, float *z) { + int ix, iy, iz; + + esp_err_t res = flow3r_bsp_imu_read_gyro(imu, &ix, &iy, &iz); + + if (res == ESP_OK) { + // TODO: un-hardcode the 2000 dps range + *x = lsb_to_dps(ix, 2000.f, imu->bmi.resolution); + *y = lsb_to_dps(iy, 2000.f, imu->bmi.resolution); + *z = lsb_to_dps(iz, 2000.f, imu->bmi.resolution); + } + + return res; +} + esp_err_t flow3r_bsp_imu_read_pressure(flow3r_bsp_imu_t *imu, float *pressure, float *temperature) { int8_t rslt = 0; @@ -619,6 +662,40 @@ static int8_t set_accel_config(struct bmi2_dev *bmi) { return rslt; } +static int8_t set_gyro_config(struct bmi2_dev *bmi) { + int8_t rslt; + struct bmi2_sens_config config; + + config.type = BMI2_GYRO; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi2_get_sensor_config(&config, 1, bmi); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) { + // Output Data Rate + config.cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + + // Measurement Range. By default the range is 2000 deg per second. + config.cfg.gyr.range = BMI2_GYR_RANGE_2000; + + config.cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE; + + // Full performance mode + config.cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config.cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + rslt = bmi2_set_sensor_config(&config, 1, bmi); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, bmi); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} + static int8_t set_bmp_config( struct bmp5_osr_odr_press_config *osr_odr_press_cfg, struct bmp5_dev *dev) { int8_t rslt; @@ -689,3 +766,13 @@ static float lsb_to_mps(int16_t val, float g_range, uint8_t bit_width) { return (GRAVITY_EARTH * val * g_range) / half_scale; } + +// Convert lsb to degree per second for 16 bit gyro at +// range 125, 250, 500, 1000 or 2000dps. +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) { + double power = 2; + + float half_scale = (float)((pow((double)power, (double)bit_width) / 2.0f)); + + return (dps / (half_scale)) * (val); +} diff --git a/components/flow3r_bsp/flow3r_bsp_imu.h b/components/flow3r_bsp/flow3r_bsp_imu.h index b65248860e237d23a87df732c1de01c2a6d200b2..8b857e519230f36f6bc10624b0ba5d4ecf9c6de2 100644 --- a/components/flow3r_bsp/flow3r_bsp_imu.h +++ b/components/flow3r_bsp/flow3r_bsp_imu.h @@ -30,7 +30,13 @@ esp_err_t flow3r_bsp_imu_init(flow3r_bsp_imu_t *imu); // Return values in m/s**2. esp_err_t flow3r_bsp_imu_read_acc_mps(flow3r_bsp_imu_t *imu, float *x, float *y, float *z); - +// Query the IMU for a gyroscope reading. +// +// This directly calls the I2C bus and need to lock the bus for that. +// Returns ESP_ERR_NOT_FOUND if there is no new reading available. +// Return values in deg/s. +esp_err_t flow3r_bsp_imu_read_gyro_dps(flow3r_bsp_imu_t *imu, float *x, + float *y, float *z); // Query the IMU for a pressure sensor reading. // // Return cached data if no new reading is available. diff --git a/components/micropython/usermodule/mp_imu.c b/components/micropython/usermodule/mp_imu.c index e72de8e1c6ac1d5d1ab12a3cf122fd8ee3421fa6..654289b1c1fe387ee586d928eb9b84e6f42bf2f0 100644 --- a/components/micropython/usermodule/mp_imu.c +++ b/components/micropython/usermodule/mp_imu.c @@ -16,6 +16,19 @@ STATIC mp_obj_t mp_imu_acc_read(void) { STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_imu_acc_read_obj, mp_imu_acc_read); +STATIC mp_obj_t mp_imu_gyro_read(void) { + static float x, y, z; + + // Will not overwrite old data if there is an error + st3m_imu_read_gyro_dps(&x, &y, &z); + + mp_obj_t items[3] = { mp_obj_new_float(x), mp_obj_new_float(y), + mp_obj_new_float(z) }; + return mp_obj_new_tuple(3, items); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_imu_gyro_read_obj, mp_imu_gyro_read); + STATIC mp_obj_t mp_imu_pressure_read(void) { static float pressure, temperature; @@ -32,6 +45,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_imu_pressure_read_obj, STATIC const mp_rom_map_elem_t globals_table[] = { { MP_ROM_QSTR(MP_QSTR_acc_read), MP_ROM_PTR(&mp_imu_acc_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_gyro_read), MP_ROM_PTR(&mp_imu_gyro_read_obj) }, { MP_ROM_QSTR(MP_QSTR_pressure_read), MP_ROM_PTR(&mp_imu_pressure_read_obj) }, }; diff --git a/components/st3m/st3m_imu.c b/components/st3m/st3m_imu.c index 4cd9b0cb9c35963ce70448a90d3e693491a66b94..dcf975a3facd7257367f3e8220da338232ad0ce6 100644 --- a/components/st3m/st3m_imu.c +++ b/components/st3m/st3m_imu.c @@ -23,6 +23,10 @@ esp_err_t st3m_imu_read_acc_mps(float *x, float *y, float *z) { return flow3r_bsp_imu_read_acc_mps(&imu, x, y, z); } +esp_err_t st3m_imu_read_gyro_dps(float *x, float *y, float *z) { + return flow3r_bsp_imu_read_gyro_dps(&imu, x, y, z); +} + esp_err_t st3m_imu_read_pressure(float *pressure, float *temperature) { return flow3r_bsp_imu_read_pressure(&imu, pressure, temperature); } diff --git a/components/st3m/st3m_imu.h b/components/st3m/st3m_imu.h index 13e31b8c55d2e0ec28048d9760a48a45b812fd60..8af13fbb6b1e5c137668de9fbe8f070a00452182 100644 --- a/components/st3m/st3m_imu.h +++ b/components/st3m/st3m_imu.h @@ -8,4 +8,5 @@ void st3m_imu_init(void); esp_err_t st3m_imu_read_acc_mps(float *x, float *y, float *z); +esp_err_t st3m_imu_read_gyro_dps(float *x, float *y, float *z); esp_err_t st3m_imu_read_pressure(float *pressure, float *temperature);