|
|
@@ -16,12 +16,16 @@ static const char *TAG = "guguji_sensors";
|
|
|
#define QMI_REG_CTRL5 0x06
|
|
|
#define QMI_REG_CTRL7 0x08
|
|
|
#define QMI_REG_DATA_START 0x35
|
|
|
+#define QMI_EXPECTED_WHO_AM_I 0x05
|
|
|
|
|
|
#define QMC_REG_CHIP_ID 0x00
|
|
|
#define QMC_REG_DATA_START 0x01
|
|
|
#define QMC_REG_STATUS 0x09
|
|
|
#define QMC_REG_CTRL1 0x0A
|
|
|
#define QMC_REG_CTRL2 0x0B
|
|
|
+#define QMC_EXPECTED_CHIP_ID 0x90
|
|
|
+
|
|
|
+#define I2C_XFER_TIMEOUT_MS 50
|
|
|
|
|
|
static bool g_qmi_ok = false;
|
|
|
static bool g_qmc_ok = false;
|
|
|
@@ -32,12 +36,12 @@ static i2c_master_dev_handle_t g_qmc_device = NULL;
|
|
|
static esp_err_t i2c_write_u8(i2c_master_dev_handle_t device, uint8_t reg, uint8_t value)
|
|
|
{
|
|
|
uint8_t payload[2] = {reg, value};
|
|
|
- return i2c_master_transmit(device, payload, sizeof(payload), 50);
|
|
|
+ return i2c_master_transmit(device, payload, sizeof(payload), I2C_XFER_TIMEOUT_MS);
|
|
|
}
|
|
|
|
|
|
static esp_err_t i2c_read(i2c_master_dev_handle_t device, uint8_t reg, uint8_t *data, size_t length)
|
|
|
{
|
|
|
- return i2c_master_transmit_receive(device, ®, 1, data, length, 50);
|
|
|
+ return i2c_master_transmit_receive(device, ®, 1, data, length, I2C_XFER_TIMEOUT_MS);
|
|
|
}
|
|
|
|
|
|
static int16_t le_i16(const uint8_t *data)
|
|
|
@@ -45,65 +49,183 @@ static int16_t le_i16(const uint8_t *data)
|
|
|
return (int16_t)((uint16_t)data[0] | ((uint16_t)data[1] << 8));
|
|
|
}
|
|
|
|
|
|
-esp_err_t guguji_sensors_init(void)
|
|
|
+static bool address_already_tried(const uint8_t *addresses, size_t current_index, uint8_t address)
|
|
|
{
|
|
|
- i2c_master_bus_config_t bus_config = {
|
|
|
- .i2c_port = GUGUJI_I2C_PORT,
|
|
|
- .sda_io_num = GUGUJI_I2C_SDA_GPIO,
|
|
|
- .scl_io_num = GUGUJI_I2C_SCL_GPIO,
|
|
|
- .clk_source = I2C_CLK_SRC_DEFAULT,
|
|
|
- .glitch_ignore_cnt = 7,
|
|
|
- .flags.enable_internal_pullup = true,
|
|
|
- };
|
|
|
- ESP_RETURN_ON_ERROR(i2c_new_master_bus(&bus_config, &g_i2c_bus), TAG, "创建 I2C master bus 失败");
|
|
|
+ for (size_t i = 0; i < current_index; ++i) {
|
|
|
+ if (addresses[i] == address) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
|
|
|
- i2c_device_config_t qmi_config = {
|
|
|
- .dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
|
|
- .device_address = GUGUJI_QMI8658A_ADDR,
|
|
|
- .scl_speed_hz = GUGUJI_I2C_FREQ_HZ,
|
|
|
- };
|
|
|
- ESP_RETURN_ON_ERROR(
|
|
|
- i2c_master_bus_add_device(g_i2c_bus, &qmi_config, &g_qmi_device),
|
|
|
+static void log_i2c_bus_scan(void)
|
|
|
+{
|
|
|
+ int found_count = 0;
|
|
|
+ ESP_LOGI(
|
|
|
TAG,
|
|
|
- "添加 QMI8658A I2C 设备失败");
|
|
|
+ "I2C 配置: port=%d SDA=GPIO%d SCL=GPIO%d freq=%dHz",
|
|
|
+ (int)GUGUJI_I2C_PORT,
|
|
|
+ (int)GUGUJI_I2C_SDA_GPIO,
|
|
|
+ (int)GUGUJI_I2C_SCL_GPIO,
|
|
|
+ GUGUJI_I2C_FREQ_HZ);
|
|
|
|
|
|
- i2c_device_config_t qmc_config = {
|
|
|
+ // QMC6309 使用 0x7C 这个较高的 7-bit 地址,所以扫描范围包含到 0x7E。
|
|
|
+ for (uint8_t address = 0x03; address <= 0x7E; ++address) {
|
|
|
+ if (i2c_master_probe(g_i2c_bus, address, 20) == ESP_OK) {
|
|
|
+ ESP_LOGI(TAG, "I2C 扫描发现设备: 0x%02X", address);
|
|
|
+ ++found_count;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (found_count == 0) {
|
|
|
+ ESP_LOGW(TAG, "I2C 扫描未发现设备,请检查 SDA/SCL、3.3V、GND 和上拉电阻");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static esp_err_t add_i2c_device(uint8_t address, i2c_master_dev_handle_t *device)
|
|
|
+{
|
|
|
+ i2c_device_config_t config = {
|
|
|
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
|
|
- .device_address = GUGUJI_QMC6309_ADDR,
|
|
|
+ .device_address = address,
|
|
|
.scl_speed_hz = GUGUJI_I2C_FREQ_HZ,
|
|
|
};
|
|
|
- ESP_RETURN_ON_ERROR(
|
|
|
- i2c_master_bus_add_device(g_i2c_bus, &qmc_config, &g_qmc_device),
|
|
|
- TAG,
|
|
|
- "添加 QMC6309 I2C 设备失败");
|
|
|
+ return i2c_master_bus_add_device(g_i2c_bus, &config, device);
|
|
|
+}
|
|
|
+
|
|
|
+static bool try_init_qmi8658a(uint8_t address)
|
|
|
+{
|
|
|
+ i2c_master_dev_handle_t device = NULL;
|
|
|
+ esp_err_t err = add_i2c_device(address, &device);
|
|
|
+ if (err != ESP_OK) {
|
|
|
+ ESP_LOGW(TAG, "添加 QMI8658A 候选地址 0x%02X 失败: %s", address, esp_err_to_name(err));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
uint8_t who_am_i = 0;
|
|
|
- if (i2c_read(g_qmi_device, QMI_REG_WHO_AM_I, &who_am_i, 1) == ESP_OK && who_am_i == 0x05) {
|
|
|
- // CTRL1: 开启地址自增并使用 little-endian,方便一次读完 AX~GZ。
|
|
|
- i2c_write_u8(g_qmi_device, QMI_REG_CTRL1, 0x40);
|
|
|
- // CTRL2: 加速度 ±8g,ODR 约 112Hz;CTRL3: 陀螺仪 ±512dps,ODR 约 112Hz。
|
|
|
- i2c_write_u8(g_qmi_device, QMI_REG_CTRL2, 0x26);
|
|
|
- i2c_write_u8(g_qmi_device, QMI_REG_CTRL3, 0x56);
|
|
|
+ err = i2c_read(device, QMI_REG_WHO_AM_I, &who_am_i, 1);
|
|
|
+ if (err != ESP_OK || who_am_i != QMI_EXPECTED_WHO_AM_I) {
|
|
|
+ if (err == ESP_OK) {
|
|
|
+ ESP_LOGW(TAG, "QMI8658A 地址 0x%02X ID 不匹配: who_am_i=0x%02X", address, who_am_i);
|
|
|
+ } else {
|
|
|
+ ESP_LOGW(TAG, "QMI8658A 地址 0x%02X 读取 ID 失败: %s", address, esp_err_to_name(err));
|
|
|
+ }
|
|
|
+ i2c_master_bus_rm_device(device);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // CTRL1: 开启地址自增并使用 little-endian,方便一次读完 AX~GZ。
|
|
|
+ err = i2c_write_u8(device, QMI_REG_CTRL1, 0x40);
|
|
|
+ if (err == ESP_OK) {
|
|
|
+ // CTRL2: 加速度 ±8g,ODR 约 112Hz。
|
|
|
+ err = i2c_write_u8(device, QMI_REG_CTRL2, 0x26);
|
|
|
+ }
|
|
|
+ if (err == ESP_OK) {
|
|
|
+ // CTRL3: 陀螺仪 ±512dps,ODR 约 112Hz。
|
|
|
+ err = i2c_write_u8(device, QMI_REG_CTRL3, 0x56);
|
|
|
+ }
|
|
|
+ if (err == ESP_OK) {
|
|
|
// 打开加速度和陀螺仪低通滤波。
|
|
|
- i2c_write_u8(g_qmi_device, QMI_REG_CTRL5, 0x11);
|
|
|
+ err = i2c_write_u8(device, QMI_REG_CTRL5, 0x11);
|
|
|
+ }
|
|
|
+ if (err == ESP_OK) {
|
|
|
// 使能 accel + gyro。
|
|
|
- i2c_write_u8(g_qmi_device, QMI_REG_CTRL7, 0x03);
|
|
|
- g_qmi_ok = true;
|
|
|
- ESP_LOGI(TAG, "QMI8658A 初始化成功");
|
|
|
- } else {
|
|
|
- ESP_LOGW(TAG, "QMI8658A 初始化失败,who_am_i=0x%02X", who_am_i);
|
|
|
+ err = i2c_write_u8(device, QMI_REG_CTRL7, 0x03);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (err != ESP_OK) {
|
|
|
+ ESP_LOGW(TAG, "QMI8658A 地址 0x%02X 配置失败: %s", address, esp_err_to_name(err));
|
|
|
+ i2c_master_bus_rm_device(device);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_qmi_device = device;
|
|
|
+ g_qmi_ok = true;
|
|
|
+ ESP_LOGI(TAG, "QMI8658A 初始化成功: address=0x%02X who_am_i=0x%02X", address, who_am_i);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+static bool try_init_qmc6309(uint8_t address)
|
|
|
+{
|
|
|
+ i2c_master_dev_handle_t device = NULL;
|
|
|
+ esp_err_t err = add_i2c_device(address, &device);
|
|
|
+ if (err != ESP_OK) {
|
|
|
+ ESP_LOGW(TAG, "添加 QMC6309 候选地址 0x%02X 失败: %s", address, esp_err_to_name(err));
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
uint8_t chip_id = 0;
|
|
|
- if (i2c_read(g_qmc_device, QMC_REG_CHIP_ID, &chip_id, 1) == ESP_OK && chip_id == 0x90) {
|
|
|
- // 数据手册推荐的连续测量配置:32Gauss 量程、Set/Reset 开、OSR1/OSR2=8。
|
|
|
- i2c_write_u8(g_qmc_device, QMC_REG_CTRL2, 0x00);
|
|
|
- i2c_write_u8(g_qmc_device, QMC_REG_CTRL1, 0x63);
|
|
|
- g_qmc_ok = true;
|
|
|
- ESP_LOGI(TAG, "QMC6309 初始化成功");
|
|
|
- } else {
|
|
|
- ESP_LOGW(TAG, "QMC6309 初始化失败,chip_id=0x%02X", chip_id);
|
|
|
+ err = i2c_read(device, QMC_REG_CHIP_ID, &chip_id, 1);
|
|
|
+ if (err != ESP_OK || chip_id != QMC_EXPECTED_CHIP_ID) {
|
|
|
+ if (err == ESP_OK) {
|
|
|
+ ESP_LOGW(TAG, "QMC6309 地址 0x%02X ID 不匹配: chip_id=0x%02X", address, chip_id);
|
|
|
+ } else {
|
|
|
+ ESP_LOGW(TAG, "QMC6309 地址 0x%02X 读取 ID 失败: %s", address, esp_err_to_name(err));
|
|
|
+ }
|
|
|
+ i2c_master_bus_rm_device(device);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 数据手册推荐的连续测量配置:32Gauss 量程、Set/Reset 开、OSR1/OSR2=8。
|
|
|
+ err = i2c_write_u8(device, QMC_REG_CTRL2, 0x00);
|
|
|
+ if (err == ESP_OK) {
|
|
|
+ err = i2c_write_u8(device, QMC_REG_CTRL1, 0x63);
|
|
|
}
|
|
|
+ if (err != ESP_OK) {
|
|
|
+ ESP_LOGW(TAG, "QMC6309 地址 0x%02X 配置失败: %s", address, esp_err_to_name(err));
|
|
|
+ i2c_master_bus_rm_device(device);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_qmc_device = device;
|
|
|
+ g_qmc_ok = true;
|
|
|
+ ESP_LOGI(TAG, "QMC6309 初始化成功: address=0x%02X chip_id=0x%02X", address, chip_id);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+static void init_qmi8658a(void)
|
|
|
+{
|
|
|
+ const uint8_t addresses[] = {GUGUJI_QMI8658A_ADDR, 0x6A, 0x6B};
|
|
|
+ for (size_t i = 0; i < sizeof(addresses) / sizeof(addresses[0]); ++i) {
|
|
|
+ if (address_already_tried(addresses, i, addresses[i])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (try_init_qmi8658a(addresses[i])) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ESP_LOGW(TAG, "QMI8658A 初始化失败,请检查地址、供电、接线和芯片型号");
|
|
|
+}
|
|
|
+
|
|
|
+static void init_qmc6309(void)
|
|
|
+{
|
|
|
+ const uint8_t addresses[] = {GUGUJI_QMC6309_ADDR, 0x7C, 0x3E};
|
|
|
+ for (size_t i = 0; i < sizeof(addresses) / sizeof(addresses[0]); ++i) {
|
|
|
+ if (address_already_tried(addresses, i, addresses[i])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (try_init_qmc6309(addresses[i])) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ESP_LOGW(TAG, "QMC6309 初始化失败,请检查地址、供电、接线和芯片型号");
|
|
|
+}
|
|
|
+
|
|
|
+esp_err_t guguji_sensors_init(void)
|
|
|
+{
|
|
|
+ i2c_master_bus_config_t bus_config = {
|
|
|
+ .i2c_port = GUGUJI_I2C_PORT,
|
|
|
+ .sda_io_num = GUGUJI_I2C_SDA_GPIO,
|
|
|
+ .scl_io_num = GUGUJI_I2C_SCL_GPIO,
|
|
|
+ .clk_source = I2C_CLK_SRC_DEFAULT,
|
|
|
+ .glitch_ignore_cnt = 7,
|
|
|
+ .flags.enable_internal_pullup = true,
|
|
|
+ };
|
|
|
+ ESP_RETURN_ON_ERROR(i2c_new_master_bus(&bus_config, &g_i2c_bus), TAG, "创建 I2C master bus 失败");
|
|
|
+
|
|
|
+ log_i2c_bus_scan();
|
|
|
+ init_qmi8658a();
|
|
|
+ init_qmc6309();
|
|
|
|
|
|
return ESP_OK;
|
|
|
}
|