The QMI8658A is a high-performance MEMS-based attitude sensor integrating accelerometer, gyroscope, and magnetometer functionalities for precise 3D spatial orientation and motion tracking.
Key Specifications
- High-resolution acceleration and angular velocity outputs.
- On-chip temperatuer sensor with calibration algorithms for enhanced stability.
- User-configurable output data rate and full-scale ranges.
- I2C and SPI digital communication interfaces.
- High resistance to electromagnetic interference, suitable for complex environments.
Functional Principle
The sensor determines device orientation by measuring linear acceleration along three axes (X, Y, Z) via its accelerometer. The gyroscope tracks rotational velocity around these axes, while the magnetometer senses the Earth's magnetic field vector. A sensor fusion algorithm processes this data to compute the device's real-time attitude.
Pin Configuration and Communication
The device typically uses an LGA package. Key pins include those for power (VDD), ground (GND), and communication (SDA, SCL for I2C; SDI, SDO, SCK, CS for SPI).
The SDO/SA0 pin features an internal 200kΩ pull-up resistor, enabled by default. This pin determines the I2C slave address: left floating or tied high for address 0x6A, tied low for address 0x6B. The RESV (Pin 10) should not be connected to GND; it is recommended to connect it to VDDIO or leave it floating with its internal pull-up enabled. The RESV-NC (Pin 11) is a non-connect pin and should be left floating.
Interface Modes
- I2C/I3C Mode: Uses SDA and SCL lines.
- 3-Wire SPI Mode: Uses SDI, SDO, and SCK lines. The CS pin can be controlled via GPIO.
- 4-Wire SPI Mode: Uses SDI, SDO, SCK, and a dedicated CS line.
Register Map Summary
Key register groups control device operation:
- Communication Select Register: Configures the interface protocol (I2C/SPI).
- Accelerometer Configuration Register: Sets range, bandwidth, and power mode.
- Gyroscope Configuration Register: Sets range, bandwidth, and power mode.
- Output Data Register: Holds latest sensor readings.
Driver Implemantation Examples
I2C Linux Kernel Driver Snippet
#include <linux/i2c.h>
#include <linux/module.h>
static int sensor_probe(struct i2c_client *clnt, const struct i2c_device_id *id)
{
int status;
u8 config_cmd[2] = {0x80, 0x00}; // Enable and configure
status = i2c_master_send(clnt, config_cmd, 2);
if (status < 0) {
dev_err(&clnt->dev, "Configuration failed\n");
return status;
}
// ... Data reading logic
return 0;
}
static const struct i2c_device_id sensor_id[] = {
{ "qmi8658a", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, sensor_id);
static struct i2c_driver sensor_drv = {
.driver = { .name = "qmi8658a" },
.probe = sensor_probe,
.id_table = sensor_id,
};
module_i2c_driver(sensor_drv);
MODULE_LICENSE("GPL");
SPI Data Reading Example (User Space)
#include <stdio.h>
#include <fcntl.h>
#include <linux/spi/spidev.h>
int main() {
int spifd = open("/dev/spidev0.0", O_RDWR);
uint8_t tx = 0x37; // Temp register address
uint8_t rx[2];
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)&tx,
.rx_buf = (unsigned long)rx,
.len = 3,
};
ioctl(spifd, SPI_IOC_MESSAGE(1), &tr);
int16_t temp_val = (rx[1] << 8) | rx[2];
printf("Temperature: %d\n", temp_val);
close(spifd);
return 0;
}
Raw Data Conversion
Sensor outputs are typically 16-bit two's complement values. A conversion function is required.
void convert_raw_data(uint8_t *raw, int16_t *result) {
// Assumes raw[] contains 6 bytes for X, Y, Z axes.
for (int idx = 0; idx < 3; idx++) {
// Combine high and low bytes (little-endian)
result[idx] = (int16_t)((raw[2*idx + 1] << 8) | raw[2*idx]);
}
}