#include "qmi8658a.h" #include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #define TAG "QMI8658A" QMI8658A::QMI8658A(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr), state_(QMI8658A_STATE_UNINITIALIZED), last_error_(QMI8658A_OK), acc_scale_(1.0f), gyro_scale_(1.0f), is_calibrating_(false), calibration_start_time_(0), calibration_duration_(0), calibration_sample_count_(0), buffer_task_handle_(nullptr), buffer_enabled_(false), buffer_interval_ms_(0), interrupt_pin_(GPIO_NUM_NC), interrupt_type_(QMI8658A_INT_DISABLE), interrupt_enabled_(false), fifo_enabled_(false) { // 默认配置 - 修正ODR设置以匹配实际寄存器值 config_.mode = QMI8658A_MODE_DUAL; config_.acc_range = QMI8658A_ACC_RANGE_4G; // 匹配CTRL2寄存器值0x16 config_.gyro_range = QMI8658A_GYRO_RANGE_512DPS; // 匹配CTRL3寄存器值0x56 config_.acc_odr = QMI8658A_ODR_125HZ; // 匹配实际寄存器值0x06 config_.gyro_odr = QMI8658A_ODR_125HZ; // 匹配实际寄存器值0x06 // 初始化缓冲区结构 memset(&data_buffer_, 0, sizeof(data_buffer_)); data_buffer_.mutex = nullptr; // 初始化校准数据 memset(&calibration_, 0, sizeof(calibration_)); memset(calibration_acc_sum_, 0, sizeof(calibration_acc_sum_)); memset(calibration_gyro_sum_, 0, sizeof(calibration_gyro_sum_)); // 初始化FIFO配置 memset(&fifo_config_, 0, sizeof(fifo_config_)); } qmi8658a_error_t QMI8658A::Initialize(const qmi8658a_config_t* config) { ESP_LOGI(TAG, "Initializing QMI8658A sensor..."); state_ = QMI8658A_STATE_INITIALIZING; // 执行自检 qmi8658a_error_t result = PerformSelfTest(); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Self-test failed during initialization"); state_ = QMI8658A_STATE_ERROR; return result; } // 软件复位 result = SoftReset(); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Software reset failed"); state_ = QMI8658A_STATE_ERROR; return result; } // 保存配置 if (config) { config_ = *config; } // 计算比例因子 CalculateScaleFactors(); // 配置加速度计 - 使用更保守的设置 result = SetAccelConfig(QMI8658A_ACC_RANGE_4G, QMI8658A_ODR_125HZ); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to configure accelerometer"); state_ = QMI8658A_STATE_ERROR; return result; } // 配置陀螺仪 - 使用更保守的设置 result = SetGyroConfig(QMI8658A_GYRO_RANGE_256DPS, QMI8658A_ODR_125HZ); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to configure gyroscope"); state_ = QMI8658A_STATE_ERROR; return result; } // 配置CTRL1 - 使能数据就绪/中断相关功能以确保STATUS0有效 result = WriteRegWithVerification(QMI8658A_CTRL1, 0x60); if (result != QMI8658A_OK) { ESP_LOGW(TAG, "Failed to configure CTRL1 register"); } else { VerifyRegisterValue(QMI8658A_CTRL1, 0x60, "CTRL1"); } uint8_t mode_val = config_.mode; result = SetMode(static_cast(mode_val)); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to set mode"); state_ = QMI8658A_STATE_ERROR; return result; } // 添加额外的寄存器配置 // 配置CTRL5寄存器 - 设置加速度计和陀螺仪的带宽滤波 result = WriteRegWithVerification(QMI8658A_CTRL5, 0x35); if (result != QMI8658A_OK) { ESP_LOGW(TAG, "Failed to configure CTRL5 register"); } else { VerifyRegisterValue(QMI8658A_CTRL5, 0x35, "CTRL5"); } // 配置CTRL6寄存器 - 设置陀螺仪的LPF result = WriteRegWithVerification(QMI8658A_CTRL6, 0x00); if (result != QMI8658A_OK) { ESP_LOGW(TAG, "Failed to configure CTRL6 register"); } // 等待传感器稳定 vTaskDelay(pdMS_TO_TICKS(100)); // 增加等待时间到100ms // 验证关键寄存器配置 uint8_t expected_ctrl2 = (config_.acc_range << 4) | config_.acc_odr; result = VerifyRegisterValue(QMI8658A_CTRL2, expected_ctrl2, "CTRL2"); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "CTRL2 verification failed"); state_ = QMI8658A_STATE_ERROR; return result; } uint8_t expected_ctrl3 = (config_.gyro_range << 4) | config_.gyro_odr; result = VerifyRegisterValue(QMI8658A_CTRL3, expected_ctrl3, "CTRL3 (Gyro Config)"); if (result != QMI8658A_OK) { state_ = QMI8658A_STATE_ERROR; return result; } uint8_t expected_ctrl7 = (mode_val == QMI8658A_MODE_DISABLE) ? 0x00 : (uint8_t)(0x80 | mode_val); result = VerifyRegisterValue(QMI8658A_CTRL7, expected_ctrl7, "CTRL7 (Mode)"); if (result != QMI8658A_OK) { state_ = QMI8658A_STATE_ERROR; return result; } // 诊断寄存器状态 ESP_LOGI(TAG, "=== QMI8658A Register Diagnostics ==="); uint8_t ctrl1 = ReadReg(QMI8658A_CTRL1); uint8_t ctrl2 = ReadReg(QMI8658A_CTRL2); uint8_t ctrl3 = ReadReg(QMI8658A_CTRL3); uint8_t ctrl5 = ReadReg(QMI8658A_CTRL5); uint8_t ctrl6 = ReadReg(QMI8658A_CTRL6); uint8_t ctrl7 = ReadReg(QMI8658A_CTRL7); uint8_t status0 = ReadReg(QMI8658A_STATUS0); uint8_t status1 = ReadReg(QMI8658A_STATUS1); ESP_LOGI(TAG, "CTRL1: 0x%02X, CTRL2: 0x%02X, CTRL3: 0x%02X, CTRL5: 0x%02X, CTRL6: 0x%02X, CTRL7: 0x%02X", ctrl1, ctrl2, ctrl3, ctrl5, ctrl6, ctrl7); ESP_LOGI(TAG, "STATUS0: 0x%02X, STATUS1: 0x%02X", status0, status1); ESP_LOGI(TAG, "====================================="); // 等待数据就绪 - 只进行一次等待 if (config_.mode != QMI8658A_MODE_DISABLE) { ESP_LOGI(TAG, "Waiting for sensor data to be ready..."); uint32_t wait_count = 0; const uint32_t max_wait = 100; // 最多等待1秒 while (wait_count < max_wait) { uint8_t status = ReadReg(QMI8658A_STATUS0); if (status & 0x03) { // 检查加速度计或陀螺仪数据就绪 ESP_LOGI(TAG, "Data ready after %lu ms", wait_count * 10); break; } vTaskDelay(pdMS_TO_TICKS(10)); wait_count++; } if (wait_count >= max_wait) { ESP_LOGW(TAG, "Data ready timeout, but initialization completed"); } } state_ = QMI8658A_STATE_READY; UpdateScaleFactors(); ESP_LOGI(TAG, "QMI8658A initialization completed successfully"); DumpRegisters(); return QMI8658A_OK; } uint8_t QMI8658A::GetChipId() { uint8_t chip_id = ReadReg(QMI8658A_WHO_AM_I); if (chip_id == 0xFF) { ESP_LOGE(TAG, "Failed to read chip ID register, I2C communication error"); return 0xFF; } return chip_id; } uint8_t QMI8658A::GetRevisionId() { return ReadReg(QMI8658A_REVISION_ID); } // 静态连接检测方法(用于生产测试) bool QMI8658A::CheckConnection(i2c_master_bus_handle_t i2c_bus, uint8_t* detected_address) { // 可能的QMI8658A I2C地址 uint8_t possible_addresses[] = {0x6A, 0x6B}; uint8_t num_addresses = sizeof(possible_addresses) / sizeof(possible_addresses[0]); for (uint8_t i = 0; i < num_addresses; i++) { uint8_t addr = possible_addresses[i]; // 创建临时I2C设备句柄进行测试 i2c_master_dev_handle_t dev_handle; i2c_device_config_t dev_cfg = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = addr, .scl_speed_hz = 400000, // 400kHz }; esp_err_t ret = i2c_master_bus_add_device(i2c_bus, &dev_cfg, &dev_handle); if (ret != ESP_OK) { continue; // 尝试下一个地址 } // 尝试读取WHO_AM_I寄存器 uint8_t reg_addr = QMI8658A_WHO_AM_I; uint8_t chip_id = 0; ret = i2c_master_transmit_receive(dev_handle, ®_addr, 1, &chip_id, 1, 1000); // 清理设备句柄 i2c_master_bus_rm_device(dev_handle); if (ret == ESP_OK && chip_id == QMI8658A_CHIP_ID) { // 找到有效的QMI8658A设备 if (detected_address != nullptr) { *detected_address = addr; } return true; } } return false; // 未找到有效设备 } qmi8658a_error_t QMI8658A::SoftReset() { ESP_LOGI(TAG, "Performing soft reset..."); qmi8658a_error_t result = WriteRegWithVerification(QMI8658A_RESET, 0xB0); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to perform soft reset"); return result; } // 等待复位完成 - 大幅增加等待时间以确保传感器完全稳定 vTaskDelay(pdMS_TO_TICKS(200)); // 增加到200ms等待时间 // 验证复位是否成功 - 检查芯片ID uint8_t chip_id = GetChipId(); if (chip_id != QMI8658A_CHIP_ID) { ESP_LOGE(TAG, "Soft reset verification failed: chip ID = 0x%02X", chip_id); return SetError(QMI8658A_ERROR_INIT_FAILED); } ESP_LOGI(TAG, "Soft reset completed and verified successfully"); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::SetMode(qmi8658a_mode_t mode) { ESP_LOGI(TAG, "Setting mode: %d", mode); uint8_t value = 0x00; switch (mode) { case QMI8658A_MODE_DISABLE: value = 0x00; break; case QMI8658A_MODE_ACC_ONLY: value = 0x81; break; case QMI8658A_MODE_GYRO_ONLY: value = 0x82; break; case QMI8658A_MODE_DUAL: value = 0x83; break; } qmi8658a_error_t result = WriteRegWithVerification(QMI8658A_CTRL7, value, 3); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to set mode: %d", mode); return result; } // 更新配置 config_.mode = mode; ESP_LOGI(TAG, "Mode set successfully: CTRL7=0x%02X", value); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::SetAccelConfig(qmi8658a_acc_range_t range, qmi8658a_odr_t odr) { ESP_LOGI(TAG, "Setting accelerometer config: range=%d, odr=%d", range, odr); uint8_t ctrl2_val = (range << 4) | odr; // 使用带验证的写入函数,最多重试3次 qmi8658a_error_t result = WriteRegWithVerification(QMI8658A_CTRL2, ctrl2_val, 3); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to set accelerometer config: range=%d, odr=%d", range, odr); return result; } // 更新配置 config_.acc_range = range; config_.acc_odr = odr; UpdateScaleFactors(); ESP_LOGI(TAG, "Accelerometer config set successfully: CTRL2=0x%02X", ctrl2_val); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::SetGyroConfig(qmi8658a_gyro_range_t range, qmi8658a_odr_t odr) { ESP_LOGI(TAG, "Setting gyroscope config: range=%d, odr=%d", range, odr); uint8_t ctrl3_val = (range << 4) | odr; // 使用带验证的写入函数,最多重试3次 qmi8658a_error_t result = WriteRegWithVerification(QMI8658A_CTRL3, ctrl3_val, 3); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to set gyroscope config: range=%d, odr=%d", range, odr); return result; } // 更新配置 config_.gyro_range = range; config_.gyro_odr = odr; UpdateScaleFactors(); ESP_LOGI(TAG, "Gyroscope config set successfully: CTRL3=0x%02X", ctrl3_val); return QMI8658A_OK; } void QMI8658A::CalculateScaleFactors() { // 计算加速度计比例因子 (g) switch (config_.acc_range) { case QMI8658A_ACC_RANGE_2G: acc_scale_ = 2.0f / 32768.0f; break; case QMI8658A_ACC_RANGE_4G: acc_scale_ = 4.0f / 32768.0f; break; case QMI8658A_ACC_RANGE_8G: acc_scale_ = 8.0f / 32768.0f; break; case QMI8658A_ACC_RANGE_16G: acc_scale_ = 16.0f / 32768.0f; break; } // 计算陀螺仪比例因子 (dps) switch (config_.gyro_range) { case QMI8658A_GYRO_RANGE_16DPS: gyro_scale_ = 16.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_32DPS: gyro_scale_ = 32.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_64DPS: gyro_scale_ = 64.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_128DPS: gyro_scale_ = 128.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_256DPS: gyro_scale_ = 256.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_512DPS: gyro_scale_ = 512.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_1024DPS: gyro_scale_ = 1024.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_2048DPS: gyro_scale_ = 2048.0f / 32768.0f; break; } ESP_LOGI(TAG, "Scale factors - Acc: %.6f, Gyro: %.6f", acc_scale_, gyro_scale_); } int16_t QMI8658A::ReadInt16(uint8_t reg_low) { uint8_t data[2]; ReadRegs(reg_low, data, 2); return (int16_t)((data[1] << 8) | data[0]); } qmi8658a_error_t QMI8658A::ReadAccelData(float* acc_x, float* acc_y, float* acc_z) { if (!acc_x || !acc_y || !acc_z) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } if (state_ != QMI8658A_STATE_READY) { return SetError(QMI8658A_ERROR_DATA_NOT_READY); } uint8_t buf[6]; ReadRegs(QMI8658A_AX_L, buf, 6); int16_t raw_x = (int16_t)((buf[1] << 8) | buf[0]); int16_t raw_y = (int16_t)((buf[3] << 8) | buf[2]); int16_t raw_z = (int16_t)((buf[5] << 8) | buf[4]); // 应用缩放和校准 float ax = raw_x * acc_scale_; float ay = raw_y * acc_scale_; float az = raw_z * acc_scale_; if (calibration_.is_calibrated) { float bx = calibration_.acc_bias[0]; float by = calibration_.acc_bias[1]; float bz = calibration_.acc_bias[2]; bool valid_bias = fabs(bx) < 0.5f && fabs(by) < 0.5f && fabs(bz) < 0.5f; if (valid_bias) { ax -= bx; ay -= by; az -= bz; } } *acc_x = ax; *acc_y = ay; *acc_z = az; // 数据合理性检查 - 加速度值不应超过设置的量程 float max_acc = 4.0f; // 假设使用4G量程 if (fabs(*acc_x) > max_acc * 1.1f || fabs(*acc_y) > max_acc * 1.1f || fabs(*acc_z) > max_acc * 1.1f) { ESP_LOGE(TAG, "Invalid accelerometer readings: [%.3f, %.3f, %.3f] g", *acc_x, *acc_y, *acc_z); return SetError(QMI8658A_ERROR_DATA_NOT_READY); } return QMI8658A_OK; } qmi8658a_error_t QMI8658A::ReadGyroData(float* gyro_x, float* gyro_y, float* gyro_z) { if (!gyro_x || !gyro_y || !gyro_z) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } if (state_ != QMI8658A_STATE_READY) { return SetError(QMI8658A_ERROR_DATA_NOT_READY); } uint8_t buf[6]; ReadRegs(QMI8658A_GX_L, buf, 6); int16_t raw_x = (int16_t)((buf[1] << 8) | buf[0]); int16_t raw_y = (int16_t)((buf[3] << 8) | buf[2]); int16_t raw_z = (int16_t)((buf[5] << 8) | buf[4]); float gx = raw_x * gyro_scale_; float gy = raw_y * gyro_scale_; float gz = raw_z * gyro_scale_; if (calibration_.is_calibrated) { float bx = calibration_.gyro_bias[0]; float by = calibration_.gyro_bias[1]; float bz = calibration_.gyro_bias[2]; bool valid_bias = fabs(bx) < 50.0f && fabs(by) < 50.0f && fabs(bz) < 50.0f; if (valid_bias) { gx -= bx; gy -= by; gz -= bz; } } *gyro_x = gx; *gyro_y = gy; *gyro_z = gz; float max_gyro = 400.0f; if (fabs(*gyro_x) > max_gyro || fabs(*gyro_y) > max_gyro || fabs(*gyro_z) > max_gyro) { ESP_LOGW(TAG, "Gyro readings out of expected range: [%.3f, %.3f, %.3f] dps", *gyro_x, *gyro_y, *gyro_z); // 不再直接返回错误,而是继续处理但记录警告 } return QMI8658A_OK; } qmi8658a_error_t QMI8658A::ReadTemperature(float* temperature) { if (!temperature) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } if (state_ != QMI8658A_STATE_READY) { return SetError(QMI8658A_ERROR_DATA_NOT_READY); } uint8_t tl = ReadReg(QMI8658A_TEMP_L); uint8_t th = ReadReg(QMI8658A_TEMP_H); *temperature = (float)th + ((float)tl / 256.0f); if (*temperature < -40.0f || *temperature > 125.0f) { ESP_LOGW(TAG, "Temperature reading out of expected range: %.2f°C", *temperature); *temperature = 25.0f; } return QMI8658A_OK; } qmi8658a_error_t QMI8658A::InitializeBuffer() { // 初始化缓冲区 memset(&data_buffer_, 0, sizeof(data_buffer_)); data_buffer_.mutex = xSemaphoreCreateMutex(); if (data_buffer_.mutex == NULL) { return SetError(QMI8658A_ERROR_INIT_FAILED); } buffer_enabled_ = false; buffer_task_handle_ = NULL; ESP_LOGI(TAG, "Data buffer initialized"); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::StartBufferedReading(uint32_t interval_ms) { if (state_ != QMI8658A_STATE_READY) { return SetError(QMI8658A_ERROR_DATA_NOT_READY); } if (data_buffer_.mutex == NULL) { qmi8658a_error_t r = InitializeBuffer(); if (r != QMI8658A_OK) { return r; } } if (buffer_enabled_) { ESP_LOGW(TAG, "Buffered reading already started"); return QMI8658A_OK; } buffer_interval_ms_ = interval_ms; buffer_enabled_ = true; // 创建缓冲任务 BaseType_t result = xTaskCreate( BufferTask, "qmi8658a_buffer", 4096, this, 5, &buffer_task_handle_ ); if (result != pdPASS) { buffer_enabled_ = false; return SetError(QMI8658A_ERROR_INIT_FAILED); } ESP_LOGI(TAG, "Started buffered reading with %" PRIu32 " ms interval", interval_ms); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::StopBufferedReading() { if (!buffer_enabled_) { return QMI8658A_OK; } buffer_enabled_ = false; if (buffer_task_handle_ != NULL) { vTaskDelete(buffer_task_handle_); buffer_task_handle_ = NULL; } ESP_LOGI(TAG, "Stopped buffered reading"); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::GetBufferedData(qmi8658a_data_t* data, uint32_t max_count, uint32_t* actual_count) { if (!data || !actual_count) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } *actual_count = 0; if (xSemaphoreTake(data_buffer_.mutex, pdMS_TO_TICKS(100)) != pdTRUE) { return SetError(QMI8658A_ERROR_TIMEOUT); } uint32_t count = 0; while (count < max_count && data_buffer_.count > 0) { data[count] = data_buffer_.data[data_buffer_.tail]; data_buffer_.tail = (data_buffer_.tail + 1) % QMI8658A_BUFFER_SIZE; data_buffer_.count--; count++; } *actual_count = count; xSemaphoreGive(data_buffer_.mutex); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::ClearBuffer() { if (xSemaphoreTake(data_buffer_.mutex, pdMS_TO_TICKS(100)) != pdTRUE) { return SetError(QMI8658A_ERROR_TIMEOUT); } data_buffer_.head = 0; data_buffer_.tail = 0; data_buffer_.count = 0; data_buffer_.overflow = false; xSemaphoreGive(data_buffer_.mutex); ESP_LOGI(TAG, "Buffer cleared"); return QMI8658A_OK; } uint32_t QMI8658A::GetBufferCount() { if (xSemaphoreTake(data_buffer_.mutex, pdMS_TO_TICKS(10)) != pdTRUE) { return 0; } uint32_t count = data_buffer_.count; xSemaphoreGive(data_buffer_.mutex); return count; } bool QMI8658A::IsBufferOverflow() { if (xSemaphoreTake(data_buffer_.mutex, pdMS_TO_TICKS(10)) != pdTRUE) { return false; } bool overflow = data_buffer_.overflow; xSemaphoreGive(data_buffer_.mutex); return overflow; } qmi8658a_error_t QMI8658A::ConfigureInterrupt(qmi8658a_interrupt_t int_type, gpio_num_t pin) { interrupt_type_ = int_type; interrupt_pin_ = pin; if (int_type == QMI8658A_INT_DISABLE) { interrupt_enabled_ = false; return QMI8658A_OK; } // 配置GPIO中断 gpio_config_t io_conf = {}; io_conf.intr_type = GPIO_INTR_POSEDGE; io_conf.mode = GPIO_MODE_INPUT; io_conf.pin_bit_mask = (1ULL << pin); io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; io_conf.pull_up_en = GPIO_PULLUP_ENABLE; esp_err_t ret = gpio_config(&io_conf); if (ret != ESP_OK) { return SetError(QMI8658A_ERROR_INIT_FAILED); } // 安装中断服务 ret = gpio_install_isr_service(0); if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) { return SetError(QMI8658A_ERROR_INIT_FAILED); } // 添加中断处理程序 ret = gpio_isr_handler_add(pin, InterruptHandler, this); if (ret != ESP_OK) { return SetError(QMI8658A_ERROR_INIT_FAILED); } // 配置传感器中断 uint8_t int_config = 0; switch (int_type) { case QMI8658A_INT_DATA_READY: int_config = 0x01; break; case QMI8658A_INT_FIFO_WATERMARK: int_config = 0x02; break; case QMI8658A_INT_FIFO_FULL: int_config = 0x04; break; case QMI8658A_INT_MOTION_DETECT: int_config = 0x08; break; default: break; } WriteReg(0x56, int_config); // INT_EN寄存器 interrupt_enabled_ = true; ESP_LOGI(TAG, "Interrupt configured: type=%d, pin=%d", int_type, pin); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::EnableFIFO(const qmi8658a_fifo_config_t* fifo_config) { if (!fifo_config) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } fifo_config_ = *fifo_config; // 配置FIFO uint8_t fifo_ctrl = 0x40; // 启用FIFO if (fifo_config->watermark > 0 && fifo_config->watermark <= QMI8658A_FIFO_SIZE) { fifo_ctrl |= (fifo_config->watermark & 0x1F); } WriteReg(0x13, fifo_ctrl); // FIFO_CTRL寄存器 // 如果配置了中断,设置中断 if (fifo_config->interrupt_type != QMI8658A_INT_DISABLE) { qmi8658a_error_t result = ConfigureInterrupt(fifo_config->interrupt_type, fifo_config->interrupt_pin); if (result != QMI8658A_OK) { return result; } } fifo_enabled_ = true; ESP_LOGI(TAG, "FIFO enabled with watermark: %d", fifo_config->watermark); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::DisableFIFO() { WriteReg(0x13, 0x00); // 禁用FIFO fifo_enabled_ = false; ESP_LOGI(TAG, "FIFO disabled"); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::ReadFIFO(qmi8658a_data_t* data_array, uint8_t max_count, uint8_t* actual_count) { if (!data_array || !actual_count) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } *actual_count = 0; if (!fifo_enabled_) { return SetError(QMI8658A_ERROR_DATA_NOT_READY); } // 读取FIFO状态 uint8_t fifo_status = ReadReg(0x14); // FIFO_STATUS寄存器 uint8_t fifo_count = fifo_status & 0x1F; if (fifo_count == 0) { return QMI8658A_OK; } uint8_t read_count = (fifo_count < max_count) ? fifo_count : max_count; for (uint8_t i = 0; i < read_count; i++) { qmi8658a_error_t result = ReadSensorData(&data_array[i]); if (result != QMI8658A_OK) { return result; } } *actual_count = read_count; return QMI8658A_OK; } qmi8658a_error_t QMI8658A::AddToBuffer(const qmi8658a_data_t* data) { if (!data) { return QMI8658A_ERROR_INVALID_PARAM; } if (xSemaphoreTake(data_buffer_.mutex, pdMS_TO_TICKS(10)) != pdTRUE) { return QMI8658A_ERROR_TIMEOUT; } if (data_buffer_.count >= QMI8658A_BUFFER_SIZE) { // 缓冲区满,覆盖最旧的数据 data_buffer_.tail = (data_buffer_.tail + 1) % QMI8658A_BUFFER_SIZE; data_buffer_.overflow = true; } else { data_buffer_.count++; } data_buffer_.data[data_buffer_.head] = *data; data_buffer_.head = (data_buffer_.head + 1) % QMI8658A_BUFFER_SIZE; xSemaphoreGive(data_buffer_.mutex); return QMI8658A_OK; } void QMI8658A::BufferTask(void* parameter) { QMI8658A* sensor = static_cast(parameter); qmi8658a_data_t data; while (sensor->buffer_enabled_) { if (sensor->ReadSensorData(&data) == QMI8658A_OK) { sensor->AddToBuffer(&data); // 如果正在校准,添加到校准数据 if (sensor->is_calibrating_) { sensor->calibration_acc_sum_[0] += data.acc_x; sensor->calibration_acc_sum_[1] += data.acc_y; sensor->calibration_acc_sum_[2] += data.acc_z; sensor->calibration_gyro_sum_[0] += data.gyro_x; sensor->calibration_gyro_sum_[1] += data.gyro_y; sensor->calibration_gyro_sum_[2] += data.gyro_z; sensor->calibration_sample_count_++; } } vTaskDelay(pdMS_TO_TICKS(sensor->buffer_interval_ms_)); } vTaskDelete(NULL); } void IRAM_ATTR QMI8658A::InterruptHandler(void* arg) { QMI8658A* sensor = static_cast(arg); // 在中断中只做最小的处理 BaseType_t xHigherPriorityTaskWoken = pdFALSE; // 可以在这里设置一个标志或发送通知 // 实际的数据读取应该在任务中进行 // 使用sensor参数避免未使用变量警告 (void)sensor; (void)xHigherPriorityTaskWoken; } qmi8658a_error_t QMI8658A::ReadSensorData(qmi8658a_data_t* data) { if (!data) { ESP_LOGE(TAG, "Data pointer is null"); return SetError(QMI8658A_ERROR_INVALID_PARAM); } if (state_ != QMI8658A_STATE_READY) { ESP_LOGE(TAG, "Sensor not ready, current state: %d", state_); return SetError(QMI8658A_ERROR_DATA_NOT_READY); } // 增加重试机制 const int max_retries = 3; for (int retry = 0; retry < max_retries; retry++) { // 检查数据是否就绪 if (!IsDataReady()) { // 优化警告日志输出:降低级别并减少频率 static int data_not_ready_count = 0; static int last_log_time = 0; int current_time = esp_timer_get_time(); // 每10次警告或每1秒才输出一次日志,降低日志级别为DEBUG if (data_not_ready_count % 10 == 0 || (current_time - last_log_time) > 1000000) { ESP_LOGD(TAG, "Sensor data not ready (计数: %d), STATUS0: 0x%02X", data_not_ready_count, ReadReg(QMI8658A_STATUS0)); last_log_time = current_time; } data_not_ready_count++; // 添加小延迟后重试 if (retry < max_retries - 1) { vTaskDelay(pdMS_TO_TICKS(5)); continue; } return SetError(QMI8658A_ERROR_DATA_NOT_READY); } // 初始化数据结构 memset(data, 0, sizeof(qmi8658a_data_t)); data->timestamp = esp_timer_get_time(); data->valid = false; qmi8658a_error_t result; bool data_valid = true; // 读取加速度数据 if (config_.mode == QMI8658A_MODE_ACC_ONLY || config_.mode == QMI8658A_MODE_DUAL) { result = ReadAccelData(&data->acc_x, &data->acc_y, &data->acc_z); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to read accelerometer data, error: %d", result); data_valid = false; } else { static float prev_acc_x = 0, prev_acc_y = 0, prev_acc_z = 0; static bool acc_initialized = false; if (!acc_initialized) { prev_acc_x = data->acc_x; prev_acc_y = data->acc_y; prev_acc_z = data->acc_z; data->acc_x = prev_acc_x; data->acc_y = prev_acc_y; data->acc_z = prev_acc_z; acc_initialized = true; } else { const float alpha = 0.6f; float filtered_x = alpha * prev_acc_x + (1 - alpha) * data->acc_x; float filtered_y = alpha * prev_acc_y + (1 - alpha) * data->acc_y; float filtered_z = alpha * prev_acc_z + (1 - alpha) * data->acc_z; prev_acc_x = filtered_x; prev_acc_y = filtered_y; prev_acc_z = filtered_z; data->acc_x = filtered_x; data->acc_y = filtered_y; data->acc_z = filtered_z; } if (fabs(data->acc_x) < 0.03f) data->acc_x = 0.0f; if (fabs(data->acc_y) < 0.03f) data->acc_y = 0.0f; ESP_LOGD(TAG, "Accel data: X=%.3f, Y=%.3f, Z=%.3f", data->acc_x, data->acc_y, data->acc_z); } } // 读取陀螺仪数据 if (config_.mode == QMI8658A_MODE_GYRO_ONLY || config_.mode == QMI8658A_MODE_DUAL) { result = ReadGyroData(&data->gyro_x, &data->gyro_y, &data->gyro_z); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to read gyroscope data, error: %d", result); // 不再因为陀螺仪读取错误而标记整个数据无效,而是继续处理 } else { static float prev_gyro_x = 0, prev_gyro_y = 0, prev_gyro_z = 0; static bool gyro_initialized = false; if (!gyro_initialized) { prev_gyro_x = data->gyro_x; prev_gyro_y = data->gyro_y; prev_gyro_z = data->gyro_z; data->gyro_x = prev_gyro_x; data->gyro_y = prev_gyro_y; data->gyro_z = prev_gyro_z; gyro_initialized = true; } else { const float alpha = 0.5f; float filtered_x = alpha * prev_gyro_x + (1 - alpha) * data->gyro_x; float filtered_y = alpha * prev_gyro_y + (1 - alpha) * data->gyro_y; float filtered_z = alpha * prev_gyro_z + (1 - alpha) * data->gyro_z; prev_gyro_x = filtered_x; prev_gyro_y = filtered_y; prev_gyro_z = filtered_z; data->gyro_x = filtered_x; data->gyro_y = filtered_y; data->gyro_z = filtered_z; } if (fabs(data->gyro_x) < 0.8f) data->gyro_x = 0.0f; if (fabs(data->gyro_y) < 0.8f) data->gyro_y = 0.0f; if (fabs(data->gyro_z) < 0.8f) data->gyro_z = 0.0f; ESP_LOGV(TAG, "Gyro data after filtering: [%.3f, %.3f, %.3f] dps", data->gyro_x, data->gyro_y, data->gyro_z); } } // 读取温度数据 result = ReadTemperature(&data->temperature); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to read temperature data, error: %d", result); data_valid = false; } else { ESP_LOGD(TAG, "Temperature: %.2f°C", data->temperature); } // 如果数据有效,完成读取 if (data_valid) { data->valid = true; ESP_LOGD(TAG, "Successfully read sensor data (retry: %d)", retry); return QMI8658A_OK; } // 如果数据无效且未到最大重试次数,等待后重试 if (retry < max_retries - 1) { ESP_LOGW(TAG, "Invalid sensor data, retrying... (%d/%d)", retry + 1, max_retries); vTaskDelay(pdMS_TO_TICKS(10)); } } // 所有重试均失败 ESP_LOGE(TAG, "Failed to read valid sensor data after %d retries", max_retries); return SetError(QMI8658A_ERROR_DATA_NOT_READY); } bool QMI8658A::IsDataReady() { if (state_ != QMI8658A_STATE_READY) { return false; } uint8_t status = ReadReg(QMI8658A_STATUS0); bool acc_ready = (status & 0x01) != 0; bool gyro_ready = (status & 0x02) != 0; switch (config_.mode) { case QMI8658A_MODE_ACC_ONLY: return acc_ready; case QMI8658A_MODE_GYRO_ONLY: return gyro_ready; case QMI8658A_MODE_DUAL: // 任一就绪即可开始读取,读取本身使用突发读保证快照一致性 return acc_ready || gyro_ready; default: return false; } } qmi8658a_error_t QMI8658A::SetError(qmi8658a_error_t error) { last_error_ = error; return error; } void QMI8658A::DumpRegisters() { uint8_t chip = ReadReg(QMI8658A_WHO_AM_I); uint8_t rev = ReadReg(QMI8658A_REVISION_ID); uint8_t c1 = ReadReg(QMI8658A_CTRL1); uint8_t c2 = ReadReg(QMI8658A_CTRL2); uint8_t c3 = ReadReg(QMI8658A_CTRL3); uint8_t c4 = ReadReg(QMI8658A_CTRL4); uint8_t c5 = ReadReg(QMI8658A_CTRL5); uint8_t c6 = ReadReg(QMI8658A_CTRL6); uint8_t c7 = ReadReg(QMI8658A_CTRL7); uint8_t c8 = ReadReg(QMI8658A_CTRL8); uint8_t c9 = ReadReg(QMI8658A_CTRL9); uint8_t s0 = ReadReg(QMI8658A_STATUS0); uint8_t s1 = ReadReg(QMI8658A_STATUS1); ESP_LOGI(TAG, "ID:0x%02X REV:0x%02X", chip, rev); ESP_LOGI(TAG, "C1:0x%02X C2:0x%02X C3:0x%02X C4:0x%02X C5:0x%02X C6:0x%02X C7:0x%02X C8:0x%02X C9:0x%02X", c1,c2,c3,c4,c5,c6,c7,c8,c9); ESP_LOGI(TAG, "S0:0x%02X S1:0x%02X", s0, s1); } void QMI8658A::RunBaselineDiagnostics(uint16_t samples, uint16_t interval_ms) { if (state_ != QMI8658A_STATE_READY) { ESP_LOGE(TAG, "Sensor not ready for diagnostics"); return; } double ax_sum = 0, ay_sum = 0, az_sum = 0; double gx_sum = 0, gy_sum = 0, gz_sum = 0; double ax_sq = 0, ay_sq = 0, az_sq = 0; double gx_sq = 0, gy_sq = 0, gz_sq = 0; uint16_t ok = 0; for (uint16_t i = 0; i < samples; i++) { qmi8658a_data_t d; qmi8658a_error_t r = ReadSensorData(&d); if (r == QMI8658A_OK && d.valid) { ax_sum += d.acc_x; ay_sum += d.acc_y; az_sum += d.acc_z; gx_sum += d.gyro_x; gy_sum += d.gyro_y; gz_sum += d.gyro_z; ax_sq += d.acc_x * d.acc_x; ay_sq += d.acc_y * d.acc_y; az_sq += d.acc_z * d.acc_z; gx_sq += d.gyro_x * d.gyro_x; gy_sq += d.gyro_y * d.gyro_y; gz_sq += d.gyro_z * d.gyro_z; ok++; } vTaskDelay(pdMS_TO_TICKS(interval_ms)); } if (ok == 0) { ESP_LOGE(TAG, "No valid samples for diagnostics"); return; } double ax_mean = ax_sum / ok, ay_mean = ay_sum / ok, az_mean = az_sum / ok; double gx_mean = gx_sum / ok, gy_mean = gy_sum / ok, gz_mean = gz_sum / ok; double ax_std = sqrt(ax_sq / ok - ax_mean * ax_mean); double ay_std = sqrt(ay_sq / ok - ay_mean * ay_mean); double az_std = sqrt(az_sq / ok - az_mean * az_mean); double gx_std = sqrt(gx_sq / ok - gx_mean * gx_mean); double gy_std = sqrt(gy_sq / ok - gy_mean * gy_mean); double gz_std = sqrt(gz_sq / ok - gz_mean * gz_mean); double acc_mag = sqrt(ax_mean * ax_mean + ay_mean * ay_mean + az_mean * az_mean); double acc_bias = fabs(acc_mag - 1.0); ESP_LOGI(TAG, "Baseline accel mean: [%.4f, %.4f, %.4f] g", ax_mean, ay_mean, az_mean); ESP_LOGI(TAG, "Baseline accel std: [%.4f, %.4f, %.4f] g", ax_std, ay_std, az_std); ESP_LOGI(TAG, "Accel |mean|-1g: %.5f g", acc_bias); ESP_LOGI(TAG, "Baseline gyro mean: [%.4f, %.4f, %.4f] dps", gx_mean, gy_mean, gz_mean); ESP_LOGI(TAG, "Baseline gyro std: [%.4f, %.4f, %.4f] dps", gx_std, gy_std, gz_std); } // 新增:带验证的寄存器写入函数 qmi8658a_error_t QMI8658A::WriteRegWithVerification(uint8_t reg, uint8_t value, uint8_t max_retries) { for (uint8_t retry = 0; retry < max_retries; retry++) { // 写入寄存器 esp_err_t ret = WriteRegWithError(reg, value); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to write register 0x%02X (attempt %d/%d): %s", reg, retry + 1, max_retries, esp_err_to_name(ret)); if (retry == max_retries - 1) { return SetError(QMI8658A_ERROR_I2C_COMM); } vTaskDelay(pdMS_TO_TICKS(10)); // 等待10ms后重试 continue; } // 等待写入完成 vTaskDelay(pdMS_TO_TICKS(5)); // 读回验证 uint8_t read_value = ReadReg(reg); if (read_value == 0xFF) { ESP_LOGE(TAG, "Failed to read back register 0x%02X for verification (attempt %d/%d)", reg, retry + 1, max_retries); if (retry == max_retries - 1) { return SetError(QMI8658A_ERROR_I2C_COMM); } vTaskDelay(pdMS_TO_TICKS(10)); continue; } if (read_value == value) { ESP_LOGI(TAG, "Register 0x%02X successfully written and verified: 0x%02X", reg, value); return QMI8658A_OK; } else { ESP_LOGW(TAG, "Register 0x%02X verification failed (attempt %d/%d): wrote 0x%02X, read 0x%02X", reg, retry + 1, max_retries, value, read_value); if (retry == max_retries - 1) { return SetError(QMI8658A_ERROR_CONFIG_FAILED); } vTaskDelay(pdMS_TO_TICKS(10)); } } return SetError(QMI8658A_ERROR_CONFIG_FAILED); } // 新增:验证寄存器值函数 qmi8658a_error_t QMI8658A::VerifyRegisterValue(uint8_t reg, uint8_t expected_value, const char* reg_name) { uint8_t actual_value = ReadReg(reg); if (actual_value == 0xFF) { ESP_LOGE(TAG, "Failed to read %s register (0x%02X) for verification", reg_name, reg); return SetError(QMI8658A_ERROR_I2C_COMM); } if (actual_value != expected_value) { ESP_LOGE(TAG, "%s register (0x%02X) verification failed: expected 0x%02X, got 0x%02X", reg_name, reg, expected_value, actual_value); return SetError(QMI8658A_ERROR_CONFIG_FAILED); } ESP_LOGI(TAG, "%s register (0x%02X) verified successfully: 0x%02X", reg_name, reg, actual_value); return QMI8658A_OK; } // 新增:等待数据就绪函数 qmi8658a_error_t QMI8658A::WaitForDataReady(uint32_t timeout_ms) { uint32_t start_time = esp_timer_get_time() / 1000; // 转换为毫秒 uint32_t elapsed_time = 0; ESP_LOGI(TAG, "Waiting for data ready (timeout: %lu ms)...", timeout_ms); // 分阶段检查:先检查任一传感器就绪,再检查同时就绪 bool any_ready = false; while (elapsed_time < timeout_ms) { uint8_t status0 = ReadReg(QMI8658A_STATUS0); if (status0 == 0xFF) { ESP_LOGE(TAG, "Failed to read STATUS0 register while waiting for data ready"); return SetError(QMI8658A_ERROR_I2C_COMM); } // 检查加速度计和陀螺仪数据是否就绪 bool acc_ready = (status0 & 0x01) != 0; bool gyro_ready = (status0 & 0x02) != 0; // 检测到任一传感器就绪,记录并继续等待 if (acc_ready || gyro_ready) { if (!any_ready) { ESP_LOGI(TAG, "At least one sensor ready after %lu ms (STATUS0: 0x%02X)", elapsed_time, status0); any_ready = true; } // 如果任一传感器就绪且已等待至少100ms,就返回成功 // 这解决了某些情况下一个传感器就绪另一个未就绪的问题 if (any_ready && elapsed_time > 100) { ESP_LOGI(TAG, "At least one sensor ready, proceeding after %lu ms (STATUS0: 0x%02X)", elapsed_time, status0); return QMI8658A_OK; } } // 根据是否已检测到传感器就绪调整等待时间 uint8_t delay_time = any_ready ? 5 : 10; // 已检测到就绪则减少等待时间 vTaskDelay(pdMS_TO_TICKS(delay_time)); elapsed_time = (esp_timer_get_time() / 1000) - start_time; } ESP_LOGI(TAG, "Timeout waiting for data ready after %lu ms", timeout_ms); return SetError(QMI8658A_ERROR_TIMEOUT); } // 新增:自检函数 qmi8658a_error_t QMI8658A::PerformSelfTest() { ESP_LOGI(TAG, "Performing self-test..."); // 检查芯片ID uint8_t chip_id = GetChipId(); if (chip_id != QMI8658A_CHIP_ID) { ESP_LOGE(TAG, "Self-test failed: Invalid chip ID 0x%02X", chip_id); return SetError(QMI8658A_ERROR_CHIP_ID); } // 检查关键寄存器的可读性 uint8_t test_regs[] = {QMI8658A_WHO_AM_I, QMI8658A_REVISION_ID, QMI8658A_STATUS0, QMI8658A_STATUS1}; const char* test_reg_names[] = {"WHO_AM_I", "REVISION_ID", "STATUS0", "STATUS1"}; for (int i = 0; i < 4; i++) { uint8_t value = ReadReg(test_regs[i]); if (value == 0xFF) { ESP_LOGE(TAG, "Self-test failed: Cannot read %s register (0x%02X)", test_reg_names[i], test_regs[i]); return SetError(QMI8658A_ERROR_I2C_COMM); } ESP_LOGI(TAG, "Self-test: %s (0x%02X) = 0x%02X", test_reg_names[i], test_regs[i], value); } ESP_LOGI(TAG, "Self-test completed successfully"); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::UpdateConfiguration(const qmi8658a_config_t* new_config) { if (!new_config) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } // 验证新配置 qmi8658a_error_t result = ValidateConfiguration(new_config); if (result != QMI8658A_OK) { return result; } // 保存旧配置以便回滚 qmi8658a_config_t old_config = config_; config_ = *new_config; // 应用配置更改 result = ApplyConfigurationChanges(); if (result != QMI8658A_OK) { // 回滚到旧配置 config_ = old_config; return result; } ESP_LOGI(TAG, "Configuration updated successfully"); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::ValidateConfiguration(const qmi8658a_config_t* config) { if (!config) { return QMI8658A_ERROR_INVALID_PARAM; } // 验证加速度计量程 if (config->acc_range > QMI8658A_ACC_RANGE_16G) { ESP_LOGE(TAG, "Invalid accelerometer range: %d", config->acc_range); return QMI8658A_ERROR_INVALID_PARAM; } // 验证陀螺仪量程 if (config->gyro_range > QMI8658A_GYRO_RANGE_2048DPS) { ESP_LOGE(TAG, "Invalid gyroscope range: %d", config->gyro_range); return QMI8658A_ERROR_INVALID_PARAM; } // 验证ODR设置 if (config->acc_odr > QMI8658A_ODR_8000HZ || config->gyro_odr > QMI8658A_ODR_8000HZ) { ESP_LOGE(TAG, "Invalid ODR setting"); return QMI8658A_ERROR_INVALID_PARAM; } // 验证工作模式 if (config->mode > QMI8658A_MODE_DUAL) { ESP_LOGE(TAG, "Invalid operation mode: %d", config->mode); return QMI8658A_ERROR_INVALID_PARAM; } return QMI8658A_OK; } qmi8658a_error_t QMI8658A::GetConfiguration(qmi8658a_config_t* config) { if (!config) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } *config = config_; return QMI8658A_OK; } qmi8658a_error_t QMI8658A::SetAccelRange(qmi8658a_acc_range_t range) { if (range > QMI8658A_ACC_RANGE_16G) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } config_.acc_range = range; qmi8658a_error_t result = SetAccelConfig(range, config_.acc_odr); if (result == QMI8658A_OK) { UpdateScaleFactors(); } return result; } qmi8658a_error_t QMI8658A::SetGyroRange(qmi8658a_gyro_range_t range) { if (range > QMI8658A_GYRO_RANGE_2048DPS) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } config_.gyro_range = range; qmi8658a_error_t result = SetGyroConfig(range, config_.gyro_odr); if (result == QMI8658A_OK) { UpdateScaleFactors(); } return result; } qmi8658a_error_t QMI8658A::SetAccelODR(qmi8658a_odr_t odr) { if (odr > QMI8658A_ODR_8000HZ) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } config_.acc_odr = odr; return SetAccelConfig(config_.acc_range, odr); } qmi8658a_error_t QMI8658A::SetGyroODR(qmi8658a_odr_t odr) { if (odr > QMI8658A_ODR_8000HZ) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } config_.gyro_odr = odr; return SetGyroConfig(config_.gyro_range, odr); } qmi8658a_error_t QMI8658A::SetOperationMode(qmi8658a_mode_t mode) { if (mode > QMI8658A_MODE_DUAL) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } config_.mode = mode; return SetMode(mode); } qmi8658a_error_t QMI8658A::StartCalibration(uint32_t duration_ms) { if (state_ != QMI8658A_STATE_READY) { return SetError(QMI8658A_ERROR_DATA_NOT_READY); } is_calibrating_ = true; calibration_start_time_ = esp_timer_get_time() / 1000; // 转换为毫秒 calibration_duration_ = duration_ms; calibration_sample_count_ = 0; // 清零累加器 memset(calibration_acc_sum_, 0, sizeof(calibration_acc_sum_)); memset(calibration_gyro_sum_, 0, sizeof(calibration_gyro_sum_)); ESP_LOGI(TAG, "Started calibration for %" PRIu32 " ms", duration_ms); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::GetCalibrationStatus(bool* is_calibrating, float* progress) { if (!is_calibrating || !progress) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } *is_calibrating = is_calibrating_; if (is_calibrating_) { uint32_t current_time = esp_timer_get_time() / 1000; uint32_t elapsed = current_time - calibration_start_time_; *progress = (float)elapsed / calibration_duration_; if (elapsed >= calibration_duration_) { // 校准完成,计算偏置 if (calibration_sample_count_ > 0) { float mean_ax = calibration_acc_sum_[0] / calibration_sample_count_; float mean_ay = calibration_acc_sum_[1] / calibration_sample_count_; float mean_az = calibration_acc_sum_[2] / calibration_sample_count_; float mean_gx = calibration_gyro_sum_[0] / calibration_sample_count_; float mean_gy = calibration_gyro_sum_[1] / calibration_sample_count_; float mean_gz = calibration_gyro_sum_[2] / calibration_sample_count_; calibration_.acc_bias[0] = mean_ax; calibration_.acc_bias[1] = mean_ay; calibration_.acc_bias[2] = mean_az - 1.0f; calibration_.gyro_bias[0] = mean_gx; calibration_.gyro_bias[1] = mean_gy; calibration_.gyro_bias[2] = mean_gz; calibration_.is_calibrated = true; calibration_.calibration_time = current_time; } is_calibrating_ = false; *is_calibrating = false; *progress = 1.0f; ESP_LOGI(TAG, "Calibration completed with %" PRIu32 " samples", calibration_sample_count_); } } else { *progress = 0.0f; } return QMI8658A_OK; } qmi8658a_error_t QMI8658A::ApplyCalibration(const qmi8658a_calibration_t* calibration) { if (!calibration) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } calibration_ = *calibration; ESP_LOGI(TAG, "Applied calibration data"); return QMI8658A_OK; } qmi8658a_error_t QMI8658A::GetCalibrationData(qmi8658a_calibration_t* calibration) { if (!calibration) { return SetError(QMI8658A_ERROR_INVALID_PARAM); } *calibration = calibration_; return QMI8658A_OK; } void QMI8658A::UpdateScaleFactors() { // 根据加速度计量程计算比例因子 switch (config_.acc_range) { case QMI8658A_ACC_RANGE_2G: acc_scale_ = 2.0f / 32768.0f; break; case QMI8658A_ACC_RANGE_4G: acc_scale_ = 4.0f / 32768.0f; break; case QMI8658A_ACC_RANGE_8G: acc_scale_ = 8.0f / 32768.0f; break; case QMI8658A_ACC_RANGE_16G: acc_scale_ = 16.0f / 32768.0f; break; default: acc_scale_ = 2.0f / 32768.0f; break; } // 根据陀螺仪量程计算比例因子 switch (config_.gyro_range) { case QMI8658A_GYRO_RANGE_16DPS: gyro_scale_ = 16.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_32DPS: gyro_scale_ = 32.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_64DPS: gyro_scale_ = 64.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_128DPS: gyro_scale_ = 128.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_256DPS: gyro_scale_ = 256.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_512DPS: gyro_scale_ = 512.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_1024DPS: gyro_scale_ = 1024.0f / 32768.0f; break; case QMI8658A_GYRO_RANGE_2048DPS: gyro_scale_ = 2048.0f / 32768.0f; break; default: gyro_scale_ = 256.0f / 32768.0f; break; } } qmi8658a_error_t QMI8658A::ApplyConfigurationChanges() { qmi8658a_error_t result; // 应用加速度计配置 result = SetAccelConfig(config_.acc_range, config_.acc_odr); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to configure accelerometer"); state_ = QMI8658A_STATE_ERROR; return result; } // 应用陀螺仪配置 result = SetGyroConfig(config_.gyro_range, config_.gyro_odr); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to configure gyroscope"); state_ = QMI8658A_STATE_ERROR; return result; } // 设置工作模式 uint8_t mode_val = config_.mode; result = SetMode(static_cast(mode_val)); if (result != QMI8658A_OK) { ESP_LOGE(TAG, "Failed to set mode"); state_ = QMI8658A_STATE_ERROR; return result; } // 更新比例因子 UpdateScaleFactors(); return QMI8658A_OK; } QMI8658A::~QMI8658A() { // 停止缓冲读取 if (buffer_enabled_) { StopBufferedReading(); } // 停止校准 if (is_calibrating_) { is_calibrating_ = false; } // 清理缓冲区 - 只有在mutex已创建时才释放 if (data_buffer_.mutex != nullptr) { vSemaphoreDelete(data_buffer_.mutex); data_buffer_.mutex = nullptr; } // 禁用FIFO if (fifo_enabled_) { DisableFIFO(); } // 设置为禁用模式 - 只有在传感器已初始化时才调用 if (state_ != QMI8658A_STATE_UNINITIALIZED) { SetMode(QMI8658A_MODE_DISABLE); } ESP_LOGI(TAG, "QMI8658A destructor completed"); }