Skip to content

Commit c940f85

Browse files
committed
drivers/sensors: Add QST QMI8658 6-axis IMU sensor driver
Add comprehensive driver support for the QST QMI8658 6-axis IMU sensor with both character device and uORB interface options. Key features implemented: * I2C communication with configurable frequency * Accelerometer and gyroscope data acquisition * Multiple full-scale ranges and ODR settings * Low-pass filter configuration * Synchronous/asynchronous sampling modes * FIFO support and interrupt handling * Temperature sensing capability * Device calibration and self-test functions Driver architecture: * qmi8658_base.c: Core I2C communication and sensor control * qmi8658.c: Character device interface with ioctl support * qmi8658_uorb.c: uORB-based sensor interface for real-time applications * qmi8658.h: Public API with register definitions and scale factors Configuration options: * CONFIG_SENSORS_QMI8658: Enable driver support * CONFIG_SENSORS_QMI8658_UORB: Use uORB interface instead of character device * CONFIG_SENSORS_QMI8658_POLL: Enable polling mode with configurable interval * CONFIG_QMI8658_I2C_FREQUENCY: Set I2C communication frequency Signed-off-by: Huang Qi <[email protected]>
1 parent d3021ff commit c940f85

File tree

12 files changed

+2911
-0
lines changed

12 files changed

+2911
-0
lines changed

Documentation/components/drivers/special/sensors.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ general interface.
3030
sensors/mcp9600.rst
3131
sensors/mpl115a.rst
3232
sensors/nau7802.rst
33+
sensors/qmi8658.rst
3334
sensors/sht4x.rst
3435
sensors/lsm6dso32.rst
3536
sensors/lis2mdl.rst
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
=======
2+
QMI8658
3+
=======
4+
5+
The QMI8658 is a high-performance 6-axis IMU sensor by QST featuring a 3-axis
6+
accelerometer and 3-axis gyroscope. It supports both I2C and SPI interfaces,
7+
although this driver currently supports I2C communication only.
8+
9+
This driver uses the :doc:`uorb
10+
</components/drivers/special/sensors/sensors_uorb>` interface. It supports the
11+
self-test capability for both the accelerometer and gyroscope.
12+
13+
This driver also provides a legacy character device interface. It supports comprehensive features including
14+
multiple full-scale ranges, configurable ODR settings, low-pass filters,
15+
FIFO buffer management, temperature sensing, and device calibration.
16+
17+
.. note::
18+
The QMI8658 is a feature-rich sensor with advanced capabilities like
19+
tap detection, motion detection, and various low-power modes. This driver
20+
implements the core functionality for accelerometer and gyroscope data
21+
acquisition with room for future feature extensions.
22+
23+
Application Programming Interface
24+
=================================
25+
26+
.. code-block:: c
27+
28+
#include <nuttx/sensors/qmi8658.h>
29+
30+
The QMI8658 driver provides two registration functions:
31+
32+
1. **Character Device Interface**: ``qmi8658_register()``
33+
2. **uORB Interface**: ``qmi8658_uorb_register()``
34+
35+
Character Device Registration
36+
-----------------------------
37+
38+
The character device interface registers the driver at a specified path (e.g., "/dev/imu0")
39+
and provides ioctl-based control and data reading.
40+
41+
.. code-block:: c
42+
43+
/* Example character device registration */
44+
45+
ret = qmi8658_register("/dev/imu0", i2c_bus, QMI8658_I2C_ADDR_DEFAULT);
46+
if (ret < 0)
47+
{
48+
syslog(LOG_ERR, "Couldn't register QMI8658: %d\n", ret);
49+
return ret;
50+
}
51+
52+
/* Configure sensor ranges */
53+
54+
int fd = open("/dev/imu0", O_RDONLY);
55+
if (fd < 0)
56+
{
57+
syslog(LOG_ERR, "Failed to open QMI8658 device\n");
58+
return -errno;
59+
}
60+
61+
/* Set accelerometer range to ±8g */
62+
63+
ret = ioctl(fd, SNIOC_SET_ACC_RANGE, QMI8658_ACC_FS_8G);
64+
if (ret < 0)
65+
{
66+
syslog(LOG_ERR, "Failed to set accelerometer range: %d\n", ret);
67+
}
68+
69+
/* Set gyroscope range to ±500 dps */
70+
71+
ret = ioctl(fd, SNIOC_SET_GYRO_RANGE, QMI8658_GYRO_FS_512DPS);
72+
if (ret < 0)
73+
{
74+
syslog(LOG_ERR, "Failed to set gyroscope range: %d\n", ret);
75+
}
76+
77+
/* Enable both sensors */
78+
79+
ret = ioctl(fd, SNIOC_ENABLE_SENSOR, 0);
80+
if (ret < 0)
81+
{
82+
syslog(LOG_ERR, "Failed to enable sensors: %d\n", ret);
83+
}
84+
85+
/* Read sensor data */
86+
87+
struct qmi8658_data_s data;
88+
ssize_t bytes_read = read(fd, &data, sizeof(data));
89+
if (bytes_read == sizeof(data))
90+
{
91+
printf("Accel: X=%d, Y=%d, Z=%d\n", data.accel_x, data.accel_y, data.accel_z);
92+
printf("Gyro: X=%d, Y=%d, Z=%d\n", data.gyro_x, data.gyro_y, data.gyro_z);
93+
printf("Temperature: %d\n", data.temperature);
94+
}
95+
96+
close(fd);
97+
98+
uORB Registration
99+
-----------------
100+
101+
The uORB interface registers the driver and creates separate uORB topics for
102+
accelerometer and gyroscope data under ``/dev/uorb/``: ``sensor_accel<n>`` and
103+
``sensor_gyro<n>``, where ``n`` is the device number.
104+
105+
.. code-block:: c
106+
107+
/* Example uORB registration */
108+
109+
ret = qmi8658_uorb_register(0, i2c_bus, QMI8658_I2C_ADDR_DEFAULT);
110+
if (ret < 0)
111+
{
112+
syslog(LOG_ERR, "Couldn't register QMI8658 uORB: %d\n", ret);
113+
return ret;
114+
}
115+
116+
Configuration Options
117+
=====================
118+
119+
The QMI8658 driver supports several Kconfig options:
120+
121+
* ``CONFIG_SENSORS_QMI8658``: Enable QMI8658 driver support
122+
* ``CONFIG_SENSORS_QMI8658_UORB``: Use uORB interface instead of character device
123+
* ``CONFIG_SENSORS_QMI8658_POLL``: Enable polling mode with configurable interval
124+
* ``CONFIG_SENSORS_QMI8658_POLL_INTERVAL``: Set polling interval (default 1s)
125+
* ``CONFIG_QMI8658_I2C_FREQUENCY``: Set I2C communication frequency (default 400kHz)
126+
127+
Supported Features
128+
==================
129+
130+
Accelerometer
131+
-------------
132+
133+
* **Full-Scale Ranges**: ±2g, ±4g, ±8g, ±16g
134+
* **Output Data Rates**: 1000Hz, 500Hz, 250Hz, 125Hz, 62.5Hz, 31.25Hz
135+
* **Low-Power ODR**: 128Hz, 21Hz, 11Hz, 3Hz
136+
* **Low-Pass Filters**: 4 different modes + OFF
137+
138+
Gyroscope
139+
---------
140+
141+
* **Full-Scale Ranges**: ±16, ±32, ±64, ±128, ±256, ±512, ±1024 dps
142+
* **Output Data Rates**: 7174.4Hz, 3587.2Hz, 1793.6Hz, 896.8Hz, 448.4Hz, 224.2Hz, 112.1Hz, 56.05Hz, 28.025Hz
143+
* **Low-Pass Filters**: 4 different modes + OFF
144+
145+
Additional Features
146+
-----------------==
147+
148+
* **Temperature Sensor**: 16-bit temperature data with 256 LSB/°C scale factor
149+
* **FIFO Buffer**: Configurable FIFO with watermark and interrupt support
150+
* **Sampling Modes**: Synchronous and asynchronous sampling
151+
* **Interrupt Support**: Data ready, FIFO watermark, motion detection
152+
* **Self-Test**: Built-in self-test capability for both sensors
153+
* **Calibration**: On-demand calibration support
154+
155+
IOCTL Commands
156+
==============
157+
158+
Character Device IOCTLs
159+
-----------------------
160+
161+
* ``SNIOC_SET_ACC_RANGE``: Set accelerometer full-scale range
162+
* ``SNIOC_SET_GYRO_RANGE``: Set gyroscope full-scale range
163+
* ``SNIOC_ENABLE_SENSOR``: Enable both accelerometer and gyroscope
164+
* ``SNIOC_DISABLE_SENSOR``: Disable both accelerometer and gyroscope
165+
166+
uORB IOCTLs
167+
-----------
168+
169+
* ``SNIOC_SETFULLSCALE``: Set full-scale range (argument in g for accel, dps for gyro)
170+
* ``SNIOC_SET_CALIBVALUE``: Set calibration offsets
171+
* ``SNIOC_SELFTEST``: Perform sensor self-test
172+
* ``SNIOC_WHO_AM_I``: Read device ID (should return 0x05)
173+
174+
Scale Factors
175+
=============
176+
177+
The driver provides predefined scale factors for converting raw sensor data
178+
to physical units:
179+
180+
Accelerometer Scale Factors (LSB/g):
181+
182+
.. code-block:: c
183+
184+
#define QMI8658_ACC_SCALE_2G (16384.0f)
185+
#define QMI8658_ACC_SCALE_4G (8192.0f)
186+
#define QMI8658_ACC_SCALE_8G (4096.0f)
187+
#define QMI8658_ACC_SCALE_16G (2048.0f)
188+
189+
Gyroscope Scale Factors (LSB/dps):
190+
191+
.. code-block:: c
192+
193+
#define QMI8658_GYRO_SCALE_16DPS (2048.0f)
194+
#define QMI8658_GYRO_SCALE_32DPS (1024.0f)
195+
#define QMI8658_GYRO_SCALE_64DPS (512.0f)
196+
#define QMI8658_GYRO_SCALE_128DPS (256.0f)
197+
#define QMI8658_GYRO_SCALE_256DPS (128.0f)
198+
#define QMI8658_GYRO_SCALE_512DPS (64.0f)
199+
#define QMI8658_GYRO_SCALE_1024DPS (32.0f)
200+
201+
Temperature Scale Factor (LSB/°C):
202+
203+
.. code-block:: c
204+
205+
#define QMI8658_TEMP_SCALE (256.0f)
206+
207+
Data Conversion
208+
===============
209+
210+
To convert raw sensor data to physical units:
211+
212+
.. code-block:: c
213+
214+
/* Convert accelerometer raw data to g */
215+
216+
float accel_x_g = (float)raw_accel_x / QMI8658_ACC_SCALE_8G;
217+
float accel_y_g = (float)raw_accel_y / QMI8658_ACC_SCALE_8G;
218+
float accel_z_g = (float)raw_accel_z / QMI8658_ACC_SCALE_8G;
219+
220+
/* Convert gyroscope raw data to dps */
221+
222+
float gyro_x_dps = (float)raw_gyro_x / QMI8658_GYRO_SCALE_512DPS;
223+
float gyro_y_dps = (float)raw_gyro_y / QMI8658_GYRO_SCALE_512DPS;
224+
float gyro_z_dps = (float)raw_gyro_z / QMI8658_GYRO_SCALE_512DPS;
225+
226+
/* Convert temperature raw data to °C */
227+
228+
float temp_c = (float)raw_temp / QMI8658_TEMP_SCALE;
229+
230+
Debugging and Testing
231+
=====================
232+
233+
To debug the QMI8658 device, you can:
234+
235+
1. **Enable Debug Output**: Set ``CONFIG_DEBUG_SENSORS`` and ``CONFIG_DEBUG_INFO``
236+
2. **Use uORB Listener**: Include ``uorb_listener`` application to monitor sensor data
237+
3. **Check Device ID**: Use ``SNIOC_WHO_AM_I`` to verify communication
238+
239+
.. code-block:: c
240+
241+
/* Verify device communication */
242+
243+
uint8_t device_id;
244+
ret = ioctl(fd, SNIOC_WHO_AM_I, (unsigned long)&device_id);
245+
if (ret == OK && device_id == QMI8658_REG_WHOAMI_DEFAULT)
246+
{
247+
printf("QMI8658 communication OK (ID: 0x%02X)\n", device_id);
248+
}
249+
else
250+
{
251+
printf("QMI8658 communication failed\n");
252+
}
253+
254+
Performance Considerations
255+
==========================
256+
257+
* **I2C Frequency**: Default 400kHz, configurable via ``CONFIG_QMI8658_I2C_FREQUENCY``
258+
* **Polling Overhead**: Use interrupt-driven mode when possible for better efficiency
259+
* **FIFO Usage**: Enable FIFO to reduce I2C traffic and CPU overhead
260+
* **Power Management**: Utilize low-power ODR settings for battery-powered applications
261+
262+
Limitations
263+
===========
264+
265+
* Currently supports I2C interface only (SPI support can be added)
266+
* Advanced features like tap detection and motion detection not yet implemented
267+
* FIFO interrupt handling not fully implemented
268+
* Some low-power modes require additional configuration
269+
270+
Hardware Connections
271+
====================
272+
273+
I2C Interface
274+
--------------
275+
276+
* **VDD**: Power supply (1.71V to 3.6V)
277+
* **GND**: Ground
278+
* **SDA/SDI**: I2C Serial Data
279+
* **SCL/SCLK**: I2C Serial Clock
280+
* **CS**: Chip Select (connect to VDD for I2C mode)
281+
* **INT1/INT2**: Interrupt pins (optional)
282+
283+
Typical I2C addresses:
284+
* **Primary**: 0x6B
285+
* **Secondary**: 0x6D (when SDO/SA0 pin is high)
286+
287+
.. note::
288+
Ensure proper pull-up resistors on SDA and SCL lines (typically 4.7kΩ for 3.3V).
289+
290+
Troubleshooting
291+
===============
292+
293+
**Device Not Responding**
294+
* Check I2C address and connections
295+
* Verify power supply voltage
296+
* Ensure CS pin is properly configured for I2C mode
297+
298+
**Incorrect Readings**
299+
* Verify full-scale range settings
300+
* Check scale factor calculations
301+
* Ensure sensor is properly calibrated
302+
303+
**Communication Errors**
304+
* Reduce I2C frequency
305+
* Check for signal integrity issues
306+
* Verify pull-up resistor values
307+
308+
**Performance Issues**
309+
* Enable FIFO mode for high ODR settings
310+
* Use interrupt-driven mode instead of polling
311+
* Optimize I2C clock frequency for your platform

Documentation/components/drivers/special/sensors/sensors_legacy.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Drivers that are available also with the new sensor framework are marked with ``
6767
- ms58xx
6868
- msa301
6969
- qencoder
70+
- :doc:`qmi8658`
7071
- scd30
7172
- scd41
7273
- sgp30

Documentation/components/drivers/special/sensors/sensors_uorb.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ Implemented Drivers
496496
- mpu9250
497497
- ms56xx
498498
- :doc:`nau7802`
499+
- :doc:`qmi8658`
499500
- :doc:`sht4x`
500501
- :doc:`lsm6dso32`
501502
- wtgahrs2

drivers/sensors/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,17 @@ if(CONFIG_SENSORS)
344344
list(APPEND SRCS tmp112.c)
345345
endif()
346346

347+
# QMI8658 6-axis IMU
348+
349+
if(CONFIG_SENSORS_QMI8658)
350+
list(APPEND SRCS qmi8658_base.c)
351+
if(CONFIG_SENSORS_QMI8658_UORB)
352+
list(APPEND SRCS qmi8658_uorb.c)
353+
else()
354+
list(APPEND SRCS qmi8658.c)
355+
endif()
356+
endif()
357+
347358
endif() # CONFIG_I2C
348359

349360
# These drivers depend on SPI support

0 commit comments

Comments
 (0)