Skip to content

Issue: QMI8658 Pedometer always reads 0 steps #109

@elfoteo

Description

@elfoteo

Hardware: ESP32-S3 (Waveshare ESP32-S3-Touch-AMOLED-1.8)
Component: SensorLib (QMI8658)

Description

I am unable to get the QMI8658 pedometer to count steps. The getPedometerCounter() function always returns 0, even though the Accelerometer and Gyroscope are working correctly and returning valid data.

Steps to Reproduce

  1. Initialize the sensor with configAccelerometer (1000Hz) and configGyroscope.
  2. Call configPedometer with standard parameters.
  3. Call enablePedometer().
  4. Read getPedometerCounter() in a loop.

Result: The counter stays at 0.

Investigation & Potential Bug in SensorQMI8658.hpp

I investigated the configPedometer implementation in SensorQMI8658.hpp and noticed potential issues with how the configuration pages are addressed.

Currently, the code writes 0x02 to QMI8658_REG_CAL4_L for both configuration commands:

// SensorQMI8658.hpp : configPedometer()

// Packet 1
writeRegister(QMI8658_REG_CAL4_H, 0x01);
writeRegister(QMI8658_REG_CAL4_L, 0x02); // <--- Sets Page 2?
writeCommand(CTRL_CMD_CONFIGURE_PEDOMETER);

// Packet 2
writeRegister(QMI8658_REG_CAL4_H, 0x02);
writeRegister(QMI8658_REG_CAL4_L, 0x02); // <--- Sets Page 2?
writeCommand(CTRL_CMD_CONFIGURE_PEDOMETER);

I attempted to fix this by changing the page indices to 0x00 and 0x01 respectively, but the issue persists.

Configuration Used

I have tried relaxing the thresholds significantly to rule out sensitivity issues:

s_qmi.configPedometer(
    /*sample_cnt*/ 500,
    /*peak2peak*/ 70,   // Very sensitive
    /*peak*/ 50,        // Very sensitive
    /*time_up*/ 2000,   // 2s window
    /*time_low*/ 100,
    /*entry_cnt*/ 2,    // Start counting after 2 steps
    /*precision*/ 0,
    /*sig_count*/ 1     // Update every step
);

Question

  1. Is there a known working configuration for the Pedometer on this specific library version?
  2. Are the CAL4_L register values in configPedometer correct?
  3. Does the Pedometer require a specific ODR (e.g., does it fail at 1000Hz)?

Any guidance would be appreciated.

Full code:

// qmi8658.c
#include "qmi8658c.h"
#include "SensorQMI8658.hpp"
#include "esp_log.h"
#include <string.h>

static const char *TAG = "QMI8658";
static SensorQMI8658 s_qmi;
static SensorData s_cache;
static bool s_cache_valid = false;

esp_err_t qmi8658_init(i2c_port_t i2c_num, gpio_num_t sda_pin,
                       gpio_num_t scl_pin) {
    if (!s_qmi.begin(i2c_num, QMI8658_I2C_ADDR, sda_pin, scl_pin)) {
        ESP_LOGE(TAG, "QMI8658 not found on I2C!");
        return ESP_ERR_NOT_FOUND;
    }

    // accel @ ±4g, 1 000 Hz, no LPF
    s_qmi.configAccelerometer(SensorQMI8658::ACC_RANGE_4G,
                              SensorQMI8658::ACC_ODR_1000Hz,
                              SensorQMI8658::LPF_MODE_0, true);

    // gyro @ ±64 dps, 896.8 Hz, strongest LPF
    s_qmi.configGyroscope(SensorQMI8658::GYR_RANGE_64DPS,
                          SensorQMI8658::GYR_ODR_896_8Hz,
                          SensorQMI8658::LPF_MODE_3, true);

    // pedometer configuration
    s_qmi.configPedometer(
        /*sample_cnt*/ 50,
        /*peak2peak*/ 200,
        /*peak*/ 100,
        /*time_up*/ 200,
        /*time_low*/ 20,
        /*entry_cnt*/ 10,
        /*precision*/ 0,
        /*sig_count*/ 4);

    s_qmi.enableAccelerometer();
    s_qmi.enableGyroscope();
    if (!s_qmi.enablePedometer()) {
        ESP_LOGW(TAG, "Pedometer enable failed");
    }

    memset(&s_cache, 0, sizeof(s_cache));
    s_cache_valid = false;
    ESP_LOGI(TAG, "QMI8658 initialized");
    return ESP_OK;
}

esp_err_t qmi8658_update(void) {
    if (!s_qmi.getDataReady()) {
        // no new data yet
        return ESP_ERR_TIMEOUT;
    }

    // read and cache all fields
    s_qmi.getAccelerometer(s_cache.accel.x, s_cache.accel.y, s_cache.accel.z);

    s_qmi.getGyroscope(s_cache.gyro.x, s_cache.gyro.y, s_cache.gyro.z);

    s_cache.pedometer = s_qmi.getPedometerCounter();
    s_cache.temperature = s_qmi.getTemperature_C();
    s_cache.timestamp = s_qmi.getTimestamp();

    s_cache_valid = true;
    return ESP_OK;
}

SensorData qmi8658_get_sensor_data(void) {
    // return the last‐cached copy (caller must check validity if needed)
    return s_cache;
}

bool qmi8658_get_accel(imu_data_t *out) {
    if (!s_cache_valid || out == NULL)
        return false;
    *out = s_cache.accel;
    return true;
}

bool qmi8658_get_gyro(imu_data_t *out) {
    if (!s_cache_valid || out == NULL)
        return false;
    *out = s_cache.gyro;
    return true;
}

uint32_t qmi8658_get_pedometer(void) {
    return s_cache_valid ? s_cache.pedometer : 0;
}

float qmi8658_get_temperature(void) {
    return s_cache_valid ? s_cache.temperature : 0.0f;
}

uint32_t qmi8658_get_timestamp(void) {
    return s_cache_valid ? s_cache.timestamp : 0;
}

esp_err_t qmi8658_shutdown(void) {
    ESP_LOGI(TAG, "Powering DOWN QMI8658…");
    // disable pedometer, gyro, accel
    s_qmi.disablePedometer();
    s_qmi.disableGyroscope();
    s_qmi.disableAccelerometer();
    return ESP_OK;
}

esp_err_t qmi8658_wakeup(void) {
    ESP_LOGI(TAG, "Waking QMI8658 back up…");
    s_qmi.enableAccelerometer();
    s_qmi.enableGyroscope();
    if (!s_qmi.enablePedometer()) {
        ESP_LOGW(TAG, "Pedometer re‑enable failed");
    }
    return ESP_OK;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions