From 6f1e5c66f5c207e421eab51f70b8500934658cca Mon Sep 17 00:00:00 2001 From: Vilem Zavodny Date: Mon, 25 Sep 2023 11:50:08 +0200 Subject: [PATCH] icm42670: Add 6-axis MotionTracking --- .github/workflows/upload_component.yml | 2 +- components/icm42670/CMakeLists.txt | 1 + components/icm42670/README.md | 32 ++ components/icm42670/icm42670.c | 414 +++++++++++++++++++++++++ components/icm42670/idf_component.yml | 5 + components/icm42670/include/icm42670.h | 275 ++++++++++++++++ components/icm42670/license.txt | 202 ++++++++++++ test_app/CMakeLists.txt | 4 +- 8 files changed, 932 insertions(+), 3 deletions(-) create mode 100644 components/icm42670/CMakeLists.txt create mode 100644 components/icm42670/README.md create mode 100644 components/icm42670/icm42670.c create mode 100644 components/icm42670/idf_component.yml create mode 100644 components/icm42670/include/icm42670.h create mode 100644 components/icm42670/license.txt diff --git a/.github/workflows/upload_component.yml b/.github/workflows/upload_component.yml index 3f58e80a..34057507 100644 --- a/.github/workflows/upload_component.yml +++ b/.github/workflows/upload_component.yml @@ -16,7 +16,7 @@ jobs: with: directories: > esp32_azure_iot_kit;esp32_s2_kaluga_kit;esp_wrover_kit;esp-box;esp32_s3_usb_otg;esp32_s3_eye;esp32_s3_lcd_ev_board;esp32_s3_korvo_2;esp-box-lite;esp32_lyrat;esp32_c3_lcdkit;esp-box-3; - components/bh1750;components/ds18b20;components/es8311;components/es7210;components/fbm320;components/hts221;components/mag3110;components/mpu6050;components/ssd1306;components/esp_lvgl_port; + components/bh1750;components/ds18b20;components/es8311;components/es7210;components/fbm320;components/hts221;components/mag3110;components/mpu6050;components/ssd1306;components/esp_lvgl_port;components/icm42670; components/lcd_touch/esp_lcd_touch;components/lcd_touch/esp_lcd_touch_ft5x06;components/lcd_touch/esp_lcd_touch_gt911;components/lcd_touch/esp_lcd_touch_tt21100;components/lcd_touch/esp_lcd_touch_gt1151;components/lcd_touch/esp_lcd_touch_cst816s; components/lcd/esp_lcd_gc9a01;components/lcd/esp_lcd_ili9341;components/lcd/esp_lcd_ra8875;components/lcd_touch/esp_lcd_touch_stmpe610;components/lcd/esp_lcd_sh1107;components/lcd/esp_lcd_st7796;components/lcd/esp_lcd_gc9503;components/lcd/esp_lcd_ssd1681; components/io_expander/esp_io_expander;components/io_expander/esp_io_expander_tca9554;components/io_expander/esp_io_expander_tca95xx_16bit;components/io_expander/esp_io_expander_ht8574; diff --git a/components/icm42670/CMakeLists.txt b/components/icm42670/CMakeLists.txt new file mode 100644 index 00000000..af44ef91 --- /dev/null +++ b/components/icm42670/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "icm42670.c" INCLUDE_DIRS "include" REQUIRES "driver") diff --git a/components/icm42670/README.md b/components/icm42670/README.md new file mode 100644 index 00000000..d7ecd68f --- /dev/null +++ b/components/icm42670/README.md @@ -0,0 +1,32 @@ +# ICM42607/ICM42670 6-Axis MotionTracking (Accelerometer and Gyroscope) + +[![Component Registry](https://components.espressif.com/components/espressif/icm42670/badge.svg)](https://components.espressif.com/components/espressif/icm42670) + +C driver for Invensense ICM42607/ICM42670 6-axis gyroscope and accelerometer based on I2C communication. + +## Features + +- Get 3-axis accelerometer and 3-axis gyroscope data, either raw or as floating point values. +- Read temperature from ICM42607/ICM42670 internal temperature sensor. +- Configure gyroscope and accelerometer sensitivity. +- ICM42607/ICM42670 power down mode. + +## Limitations + +- Only I2C communication is supported. +- Driver has not been tested with ICM42670 yet. + +## Get Started + +This driver, along with many other components from this repository, can be used as a package from [Espressif's IDF Component Registry](https://components.espressif.com). To include this driver in your project, run the following idf.py from the project's root directory: + +``` + idf.py add-dependency "espressif/icm42670==1.0.0" +``` + +Another option is to manually create a `idf_component.yml` file. You can find more about using .yml files for components from [Espressif's documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html). + +## See Also +* [MPU6050 datasheet](https://invensense.tdk.com/products/motion-tracking/6-axis/icm-42670-p/) + + diff --git a/components/icm42670/icm42670.c b/components/icm42670/icm42670.c new file mode 100644 index 00000000..1aad8726 --- /dev/null +++ b/components/icm42670/icm42670.c @@ -0,0 +1,414 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "esp_system.h" +#include "esp_check.h" +#include "driver/i2c.h" +#include "icm42670.h" + +#define ALPHA 0.99f /*!< Weight of gyroscope */ +#define RAD_TO_DEG 57.27272727f /*!< Radians to degrees */ + +#define ICM42607_ID 0x60 +#define ICM42670_ID 0x67 + +/* ICM42670 register */ +#define ICM42670_WHOAMI 0x75 +#define ICM42670_GYRO_CONFIG0 0x20 +#define ICM42670_ACCEL_CONFIG0 0x21 +#define ICM42670_TEMP_CONFIG 0x22 +#define ICM42670_PWR_MGMT0 0x1F +#define ICM42670_TEMP_DATA 0x09 +#define ICM42670_ACCEL_DATA 0x0B +#define ICM42670_GYRO_DATA 0x11 + +/* Sensitivity of the gyroscope */ +#define GYRO_FS_2000_SENSITIVITY (16.4) +#define GYRO_FS_1000_SENSITIVITY (32.8) +#define GYRO_FS_500_SENSITIVITY (65.5) +#define GYRO_FS_250_SENSITIVITY (131.0) + +/* Sensitivity of the accelerometer */ +#define ACCE_FS_16G_SENSITIVITY (2048) +#define ACCE_FS_8G_SENSITIVITY (4096) +#define ACCE_FS_4G_SENSITIVITY (8192) +#define ACCE_FS_2G_SENSITIVITY (16384) + +/******************************************************************************* +* Types definitions +*******************************************************************************/ + +typedef struct { + i2c_port_t bus; + uint8_t dev_addr; + uint32_t counter; + float dt; /*!< delay time between two measurements, dt should be small (ms level) */ + struct timeval *timer; +} icm42670_dev_t; + +/******************************************************************************* +* Function definitions +*******************************************************************************/ +static esp_err_t icm42670_write(icm42670_handle_t sensor, const uint8_t reg_start_addr, const uint8_t *data_buf, const uint8_t data_len); +static esp_err_t icm42670_read(icm42670_handle_t sensor, const uint8_t reg_start_addr, uint8_t *data_buf, const uint8_t data_len); + +static esp_err_t icm42670_get_raw_value(icm42670_handle_t sensor, uint8_t reg, icm42670_raw_value_t *value); + +/******************************************************************************* +* Local variables +*******************************************************************************/ +static const char *TAG = "ICM42670"; + +/******************************************************************************* +* Public API functions +*******************************************************************************/ + +icm42670_handle_t icm42670_create(i2c_port_t port, const uint8_t dev_addr) +{ + icm42670_dev_t *sensor = (icm42670_dev_t *) heap_caps_calloc(1, sizeof(icm42670_dev_t), MALLOC_CAP_DEFAULT); + sensor->bus = port; + sensor->dev_addr = dev_addr; + sensor->counter = 0; + sensor->dt = 0; + sensor->timer = (struct timeval *) calloc(1, sizeof(struct timeval)); + + uint8_t dev_id = 0; + icm42670_get_deviceid(sensor, &dev_id); + if (dev_id != ICM42607_ID && dev_id != ICM42670_ID) { + ESP_LOGE(TAG, "Incorrect Device ID (0x%02x).", dev_id); + return NULL; + } + + ESP_LOGI(TAG, "Found device %s, ID: 0x%02x", (dev_id == ICM42607_ID ? "ICM42607" : "ICM42670"), dev_id); + + return (icm42670_handle_t) sensor; +} + +void icm42670_delete(icm42670_handle_t sensor) +{ + icm42670_dev_t *sens = (icm42670_dev_t *) sensor; + + if (sens->timer) { + free(sens->timer); + } + + free(sens); +} + +esp_err_t icm42670_get_deviceid(icm42670_handle_t sensor, uint8_t *deviceid) +{ + esp_err_t ret = ESP_FAIL; + + assert(deviceid != NULL); + + for (int i = 0; (i < 5 && ret != ESP_OK); i++) { + ret = icm42670_read(sensor, ICM42670_WHOAMI, deviceid, 1); + } + + return ret; +} + +esp_err_t icm42670_config(icm42670_handle_t sensor, const icm42670_cfg_t *config) +{ + uint8_t data[2]; + + assert(config != NULL); + + /* Gyroscope */ + data[0] = ((config->gyro_fs & 0x03) << 5) | (config->gyro_odr & 0x0F); + /* Accelerometer */ + data[1] = ((config->acce_fs & 0x03) << 5) | (config->acce_odr & 0x0F); + + return icm42670_write(sensor, ICM42670_GYRO_CONFIG0, data, sizeof(data)); +} + +esp_err_t icm42670_acce_set_pwr(icm42670_handle_t sensor, icm42670_acce_pwr_t state) +{ + esp_err_t ret = ESP_FAIL; + uint8_t data; + + ret = icm42670_read(sensor, ICM42670_PWR_MGMT0, &data, 1); + if (ret == ESP_OK) { + data |= (state & 0x03); + + ret = icm42670_write(sensor, ICM42670_PWR_MGMT0, &data, sizeof(data)); + } + + return ret; +} + +esp_err_t icm42670_gyro_set_pwr(icm42670_handle_t sensor, icm42670_gyro_pwr_t state) +{ + esp_err_t ret = ESP_FAIL; + uint8_t data; + + ret = icm42670_read(sensor, ICM42670_PWR_MGMT0, &data, 1); + if (ret == ESP_OK) { + data |= ((state & 0x03) << 2); + + ret = icm42670_write(sensor, ICM42670_PWR_MGMT0, &data, sizeof(data)); + } + + return ret; +} + +esp_err_t icm42670_get_acce_sensitivity(icm42670_handle_t sensor, float *sensitivity) +{ + esp_err_t ret = ESP_FAIL; + uint8_t acce_fs; + + assert(sensitivity != NULL); + + *sensitivity = 0; + + ret = icm42670_read(sensor, ICM42670_ACCEL_CONFIG0, &acce_fs, 1); + if (ret == ESP_OK) { + acce_fs = (acce_fs >> 3) & 0x03; + switch (acce_fs) { + case ACCE_FS_16G: + *sensitivity = ACCE_FS_16G_SENSITIVITY; + break; + case ACCE_FS_8G: + *sensitivity = ACCE_FS_8G_SENSITIVITY; + break; + case ACCE_FS_4G: + *sensitivity = ACCE_FS_4G_SENSITIVITY; + break; + case ACCE_FS_2G: + *sensitivity = ACCE_FS_2G_SENSITIVITY; + break; + } + } + + return ret; +} + +esp_err_t icm42670_get_gyro_sensitivity(icm42670_handle_t sensor, float *sensitivity) +{ + esp_err_t ret = ESP_FAIL; + uint8_t gyro_fs; + + assert(sensitivity != NULL); + + *sensitivity = 0; + + ret = icm42670_read(sensor, ICM42670_ACCEL_CONFIG0, &gyro_fs, 1); + if (ret == ESP_OK) { + gyro_fs = (gyro_fs >> 3) & 0x03; + switch (gyro_fs) { + case GYRO_FS_2000DPS: + *sensitivity = GYRO_FS_2000_SENSITIVITY; + break; + case GYRO_FS_1000DPS: + *sensitivity = GYRO_FS_1000_SENSITIVITY; + break; + case GYRO_FS_500DPS: + *sensitivity = GYRO_FS_500_SENSITIVITY; + break; + case GYRO_FS_250DPS: + *sensitivity = GYRO_FS_250_SENSITIVITY; + break; + } + } + + return ret; +} + +esp_err_t icm42670_get_temp_raw_value(icm42670_handle_t sensor, uint16_t *value) +{ + esp_err_t ret = ESP_FAIL; + uint8_t data[2]; + + assert(value != NULL); + + *value = 0; + + ret = icm42670_read(sensor, ICM42670_TEMP_DATA, data, sizeof(data)); + if (ret == ESP_OK) { + *value = (uint16_t)((data[0] << 8) + data[1]); + } + + return ret; +} + +esp_err_t icm42670_get_acce_raw_value(icm42670_handle_t sensor, icm42670_raw_value_t *value) +{ + return icm42670_get_raw_value(sensor, ICM42670_ACCEL_DATA, value); +} + +esp_err_t icm42670_get_gyro_raw_value(icm42670_handle_t sensor, icm42670_raw_value_t *value) +{ + return icm42670_get_raw_value(sensor, ICM42670_GYRO_DATA, value); +} + +esp_err_t icm42670_get_acce_value(icm42670_handle_t sensor, icm42670_value_t *value) +{ + esp_err_t ret; + float sensitivity; + icm42670_raw_value_t raw_value; + + assert(value != NULL); + + value->x = 0; + value->y = 0; + value->z = 0; + + ret = icm42670_get_acce_sensitivity(sensor, &sensitivity); + ESP_RETURN_ON_ERROR(ret, TAG, "Get sensitivity error!"); + + ret = icm42670_get_acce_raw_value(sensor, &raw_value); + ESP_RETURN_ON_ERROR(ret, TAG, "Get raw value error!"); + + value->x = raw_value.x / sensitivity; + value->y = raw_value.y / sensitivity; + value->z = raw_value.z / sensitivity; + + return ESP_OK; +} + +esp_err_t icm42670_get_gyro_value(icm42670_handle_t sensor, icm42670_value_t *value) +{ + esp_err_t ret; + float sensitivity; + icm42670_raw_value_t raw_value; + + assert(value != NULL); + + value->x = 0; + value->y = 0; + value->z = 0; + + ret = icm42670_get_gyro_sensitivity(sensor, &sensitivity); + ESP_RETURN_ON_ERROR(ret, TAG, "Get sensitivity error!"); + + ret = icm42670_get_gyro_raw_value(sensor, &raw_value); + ESP_RETURN_ON_ERROR(ret, TAG, "Get raw value error!"); + + value->x = raw_value.x / sensitivity; + value->y = raw_value.y / sensitivity; + value->z = raw_value.z / sensitivity; + + return ESP_OK; +} + +esp_err_t icm42670_get_temp_value(icm42670_handle_t sensor, float *value) +{ + esp_err_t ret; + uint16_t raw_value; + + assert(value != NULL); + + *value = 0; + + ret = icm42670_get_temp_raw_value(sensor, &raw_value); + ESP_RETURN_ON_ERROR(ret, TAG, "Get raw value error!"); + + *value = (raw_value / 128) + 25; + + return ESP_OK; +} + +/******************************************************************************* +* Private functions +*******************************************************************************/ + +static esp_err_t icm42670_get_raw_value(icm42670_handle_t sensor, uint8_t reg, icm42670_raw_value_t *value) +{ + esp_err_t ret = ESP_FAIL; + uint8_t data[6]; + + assert(value != NULL); + + value->x = 0; + value->y = 0; + value->z = 0; + + ret = icm42670_read(sensor, reg, data, sizeof(data)); + if (ret == ESP_OK) { + value->x = (int16_t)((data[0] << 8) + data[1]); + value->y = (int16_t)((data[2] << 8) + data[3]); + value->z = (int16_t)((data[4] << 8) + data[5]); + } + + return ret; +} + +static esp_err_t icm42670_write(icm42670_handle_t sensor, const uint8_t reg_start_addr, const uint8_t *data_buf, const uint8_t data_len) +{ + icm42670_dev_t *sens = (icm42670_dev_t *) sensor; + esp_err_t ret; + + assert(sens); + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + ret = i2c_master_start(cmd); + assert(ESP_OK == ret); + ret = i2c_master_write_byte(cmd, (sens->dev_addr << 1) | I2C_MASTER_WRITE, true); + assert(ESP_OK == ret); + ret = i2c_master_write_byte(cmd, reg_start_addr, true); + assert(ESP_OK == ret); + ret = i2c_master_write(cmd, data_buf, data_len, true); + assert(ESP_OK == ret); + ret = i2c_master_stop(cmd); + assert(ESP_OK == ret); + ret = i2c_master_cmd_begin(sens->bus, cmd, 1000 / portTICK_PERIOD_MS); + i2c_cmd_link_delete(cmd); + + return ret; +} + +static esp_err_t icm42670_read(icm42670_handle_t sensor, const uint8_t reg_start_addr, uint8_t *data_buf, const uint8_t data_len) +{ + icm42670_dev_t *sens = (icm42670_dev_t *) sensor; + uint8_t reg_buff[] = {reg_start_addr}; + + assert(sens); + + /* Write register number and read data */ + return i2c_master_write_read_device(sens->bus, sens->dev_addr, reg_buff, sizeof(reg_buff), data_buf, data_len, 1000 / portTICK_PERIOD_MS); +} + +esp_err_t icm42670_complimentory_filter(icm42670_handle_t sensor, const icm42670_value_t *const acce_value, + const icm42670_value_t *const gyro_value, complimentary_angle_t *const complimentary_angle) +{ + float acce_angle[2]; + float gyro_angle[2]; + float gyro_rate[2]; + icm42670_dev_t *sens = (icm42670_dev_t *) sensor; + + sens->counter++; + if (sens->counter == 1) { + acce_angle[0] = (atan2(acce_value->y, acce_value->z) * RAD_TO_DEG); + acce_angle[1] = (atan2(acce_value->x, acce_value->z) * RAD_TO_DEG); + complimentary_angle->roll = acce_angle[0]; + complimentary_angle->pitch = acce_angle[1]; + gettimeofday(sens->timer, NULL); + return ESP_OK; + } + + struct timeval now, dt_t; + gettimeofday(&now, NULL); + timersub(&now, sens->timer, &dt_t); + sens->dt = (float) (dt_t.tv_sec) + (float)dt_t.tv_usec / 1000000; + gettimeofday(sens->timer, NULL); + + acce_angle[0] = (atan2(acce_value->y, acce_value->z) * RAD_TO_DEG); + acce_angle[1] = (atan2(acce_value->x, acce_value->z) * RAD_TO_DEG); + + gyro_rate[0] = gyro_value->x; + gyro_rate[1] = gyro_value->y; + gyro_angle[0] = gyro_rate[0] * sens->dt; + gyro_angle[1] = gyro_rate[1] * sens->dt; + + complimentary_angle->roll = (ALPHA * (complimentary_angle->roll + gyro_angle[0])) + ((1 - ALPHA) * acce_angle[0]); + complimentary_angle->pitch = (ALPHA * (complimentary_angle->pitch + gyro_angle[1])) + ((1 - ALPHA) * acce_angle[1]); + + return ESP_OK; +} diff --git a/components/icm42670/idf_component.yml b/components/icm42670/idf_component.yml new file mode 100644 index 00000000..2bf7dcfc --- /dev/null +++ b/components/icm42670/idf_component.yml @@ -0,0 +1,5 @@ +version: "1.0.0" +description: I2C driver for ICM 42670 6-Axis MotionTracking +url: https://github.com/espressif/esp-bsp/tree/master/components/icm42670 +dependencies: + idf: ">=4.4" diff --git a/components/icm42670/include/icm42670.h b/components/icm42670/include/icm42670.h new file mode 100644 index 00000000..a44b80f9 --- /dev/null +++ b/components/icm42670/include/icm42670.h @@ -0,0 +1,275 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "driver/i2c.h" + +#define ICM42670_I2C_ADDRESS 0x68 /*!< I2C address with AD0 pin low */ +#define ICM42670_I2C_ADDRESS_1 0x69 /*!< I2C address with AD0 pin high */ + +typedef enum { + ACCE_FS_16G = 0, /*!< Accelerometer full scale range is +/- 16g */ + ACCE_FS_8G = 1, /*!< Accelerometer full scale range is +/- 8g */ + ACCE_FS_4G = 2, /*!< Accelerometer full scale range is +/- 4g */ + ACCE_FS_2G = 3, /*!< Accelerometer full scale range is +/- 2g */ +} icm42670_acce_fs_t; + +typedef enum { + ACCE_PWR_OFF = 0, /*!< Accelerometer power off state */ + ACCE_PWR_ON = 1, /*!< Accelerometer power on state */ + ACCE_PWR_LOWPOWER = 2, /*!< Accelerometer low-power mode */ + ACCE_PWR_LOWNOISE = 3, /*!< Accelerometer low noise state */ +} icm42670_acce_pwr_t; + +typedef enum { + ACCE_ODR_1600HZ = 5, /*!< Accelerometer ODR 1.6 kHz */ + ACCE_ODR_800HZ = 6, /*!< Accelerometer ODR 800 Hz */ + ACCE_ODR_400HZ = 7, /*!< Accelerometer ODR 400 Hz */ + ACCE_ODR_200HZ = 8, /*!< Accelerometer ODR 200 Hz */ + ACCE_ODR_100HZ = 9, /*!< Accelerometer ODR 100 Hz */ + ACCE_ODR_50HZ = 10, /*!< Accelerometer ODR 50 Hz */ + ACCE_ODR_25HZ = 11, /*!< Accelerometer ODR 25 Hz */ + ACCE_ODR_12_5HZ = 12, /*!< Accelerometer ODR 12.5 Hz */ + ACCE_ODR_6_25HZ = 13, /*!< Accelerometer ODR 6.25 Hz */ + ACCE_ODR_3_125HZ = 14, /*!< Accelerometer ODR 3.125 Hz */ + ACCE_ODR_1_5625HZ = 15, /*!< Accelerometer ODR 1.5625 Hz */ +} icm42670_acce_odr_t; + +typedef enum { + GYRO_FS_2000DPS = 0, /*!< Gyroscope full scale range is +/- 2000 degree per sencond */ + GYRO_FS_1000DPS = 1, /*!< Gyroscope full scale range is +/- 1000 degree per sencond */ + GYRO_FS_500DPS = 2, /*!< Gyroscope full scale range is +/- 500 degree per sencond */ + GYRO_FS_250DPS = 3, /*!< Gyroscope full scale range is +/- 250 degree per sencond */ +} icm42670_gyro_fs_t; + +typedef enum { + GYRO_PWR_OFF = 0, /*!< Gyroscope power off state */ + GYRO_PWR_STANDBY = 1, /*!< Gyroscope power standby state */ + GYRO_PWR_LOWNOISE = 3, /*!< Gyroscope power low noise state */ +} icm42670_gyro_pwr_t; + +typedef enum { + GYRO_ODR_1600HZ = 5, /*!< Gyroscope ODR 1.6 kHz */ + GYRO_ODR_800HZ = 6, /*!< Gyroscope ODR 800 Hz */ + GYRO_ODR_400HZ = 7, /*!< Gyroscope ODR 400 Hz */ + GYRO_ODR_200HZ = 8, /*!< Gyroscope ODR 200 Hz */ + GYRO_ODR_100HZ = 9, /*!< Gyroscope ODR 100 Hz */ + GYRO_ODR_50HZ = 10, /*!< Gyroscope ODR 50 Hz */ + GYRO_ODR_25HZ = 11, /*!< Gyroscope ODR 25 Hz */ + GYRO_ODR_12_5HZ = 12, /*!< Gyroscope ODR 12.5 Hz */ +} icm42670_gyro_odr_t; + +typedef struct { + icm42670_acce_fs_t acce_fs; /*!< Accelerometer full scale range */ + icm42670_acce_odr_t acce_odr; /*!< Accelerometer ODR selection */ + icm42670_gyro_fs_t gyro_fs; /*!< Gyroscope full scale range */ + icm42670_gyro_odr_t gyro_odr; /*!< Gyroscope ODR selection */ +} icm42670_cfg_t; + +typedef struct { + int16_t x; + int16_t y; + int16_t z; +} icm42670_raw_value_t; + +typedef struct { + float x; + float y; + float z; +} icm42670_value_t; + +typedef struct { + float roll; + float pitch; +} complimentary_angle_t; + +typedef void *icm42670_handle_t; + +/** + * @brief Create and init sensor object and return a sensor handle + * + * @param port I2C port number + * @param dev_addr I2C device address of sensor + * + * @return + * - NULL Fail + * - Others Success + */ +icm42670_handle_t icm42670_create(i2c_port_t port, const uint8_t dev_addr); + +/** + * @brief Delete and release a sensor object + * + * @param sensor object handle of icm42670 + */ +void icm42670_delete(icm42670_handle_t sensor); + +/** + * @brief Get device identification of ICM42670 + * + * @param sensor object handle of icm42670 + * @param deviceid a pointer of device ID + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_get_deviceid(icm42670_handle_t sensor, uint8_t *deviceid); + +/** + * @brief Set accelerometer power mode + * + * @param sensor object handle of icm42670 + * @param state power mode of accelerometer + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_acce_set_pwr(icm42670_handle_t sensor, icm42670_acce_pwr_t state); + +/** + * @brief Set gyroscope power mode + * + * @param sensor object handle of icm42670 + * @param state power mode of gyroscope + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_gyro_set_pwr(icm42670_handle_t sensor, icm42670_gyro_pwr_t state); + +/** + * @brief Set accelerometer and gyroscope full scale range + * + * @param sensor object handle of icm42670 + * @param config Accelerometer and gyroscope configuration structure + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_config(icm42670_handle_t sensor, const icm42670_cfg_t *config); + +/** + * @brief Get accelerometer sensitivity + * + * @param sensor object handle of icm42670 + * @param sensitivity accelerometer sensitivity + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_get_acce_sensitivity(icm42670_handle_t sensor, float *sensitivity); + +/** + * @brief Get gyroscope sensitivity + * + * @param sensor object handle of icm42670 + * @param sensitivity gyroscope sensitivity + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_get_gyro_sensitivity(icm42670_handle_t sensor, float *sensitivity); + +/** + * @brief Read raw temperature measurements + * + * @param sensor object handle of icm42670 + * @param value raw temperature measurements + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_get_temp_raw_value(icm42670_handle_t sensor, uint16_t *value); + +/** + * @brief Read raw accelerometer measurements + * + * @param sensor object handle of icm42670 + * @param value raw accelerometer measurements + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_get_acce_raw_value(icm42670_handle_t sensor, icm42670_raw_value_t *value); + +/** + * @brief Read raw gyroscope measurements + * + * @param sensor object handle of icm42670 + * @param value raw gyroscope measurements + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_get_gyro_raw_value(icm42670_handle_t sensor, icm42670_raw_value_t *value); + +/** + * @brief Read accelerometer measurements + * + * @param sensor object handle of icm42670 + * @param value accelerometer measurements + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_get_acce_value(icm42670_handle_t sensor, icm42670_value_t *value); + +/** + * @brief Read gyro values + * + * @param sensor object handle of icm42670 + * @param value gyroscope measurements + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_get_gyro_value(icm42670_handle_t sensor, icm42670_value_t *value); + +/** + * @brief Read temperature value + * + * @param sensor object handle of icm42670 + * @param value temperature measurements + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_get_temp_value(icm42670_handle_t sensor, float *value); + +/** + * @brief use complimentory filter to caculate roll and pitch + * + * @param acce_value accelerometer measurements + * @param gyro_value gyroscope measurements + * @param complimentary_angle complimentary angle + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t icm42670_complimentory_filter(icm42670_handle_t sensor, const icm42670_value_t *acce_value, + const icm42670_value_t *gyro_value, complimentary_angle_t *complimentary_angle); + +#ifdef __cplusplus +} +#endif diff --git a/components/icm42670/license.txt b/components/icm42670/license.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/components/icm42670/license.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/test_app/CMakeLists.txt b/test_app/CMakeLists.txt index 9cec9a65..13fa8617 100644 --- a/test_app/CMakeLists.txt +++ b/test_app/CMakeLists.txt @@ -13,7 +13,7 @@ if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "4.4") list(APPEND EXTRA_COMPONENT_DIRS "../components/io_expander") endif() if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_LESS "4.4") - set(EXCLUDE_COMPONENTS "es8311" "es7210" "esp_lvgl_port" "ds18b20") + set(EXCLUDE_COMPONENTS "es8311" "es7210" "esp_lvgl_port" "ds18b20" "icm42670") elseif("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_LESS "5.0") set(EXCLUDE_COMPONENTS "esp_lcd_touch_stmpe610" "ds18b20" "esp_lcd_ssd1681") endif() @@ -24,6 +24,6 @@ if(NOT "${IDF_TARGET}" STREQUAL "esp32s3") endif() # Set the components to include the tests for. -set(TEST_COMPONENTS bh1750 ssd1306 mpu6050 mag3110 hts221 fbm320 es7210 CACHE STRING "List of components to test") +set(TEST_COMPONENTS bh1750 ssd1306 mpu6050 mag3110 hts221 fbm320 es7210 icm42670 CACHE STRING "List of components to test") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(esp_bsp_test_app)