From 2f45a41a2089fa421510531b3e12e08af7b3c7f7 Mon Sep 17 00:00:00 2001 From: xyzroe Date: Mon, 9 Jun 2025 11:41:56 +0200 Subject: [PATCH 01/11] feat(qmi8658c): add driver for QMI8658C 6-axis IMU sensor --- components/qmi8658c/.eil.yml | 22 +++ components/qmi8658c/CMakeLists.txt | 5 + components/qmi8658c/LICENSE | 26 +++ components/qmi8658c/component.mk | 2 + components/qmi8658c/qmi8658c.c | 260 +++++++++++++++++++++++++++++ components/qmi8658c/qmi8658c.h | 181 ++++++++++++++++++++ 6 files changed, 496 insertions(+) create mode 100644 components/qmi8658c/.eil.yml create mode 100644 components/qmi8658c/CMakeLists.txt create mode 100644 components/qmi8658c/LICENSE create mode 100644 components/qmi8658c/component.mk create mode 100644 components/qmi8658c/qmi8658c.c create mode 100644 components/qmi8658c/qmi8658c.h diff --git a/components/qmi8658c/.eil.yml b/components/qmi8658c/.eil.yml new file mode 100644 index 00000000..cc168daf --- /dev/null +++ b/components/qmi8658c/.eil.yml @@ -0,0 +1,22 @@ +name: qmi8658c +description: Driver for QMI8658C 6-axis IMU sensor +version: 0.5.0 +groups: + - magnetic +code_owners: xyzroe +depends: + - i2cdev + - log + - esp_idf_lib_helpers +thread_safe: yes +targets: + - esp32 + - esp32c3 + - esp8266 + - esp32s2 + - esp32c3 + - esp32c6 +license: BSD-3 +copyrights: + - name: xyzroe + year: 2024 \ No newline at end of file diff --git a/components/qmi8658c/CMakeLists.txt b/components/qmi8658c/CMakeLists.txt new file mode 100644 index 00000000..88688eb7 --- /dev/null +++ b/components/qmi8658c/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + SRCS qmi8658c.c + INCLUDE_DIRS . + REQUIRES i2cdev log esp_idf_lib_helpers +) \ No newline at end of file diff --git a/components/qmi8658c/LICENSE b/components/qmi8658c/LICENSE new file mode 100644 index 00000000..462a2103 --- /dev/null +++ b/components/qmi8658c/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2024 xyzroe + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/components/qmi8658c/component.mk b/components/qmi8658c/component.mk new file mode 100644 index 00000000..a3610e86 --- /dev/null +++ b/components/qmi8658c/component.mk @@ -0,0 +1,2 @@ +COMPONENT_ADD_INCLUDEDIRS = . +COMPONENT_DEPENDS = i2cdev log esp_idf_lib_helpers diff --git a/components/qmi8658c/qmi8658c.c b/components/qmi8658c/qmi8658c.c new file mode 100644 index 00000000..4bcd1e4b --- /dev/null +++ b/components/qmi8658c/qmi8658c.c @@ -0,0 +1,260 @@ +/** + * @file qmi8658c.c + * @brief QMI8658C sensor driver + * @author xyzroe + * ESP-IDF driver for QMI8658C sensor + * + * Datasheet: https://qstcorp.com/upload/pdf/202202/QMI8658C%20datasheet%20rev%200.9.pdf + * + * Copyright (c) 2024 xyzroe + * Licensed as described in the file LICENSE + */ + +#include +#include +#include +#include +#include "qmi8658c.h" + +static const char *TAG = "qmi8658c"; + +#define CHECK(x) \ + do \ + { \ + esp_err_t __; \ + if ((__ = x) != ESP_OK) \ + return __; \ + } \ + while (0) +#define CHECK_ARG(VAL) \ + do \ + { \ + if (!(VAL)) \ + return ESP_ERR_INVALID_ARG; \ + } \ + while (0) + +static qmi_ctx_t qmi_ctx; + +inline static esp_err_t send_command_nolock(i2c_dev_t *dev, uint8_t reg, uint8_t value) +{ + uint8_t data[2] = { reg, value }; + return i2c_dev_write(dev, NULL, 0, data, 2); +} + +static esp_err_t send_command(i2c_dev_t *dev, uint8_t reg, uint8_t value) +{ + I2C_DEV_TAKE_MUTEX(dev); + I2C_DEV_CHECK(dev, send_command_nolock(dev, reg, value)); + I2C_DEV_GIVE_MUTEX(dev); + + return ESP_OK; +} + +#define REPLY_DELAY_MS 25 + +static esp_err_t read_register(i2c_dev_t *dev, uint8_t reg, uint8_t *value) +{ + I2C_DEV_TAKE_MUTEX(dev); + + I2C_DEV_CHECK(dev, i2c_dev_read_reg(dev, reg, value, 1)); + + vTaskDelay(pdMS_TO_TICKS(REPLY_DELAY_MS)); + + I2C_DEV_GIVE_MUTEX(dev); + + return ESP_OK; +} + +esp_err_t qmi8658c_init_desc(i2c_dev_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio) +{ + CHECK_ARG(dev); + + dev->port = port; + dev->addr = addr; + dev->cfg.sda_io_num = sda_gpio; + dev->cfg.scl_io_num = scl_gpio; +#if HELPER_TARGET_IS_ESP32 + dev->cfg.master.clk_speed = QMI8658C_I2C_FREQ_HZ; +#endif + return i2c_dev_create_mutex(dev); +} + +esp_err_t qmi8658c_free_desc(i2c_dev_t *dev) +{ + CHECK_ARG(dev); + return i2c_dev_delete_mutex(dev); + /* + uint8_t ctrl7, ctrl1; + + // Read QMI8658_CTRL7 register + CHECK(read_register(dev, QMI8658_CTRL7, &ctrl7)); + + // Disable accelerometer, gyroscope, magnetometer and attitude engine + ctrl7 &= 0xF0; + CHECK(send_command(dev, QMI8658_CTRL7, ctrl7)); + + // Disable sensor by turning off the internal 2 MHz oscillator + CHECK(read_register(dev, QMI8658_CTRL1, &ctrl1)); + ctrl1 |= (1 << 0); + CHECK(send_command(dev, QMI8658_CTRL1, ctrl1)); + + // Read these two registers again to verify + CHECK(read_register(dev, QMI8658_CTRL7, &ctrl7)); + CHECK(read_register(dev, QMI8658_CTRL1, &ctrl1)); + + // Verify if the sensor is properly disabled + if (!(ctrl7 & 0x0F) && (ctrl1 & 0x01)) + { + return i2c_dev_delete_mutex(dev); + } + else + { + return ESP_FAIL; + } + */ +} + +esp_err_t qmi8658c_reset(i2c_dev_t *dev) +{ + CHECK_ARG(dev); + + return send_command(dev, QMI8658_RESET, 0xB0); +} + +/* Accelerometer sensitivity table */ +uint16_t acc_scale_sensitivity_table[4] = { + ACC_SCALE_SENSITIVITY_2G, // Sensitivity for ±2g range. + ACC_SCALE_SENSITIVITY_4G, // Sensitivity for ±4g range. + ACC_SCALE_SENSITIVITY_8G, // Sensitivity for ±8g range. + ACC_SCALE_SENSITIVITY_16G // Sensitivity for ±16g range. +}; + +/* Gyroscope sensitivity table */ +uint16_t gyro_scale_sensitivity_table[8] = { + GYRO_SCALE_SENSITIVITY_16DPS, // Sensitivity for ±16 degrees per second range. + GYRO_SCALE_SENSITIVITY_32DPS, // Sensitivity for ±32 degrees per second range. + GYRO_SCALE_SENSITIVITY_64DPS, // Sensitivity for ±64 degrees per second range. + GYRO_SCALE_SENSITIVITY_128DPS, // Sensitivity for ±128 degrees per second range. + GYRO_SCALE_SENSITIVITY_256DPS, // Sensitivity for ±256 degrees per second range. + GYRO_SCALE_SENSITIVITY_512DPS, // Sensitivity for ±512 degrees per second range. + GYRO_SCALE_SENSITIVITY_1024DPS, // Sensitivity for ±1024 degrees per second range. + GYRO_SCALE_SENSITIVITY_2048DPS // Sensitivity for ±2048 degrees per second range. +}; + +esp_err_t qmi8658c_setup(i2c_dev_t *dev, qmi8658c_config_t *config) +{ + CHECK_ARG(dev && config); + + // reset device + qmi8658c_reset(dev); + + // set mode + uint8_t ctrl7; + CHECK(read_register(dev, QMI8658_CTRL7, &ctrl7)); + ctrl7 = (ctrl7 & 0xFC) | config->mode; + CHECK(send_command(dev, QMI8658_CTRL7, ctrl7)); + + // set accelerometr scale and ODR + uint8_t ctrl2; + CHECK(read_register(dev, QMI8658_CTRL2, &ctrl2)); + ctrl2 = (ctrl2 & 0xF0) | config->acc_odr; + ctrl2 = (ctrl2 & 0x8F) | (config->acc_scale << 4); + CHECK(send_command(dev, QMI8658_CTRL2, ctrl2)); + + // set accelerometer scale and sensitivity + qmi_ctx.acc_scale = config->acc_scale; + qmi_ctx.acc_sensitivity = acc_scale_sensitivity_table[config->acc_scale]; + + // set gyroscope scale and ODR + uint8_t ctrl3; + CHECK(read_register(dev, QMI8658_CTRL3, &ctrl3)); + ctrl3 = (ctrl3 & 0xF0) | config->gyro_odr; + ctrl3 = (ctrl3 & 0x8F) | (config->gyro_scale << 4); + CHECK(send_command(dev, QMI8658_CTRL3, ctrl3)); + + // set gyroscope scale and sensitivity + qmi_ctx.gyro_scale = config->gyro_scale; + qmi_ctx.gyro_sensitivity = gyro_scale_sensitivity_table[config->gyro_scale]; + + // read device ID and revision ID + CHECK(read_register(dev, QMI8658_WHO_AM_I, &qmi_ctx.who_am_i)); + CHECK(read_register(dev, QMI8658_REVISION, &qmi_ctx.revision)); + + ESP_LOGW(TAG, "device ID: 0x%02X, revision: 0x%02X", qmi_ctx.who_am_i, qmi_ctx.revision); + + // Verify mode setting + uint8_t qmi8658_ctrl7; + CHECK(read_register(dev, QMI8658_CTRL7, &qmi8658_ctrl7)); + if ((qmi8658_ctrl7 & 0x03) != config->mode) + { + ESP_LOGE(TAG, "Mode setting verification failed"); + return ESP_FAIL; + } + + return ESP_OK; +} + +esp_err_t qmi8658c_read_data(i2c_dev_t *dev, qmi8658c_data_t *data) +{ + CHECK_ARG(dev && data); + + // Read accelerometer data + uint8_t acc_x_l, acc_x_h, acc_y_l, acc_y_h, acc_z_l, acc_z_h; + CHECK(read_register(dev, QMI8658_ACC_X_L, &acc_x_l)); + CHECK(read_register(dev, QMI8658_ACC_X_H, &acc_x_h)); + CHECK(read_register(dev, QMI8658_ACC_Y_L, &acc_y_l)); + CHECK(read_register(dev, QMI8658_ACC_Y_H, &acc_y_h)); + CHECK(read_register(dev, QMI8658_ACC_Z_L, &acc_z_l)); + CHECK(read_register(dev, QMI8658_ACC_Z_H, &acc_z_h)); + + // ESP_LOGE(TAG, "acc_x_l: %d, acc_x_h: %d, acc_y_l: %d, acc_y_h: %d, acc_z_l: %d, acc_z_h: %d", acc_x_l, acc_x_h, acc_y_l, acc_y_h, acc_z_l, acc_z_h); + + int16_t acc_x = (int16_t)((acc_x_h << 8) | acc_x_l); + int16_t acc_y = (int16_t)((acc_y_h << 8) | acc_y_l); + int16_t acc_z = (int16_t)((acc_z_h << 8) | acc_z_l); + + // ESP_LOGW(TAG, "acc_x: %d, acc_y: %d, acc_z: %d", acc_x, acc_y, acc_z); + + data->acc.x = (float)acc_x / qmi_ctx.acc_sensitivity; + data->acc.y = (float)acc_y / qmi_ctx.acc_sensitivity; + data->acc.z = (float)acc_z / qmi_ctx.acc_sensitivity; + + // Read gyroscope data + uint8_t gyr_x_l, gyr_x_h, gyr_y_l, gyr_y_h, gyr_z_l, gyr_z_h; + CHECK(read_register(dev, QMI8658_GYR_X_L, &gyr_x_l)); + CHECK(read_register(dev, QMI8658_GYR_X_H, &gyr_x_h)); + CHECK(read_register(dev, QMI8658_GYR_Y_L, &gyr_y_l)); + CHECK(read_register(dev, QMI8658_GYR_Y_H, &gyr_y_h)); + CHECK(read_register(dev, QMI8658_GYR_Z_L, &gyr_z_l)); + CHECK(read_register(dev, QMI8658_GYR_Z_H, &gyr_z_h)); + + // ESP_LOGE(TAG, "gyr_x_l: %d, gyr_x_h: %d, gyr_y_l: %d, gyr_y_h: %d, gyr_z_l: %d, gyr_z_h: %d", gyr_x_l, gyr_x_h, gyr_y_l, gyr_y_h, gyr_z_l, gyr_z_h); + + int16_t gyr_x = (int16_t)((gyr_x_h << 8) | gyr_x_l); + int16_t gyr_y = (int16_t)((gyr_y_h << 8) | gyr_y_l); + int16_t gyr_z = (int16_t)((gyr_z_h << 8) | gyr_z_l); + + // ESP_LOGW(TAG, "gyr_x: %d, gyr_y: %d, gyr_z: %d", gyr_x, gyr_y, gyr_z); + + data->gyro.x = (float)gyr_x / qmi_ctx.gyro_sensitivity; + data->gyro.y = (float)gyr_y / qmi_ctx.gyro_sensitivity; + data->gyro.z = (float)gyr_z / qmi_ctx.gyro_sensitivity; + + // Read temperature data + uint8_t temp_l, temp_h; + CHECK(read_register(dev, QMI8658_TEMP_L, &temp_l)); + CHECK(read_register(dev, QMI8658_TEMP_H, &temp_h)); + + // ESP_LOGE(TAG, "temp_l: %d, temp_h: %d", temp_l, temp_h); + + int16_t temp = (int16_t)((temp_h << 8) | temp_l); + // ESP_LOGW(TAG, "temp: %d", temp); + + data->temperature = (float)temp / TEMPERATURE_SENSOR_RESOLUTION; + + // ESP_LOGW(TAG, "Acc: x=%f, y=%f, z=%f; Gyro: x=%f, y=%f, z=%f; Temp: %f", + // data->acc.x, data->acc.y, data->acc.z, data->gyro.x, data->gyro.y, data->gyro.z, data->temperature); + + return ESP_OK; +} \ No newline at end of file diff --git a/components/qmi8658c/qmi8658c.h b/components/qmi8658c/qmi8658c.h new file mode 100644 index 00000000..4abc3ec1 --- /dev/null +++ b/components/qmi8658c/qmi8658c.h @@ -0,0 +1,181 @@ +/** + * @file qmi8658c.h + * @brief Header file for QMI8658C sensor driver + * @author xyzroe + * ESP-IDF driver for QMI8658C sensor + * + * Datasheet: https://qstcorp.com/upload/pdf/202202/QMI8658C%20datasheet%20rev%200.9.pdf + * + * Copyright (c) 2024 xyzroe + * Licensed as described in the file LICENSE + */ + +#ifndef __QMI8658C_H__ +#define __QMI8658C_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEFAUL_QMI8658C_ADDR 0x6B //!< I2C address for QMI8658C +#define QMI8658C_I2C_FREQ_HZ 400000 + +/* General purpose registers */ +#define QMI8658_WHO_AM_I 0x00 // WHO_AM_I register address. +#define QMI8658_REVISION 0x01 // REVISION register address. + +/* Setup and control registers */ +#define QMI8658_CTRL1 0x02 // Control register 1 address. +#define QMI8658_CTRL2 0x03 // Control register 2 address. +#define QMI8658_CTRL3 0x04 // Control register 3 address. +#define QMI8658_CTRL4 0x05 // Control register 4 address. +#define QMI8658_CTRL5 0x06 // Control register 5 address. +#define QMI8658_CTRL6 0x07 // Control register 6 address. +#define QMI8658_CTRL7 0x08 // Control register 7 address. +#define QMI8658_CTRL9 0x0A // Control register 9 address. + +/* Data output registers */ + +// Accelerometer +#define QMI8658_ACC_X_L 0x35 // Accelerometer X-axis low byte. +#define QMI8658_ACC_X_H 0x36 // Accelerometer X-axis high byte. +#define QMI8658_ACC_Y_L 0x37 // Accelerometer Y-axis low byte. +#define QMI8658_ACC_Y_H 0x38 // Accelerometer Y-axis high byte. +#define QMI8658_ACC_Z_L 0x39 // Accelerometer Z-axis low byte. +#define QMI8658_ACC_Z_H 0x3A // Accelerometer Z-axis high byte. + +// Gyroscope +#define QMI8658_GYR_X_L 0x3B // Gyroscope X-axis low byte. +#define QMI8658_GYR_X_H 0x3C // Gyroscope X-axis high byte. +#define QMI8658_GYR_Y_L 0x3D // Gyroscope Y-axis low byte. +#define QMI8658_GYR_Y_H 0x3E // Gyroscope Y-axis high byte. +#define QMI8658_GYR_Z_L 0x3F // Gyroscope Z-axis low byte. +#define QMI8658_GYR_Z_H 0x40 // Gyroscope Z-axis high byte. + +// Temperature sensor +#define QMI8658_TEMP_L 0x33 // Temperature sensor low byte. +#define QMI8658_TEMP_H 0x34 // Temperature sensor high byte. + +/* Soft reset register */ +#define QMI8658_RESET 0x60 // Soft reset register address. + +/* define scale sensitivity */ +/* Accelerometer scale sensitivity values for different gravity ranges */ +#define ACC_SCALE_SENSITIVITY_2G (1 << 14) // Sensitivity for ±2g range. +#define ACC_SCALE_SENSITIVITY_4G (1 << 13) // Sensitivity for ±4g range. +#define ACC_SCALE_SENSITIVITY_8G (1 << 12) // Sensitivity for ±8g range. +#define ACC_SCALE_SENSITIVITY_16G (1 << 11) // Sensitivity for ±16g range. + +/* Gyroscope scale sensitivity values for different degrees per second ranges */ +#define GYRO_SCALE_SENSITIVITY_16DPS (1 << 11) // Sensitivity for ±16 degrees per second range. +#define GYRO_SCALE_SENSITIVITY_32DPS (1 << 10) // Sensitivity for ±32 degrees per second range. +#define GYRO_SCALE_SENSITIVITY_64DPS (1 << 9) // Sensitivity for ±64 degrees per second range. +#define GYRO_SCALE_SENSITIVITY_128DPS (1 << 8) // Sensitivity for ±128 degrees per second range. +#define GYRO_SCALE_SENSITIVITY_256DPS (1 << 7) // Sensitivity for ±256 degrees per second range. +#define GYRO_SCALE_SENSITIVITY_512DPS (1 << 6) // Sensitivity for ±512 degrees per second range. +#define GYRO_SCALE_SENSITIVITY_1024DPS (1 << 5) // Sensitivity for ±1024 degrees per second range. +#define GYRO_SCALE_SENSITIVITY_2048DPS (1 << 4) // Sensitivity for ±2048 degrees per second range. + +typedef enum { + QMI8658C_MODE_ACC_ONLY = 1, + QMI8658C_MODE_GYRO_ONLY, + QMI8658C_MODE_DUAL, +} qmi8658c_mode_t; + +typedef enum { + QMI8658C_ACC_ODR_8000, + QMI8658C_ACC_ODR_4000, + QMI8658C_ACC_ODR_2000, + QMI8658C_ACC_ODR_1000, + QMI8658C_ACC_ODR_500, + QMI8658C_ACC_ODR_250, + QMI8658C_ACC_ODR_125, + QMI8658C_ACC_ODR_62_5, + QMI8658C_ACC_ODR_31_25, + QMI8658C_ACC_ODR_128 = 12, + QMI8658C_ACC_ODR_21, + QMI8658C_ACC_ODR_11, + QMI8658C_ACC_ODR_3, +} qmi8658c_acc_odr_t; + +typedef enum { + QMI8658C_GYRO_ODR_8000, + QMI8658C_GYRO_ODR_4000, + QMI8658C_GYRO_ODR_2000, + QMI8658C_GYRO_ODR_1000, + QMI8658C_GYRO_ODR_500, + QMI8658C_GYRO_ODR_250, + QMI8658C_GYRO_ODR_125, + QMI8658C_GYRO_ODR_62_5, + QMI8658C_GYRO_ODR_31_25, +} qmi8658c_gyro_odr_t; + +typedef enum { + QMI8658C_ACC_SCALE_2G, + QMI8658C_ACC_SCALE_4G, + QMI8658C_ACC_SCALE_8G, + QMI8658C_ACC_SCALE_16G, +} qmi8658c_acc_scale_t; + +typedef enum { + QMI8658C_GYRO_SCALE_16DPS, + QMI8658C_GYRO_SCALE_32DPS, + QMI8658C_GYRO_SCALE_64DPS, + QMI8658C_GYRO_SCALE_128DPS, + QMI8658C_GYRO_SCALE_256DPS, + QMI8658C_GYRO_SCALE_512DPS, + QMI8658C_GYRO_SCALE_1024DPS, + QMI8658C_GYRO_SCALE_2048DPS, +} qmi8658c_gyro_scale_t; + +#define TEMPERATURE_SENSOR_RESOLUTION (1 << 8) // Telperature sensor resolution (ADC) + +typedef struct +{ + float x; + float y; + float z; +} qmi8658c_axes_t; + +typedef struct +{ + uint16_t acc_sensitivity; // Sensitivity value for the accelerometer. + uint8_t acc_scale; // Scale setting for the accelerometer. + uint16_t gyro_sensitivity; // Sensitivity value for the gyroscope. + uint8_t gyro_scale; // Scale setting for the gyroscope. + uint8_t who_am_i; + uint8_t revision; +} qmi_ctx_t; + +typedef struct +{ + qmi8658c_axes_t acc; + qmi8658c_axes_t gyro; + float temperature; +} qmi8658c_data_t; + +typedef struct +{ + qmi8658c_mode_t mode; + qmi8658c_acc_scale_t acc_scale; + qmi8658c_acc_odr_t acc_odr; + qmi8658c_gyro_scale_t gyro_scale; + qmi8658c_gyro_odr_t gyro_odr; +} qmi8658c_config_t; + +esp_err_t qmi8658c_init_desc(i2c_dev_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio); +esp_err_t qmi8658c_free_desc(i2c_dev_t *dev); +esp_err_t qmi8658c_power_on(i2c_dev_t *dev); +esp_err_t qmi8658c_power_down(i2c_dev_t *dev); +esp_err_t qmi8658c_setup(i2c_dev_t *dev, qmi8658c_config_t *config); +esp_err_t qmi8658c_read_data(i2c_dev_t *dev, qmi8658c_data_t *data); + +#ifdef __cplusplus +} +#endif + +#endif /* __QMI8658C_H__ */ \ No newline at end of file From 34f77184d1731e90648f9a98b8c8974ad285d21f Mon Sep 17 00:00:00 2001 From: xyzroe Date: Mon, 9 Jun 2025 11:46:54 +0200 Subject: [PATCH 02/11] feat(persons): add xyzroe to persons.yml with email and GitHub ID --- devtools/persons.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/devtools/persons.yml b/devtools/persons.yml index ff3c7773..8d89427f 100644 --- a/devtools/persons.yml +++ b/devtools/persons.yml @@ -164,3 +164,8 @@ - name: vonguced full_name: Cedric von Gunten gh_id: vonguced + + name: xyzroe + gh_id: xyzroe + email: i@xyzroe.cc + \ No newline at end of file From 4381add2dbf946c820a10b5bd7433fcaadde9ea4 Mon Sep 17 00:00:00 2001 From: xyzroe Date: Mon, 9 Jun 2025 11:48:45 +0200 Subject: [PATCH 03/11] fix(persons): fix persons.yml --- devtools/persons.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/devtools/persons.yml b/devtools/persons.yml index 8d89427f..cf748c50 100644 --- a/devtools/persons.yml +++ b/devtools/persons.yml @@ -165,7 +165,6 @@ full_name: Cedric von Gunten gh_id: vonguced - name: xyzroe +- name: xyzroe gh_id: xyzroe email: i@xyzroe.cc - \ No newline at end of file From 0ede8a2e51596b7d0217f4fc36cb0ce52eac5ab4 Mon Sep 17 00:00:00 2001 From: xyzroe Date: Mon, 9 Jun 2025 11:53:11 +0200 Subject: [PATCH 04/11] fix(qmi8658c): include freertos/task.h for task management --- components/qmi8658c/qmi8658c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/qmi8658c/qmi8658c.c b/components/qmi8658c/qmi8658c.c index 4bcd1e4b..1daa7031 100644 --- a/components/qmi8658c/qmi8658c.c +++ b/components/qmi8658c/qmi8658c.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include "qmi8658c.h" From fc1414abbe016cf12e4fe4c5d2220d800ae8eab8 Mon Sep 17 00:00:00 2001 From: xyzroe Date: Mon, 9 Jun 2025 12:28:17 +0200 Subject: [PATCH 05/11] feat(qmi8658c): add example for QMI8658C sensor with initialization and data reading --- examples/qmi8658c/default/CMakeLists.txt | 6 ++ examples/qmi8658c/default/Makefile | 6 ++ examples/qmi8658c/default/README.md | 26 ++++++++ examples/qmi8658c/default/main/CMakeLists.txt | 2 + examples/qmi8658c/default/main/component.mk | 1 + examples/qmi8658c/default/main/main.c | 65 +++++++++++++++++++ examples/qmi8658c/default/sdkconfig.defaults | 1 + 7 files changed, 107 insertions(+) create mode 100644 examples/qmi8658c/default/CMakeLists.txt create mode 100644 examples/qmi8658c/default/Makefile create mode 100644 examples/qmi8658c/default/README.md create mode 100644 examples/qmi8658c/default/main/CMakeLists.txt create mode 100644 examples/qmi8658c/default/main/component.mk create mode 100644 examples/qmi8658c/default/main/main.c create mode 100644 examples/qmi8658c/default/sdkconfig.defaults diff --git a/examples/qmi8658c/default/CMakeLists.txt b/examples/qmi8658c/default/CMakeLists.txt new file mode 100644 index 00000000..194dea76 --- /dev/null +++ b/examples/qmi8658c/default/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../../components) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(qmi8658c) diff --git a/examples/qmi8658c/default/Makefile b/examples/qmi8658c/default/Makefile new file mode 100644 index 00000000..63c8e42a --- /dev/null +++ b/examples/qmi8658c/default/Makefile @@ -0,0 +1,6 @@ +#V := 1 +PROJECT_NAME := example-qmi8658c + +EXTRA_COMPONENT_DIRS := $(CURDIR)/../../../components + +include $(IDF_PATH)/make/project.mk diff --git a/examples/qmi8658c/default/README.md b/examples/qmi8658c/default/README.md new file mode 100644 index 00000000..f712799a --- /dev/null +++ b/examples/qmi8658c/default/README.md @@ -0,0 +1,26 @@ +# Example for `qmi8658c` driver + +## What it does + +This example demonstrates basic usage of the QMI8658C 6-axis IMU sensor. +It initializes the sensor, periodically reads accelerometer, gyroscope, and temperature data, and prints the results to the log. + +## Wiring + +Connect the `SCL` and `SDA` pins of the QMI8658C sensor to your ESP board with appropriate pull-up resistors. + +| Name | Description | Defaults (ESP32) | +|---------------------------------|-----------------------|------------------| +| `CONFIG_EXAMPLE_I2C_MASTER_SCL` | GPIO number for SCL | 22 | +| `CONFIG_EXAMPLE_I2C_MASTER_SDA` | GPIO number for SDA | 21 | + +## Usage + +1. Build and flash the example to your ESP board. +2. Open the serial monitor to view sensor data output. + +## Notes + +- Make sure the I2C address matches your hardware (default: `0x6B`). +- Adjust the I2C pins in `sdkconfig` or directly in the example code if needed. +- The code under `main` follows ESP-IDF code style. \ No newline at end of file diff --git a/examples/qmi8658c/default/main/CMakeLists.txt b/examples/qmi8658c/default/main/CMakeLists.txt new file mode 100644 index 00000000..cf2c455c --- /dev/null +++ b/examples/qmi8658c/default/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/qmi8658c/default/main/component.mk b/examples/qmi8658c/default/main/component.mk new file mode 100644 index 00000000..004b18e6 --- /dev/null +++ b/examples/qmi8658c/default/main/component.mk @@ -0,0 +1 @@ +COMPONENT_ADD_INCLUDEDIRS = . diff --git a/examples/qmi8658c/default/main/main.c b/examples/qmi8658c/default/main/main.c new file mode 100644 index 00000000..a63c7adb --- /dev/null +++ b/examples/qmi8658c/default/main/main.c @@ -0,0 +1,65 @@ +/** + * Simple example with QMI8658C sensor. + * + * Shows basic initialization and periodic data reading. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef APP_CPU_NUM +#define APP_CPU_NUM PRO_CPU_NUM +#endif + +static const char *TAG = "qmi8658c_example"; + +static void qmi8658c_task(void *pvParameters) +{ + i2c_dev_t dev = {0}; + + const uint8_t I2C_ADDRESS = 0x6B; + + ESP_ERROR_CHECK(qmi8658c_init_desc(&dev, I2C_ADDRESS, 0, CONFIG_EXAMPLE_I2C_MASTER_SDA, CONFIG_EXAMPLE_I2C_MASTER_SDA)); + + qmi8658c_config_t config = { + .mode = QMI8658C_MODE_DUAL, + .acc_scale = QMI8658C_ACC_SCALE_4G, + .acc_odr = QMI8658C_ACC_ODR_1000, + .gyro_scale = QMI8658C_GYRO_SCALE_64DPS, + .gyro_odr = QMI8658C_GYRO_ODR_8000, + }; + + ESP_ERROR_CHECK(qmi8658c_setup(&dev, &config)); + + vTaskDelay(pdMS_TO_TICKS(100)); // Дать сенсору стартануть + + while (1) + { + qmi8658c_data_t data; + esp_err_t res = qmi8658c_read_data(&dev, &data); + if (res == ESP_OK) + { + ESP_LOGI(TAG, "Acc: x=%.3f y=%.3f z=%.3f | Gyro: x=%.3f y=%.3f z=%.3f | Temp: %.2f", + data.acc.x, data.acc.y, data.acc.z, + data.gyro.x, data.gyro.y, data.gyro.z, + data.temperature); + } + else + { + ESP_LOGE(TAG, "Sensor read error: %s", esp_err_to_name(res)); + } + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +void app_main() +{ + ESP_ERROR_CHECK(i2cdev_init()); + xTaskCreatePinnedToCore(qmi8658c_task, "qmi8658c_task", 4096, NULL, 5, NULL, APP_CPU_NUM); +} \ No newline at end of file diff --git a/examples/qmi8658c/default/sdkconfig.defaults b/examples/qmi8658c/default/sdkconfig.defaults new file mode 100644 index 00000000..cd8cb435 --- /dev/null +++ b/examples/qmi8658c/default/sdkconfig.defaults @@ -0,0 +1 @@ +# add required non-default option for the example if any From 1b506687ff3c605cda4315fc31ca6134384a9627 Mon Sep 17 00:00:00 2001 From: xyzroe Date: Tue, 10 Jun 2025 13:51:39 +0200 Subject: [PATCH 06/11] feat(qmi8658c): add I2C master configuration options for example --- examples/qmi8658c/default/sdkconfig.defaults | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/qmi8658c/default/sdkconfig.defaults b/examples/qmi8658c/default/sdkconfig.defaults index cd8cb435..d0a8705d 100644 --- a/examples/qmi8658c/default/sdkconfig.defaults +++ b/examples/qmi8658c/default/sdkconfig.defaults @@ -1 +1,3 @@ # add required non-default option for the example if any +CONFIG_EXAMPLE_I2C_MASTER_SCL=22 +CONFIG_EXAMPLE_I2C_MASTER_SDA=21 \ No newline at end of file From 4344f43256cca2cf4cddf9390312ee9ec9dced84 Mon Sep 17 00:00:00 2001 From: xyzroe Date: Tue, 10 Jun 2025 14:59:21 +0200 Subject: [PATCH 07/11] feat(qmi8658c): add Kconfig for QMI8658C example configuration --- examples/qmi8658c/default/main/Kconfig.projbuild | 10 ++++++++++ examples/qmi8658c/default/main/main.c | 4 +--- examples/qmi8658c/default/sdkconfig.defaults | 3 --- 3 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 examples/qmi8658c/default/main/Kconfig.projbuild delete mode 100644 examples/qmi8658c/default/sdkconfig.defaults diff --git a/examples/qmi8658c/default/main/Kconfig.projbuild b/examples/qmi8658c/default/main/Kconfig.projbuild new file mode 100644 index 00000000..50ee3885 --- /dev/null +++ b/examples/qmi8658c/default/main/Kconfig.projbuild @@ -0,0 +1,10 @@ +menu "Example configuration" + config EXAMPLE_QMI_ADDRESS + hex "I2C address of QMI8658C" + default 0x6B + help + I2C address of QMI8658C IMU. + This address is used to communicate with the IMU over I2C. + The default value is 0x6B, which is the common address for this device. + rsource "../../../../devtools/Kconfig.i2c" +endmenu \ No newline at end of file diff --git a/examples/qmi8658c/default/main/main.c b/examples/qmi8658c/default/main/main.c index a63c7adb..a534bbb3 100644 --- a/examples/qmi8658c/default/main/main.c +++ b/examples/qmi8658c/default/main/main.c @@ -23,9 +23,7 @@ static void qmi8658c_task(void *pvParameters) { i2c_dev_t dev = {0}; - const uint8_t I2C_ADDRESS = 0x6B; - - ESP_ERROR_CHECK(qmi8658c_init_desc(&dev, I2C_ADDRESS, 0, CONFIG_EXAMPLE_I2C_MASTER_SDA, CONFIG_EXAMPLE_I2C_MASTER_SDA)); + ESP_ERROR_CHECK(qmi8658c_init_desc(&dev, CONFIG_EXAMPLE_QMI_ADDRESS, 0, CONFIG_EXAMPLE_I2C_MASTER_SDA, CONFIG_EXAMPLE_I2C_MASTER_SDA)); qmi8658c_config_t config = { .mode = QMI8658C_MODE_DUAL, diff --git a/examples/qmi8658c/default/sdkconfig.defaults b/examples/qmi8658c/default/sdkconfig.defaults deleted file mode 100644 index d0a8705d..00000000 --- a/examples/qmi8658c/default/sdkconfig.defaults +++ /dev/null @@ -1,3 +0,0 @@ -# add required non-default option for the example if any -CONFIG_EXAMPLE_I2C_MASTER_SCL=22 -CONFIG_EXAMPLE_I2C_MASTER_SDA=21 \ No newline at end of file From 47c774a66968c3300632cdb77f3d0aba27e3a153 Mon Sep 17 00:00:00 2001 From: xyzroe Date: Tue, 10 Jun 2025 19:47:41 +0200 Subject: [PATCH 08/11] fix(readme): add missing newline at end of file ? --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d79ca44..c0c02032 100644 --- a/README.md +++ b/README.md @@ -413,4 +413,4 @@ or [GitLab examples](https://gitlab.com/UncleRus/esp-idf-lib/tree/master/example - [Zaltora](https://github.com/Zaltora): `ina3221` -- zeroday: `onewire` \ No newline at end of file +- zeroday: `onewire` From 08f0d21ee5a581a153aecf96ab755e1bbb05236f Mon Sep 17 00:00:00 2001 From: xyzroe Date: Tue, 10 Jun 2025 20:02:05 +0200 Subject: [PATCH 09/11] feat(readme): add QMI8658C driver information to the README --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c0c02032..0692c4a5 100644 --- a/README.md +++ b/README.md @@ -248,6 +248,7 @@ or [GitLab examples](https://gitlab.com/UncleRus/esp-idf-lib/tree/master/example | **hmc5883l** | Driver for 3-axis digital compass HMC5883L and HMC5983L | BSD-3-Clause | esp32, esp8266, esp32s2, esp32c3, esp32s3, esp32c2, esp32c6, esp32h2, esp32p4, esp32c5, esp32c61 | yes | | **lsm303** | Driver for LSM303 3-axis accelerometer and magnetometer sensor | BSD-3-Clause | esp32, esp8266, esp32s2, esp32c3, esp32s3, esp32c2, esp32c6, esp32h2, esp32p4, esp32c5, esp32c61 | yes | | **qmc5883l** | Driver for QMC5883L 3-axis magnetic sensor | BSD-3-Clause | esp32, esp8266, esp32s2, esp32c3, esp32s3, esp32c2, esp32c6, esp32h2, esp32p4, esp32c5, esp32c61 | yes | +| **qmi8658c** | Driver for QMI8658C 6-axis IMU sensor | BSD-3-Clause | esp32, esp32c3, esp8266, esp32s2, esp32c3, esp32c6 | yes | @@ -411,6 +412,8 @@ or [GitLab examples](https://gitlab.com/UncleRus/esp-idf-lib/tree/master/example - [Weslley Duarte](https://github.com/weslleymfd): `ads130e08` +- [xyzroe](https://github.com/xyzroe): `qmi8658c` + - [Zaltora](https://github.com/Zaltora): `ina3221` -- zeroday: `onewire` +- zeroday: `onewire` \ No newline at end of file From 35640b4c30b006d00c5868b885ebce7e471c4266 Mon Sep 17 00:00:00 2001 From: xyzroe Date: Tue, 10 Jun 2025 20:30:24 +0200 Subject: [PATCH 10/11] chore: add copyright notice and license information to QMI8658C driver files --- components/qmi8658c/qmi8658c.c | 30 +++++++++++++++++++++++++++++- components/qmi8658c/qmi8658c.h | 30 +++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/components/qmi8658c/qmi8658c.c b/components/qmi8658c/qmi8658c.c index 1daa7031..c83282a0 100644 --- a/components/qmi8658c/qmi8658c.c +++ b/components/qmi8658c/qmi8658c.c @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2024 xyzroe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /** * @file qmi8658c.c * @brief QMI8658C sensor driver @@ -7,7 +36,6 @@ * Datasheet: https://qstcorp.com/upload/pdf/202202/QMI8658C%20datasheet%20rev%200.9.pdf * * Copyright (c) 2024 xyzroe - * Licensed as described in the file LICENSE */ #include diff --git a/components/qmi8658c/qmi8658c.h b/components/qmi8658c/qmi8658c.h index 4abc3ec1..f3035e98 100644 --- a/components/qmi8658c/qmi8658c.h +++ b/components/qmi8658c/qmi8658c.h @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2024 xyzroe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /** * @file qmi8658c.h * @brief Header file for QMI8658C sensor driver @@ -7,7 +36,6 @@ * Datasheet: https://qstcorp.com/upload/pdf/202202/QMI8658C%20datasheet%20rev%200.9.pdf * * Copyright (c) 2024 xyzroe - * Licensed as described in the file LICENSE */ #ifndef __QMI8658C_H__ From fd5897c90bdccf89a1ced57699a9ce035086364c Mon Sep 17 00:00:00 2001 From: xyzroe Date: Fri, 11 Jul 2025 12:44:35 +0200 Subject: [PATCH 11/11] fix(qmi8658c): remove duplicate entry for esp32c3 in targets list --- components/qmi8658c/.eil.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/components/qmi8658c/.eil.yml b/components/qmi8658c/.eil.yml index cc168daf..2cb0c3f0 100644 --- a/components/qmi8658c/.eil.yml +++ b/components/qmi8658c/.eil.yml @@ -14,7 +14,6 @@ targets: - esp32c3 - esp8266 - esp32s2 - - esp32c3 - esp32c6 license: BSD-3 copyrights: