Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ __pycache__/
.ruff_cache/
.dmypy.json
*.pyi
.venv/

# Databases
*.db
Expand Down
184 changes: 184 additions & 0 deletions LSM6DSV_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# LSM6DSV IMU Driver Implementation

This document describes the implementation of the LSM6DSV 6-axis IMU driver for the IMU Python package.

## Overview

The LSM6DSV is a 6-axis IMU (Inertial Measurement Unit) from STMicroelectronics that combines a 3-axis accelerometer and 3-axis gyroscope. This implementation provides SPI communication support for reading sensor data.

## Features

- **SPI Communication**: Full SPI interface support with configurable settings
- **Accelerometer**: 3-axis acceleration data with configurable ranges (±2g, ±4g, ±8g, ±16g)
- **Gyroscope**: 3-axis angular velocity data with configurable ranges (±125 to ±4000 dps)
- **Temperature**: Built-in temperature sensor
- **Background Threading**: Continuous data acquisition in background thread
- **Configurable ODR**: Adjustable output data rates for both sensors
- **Python Integration**: Seamless integration with the existing IMU package

## Hardware Requirements

- LSM6DSV sensor connected via SPI
- Linux system with SPI support
- Appropriate permissions to access SPI devices (typically `/dev/spidev*`)

## SPI Connection

The LSM6DSV uses SPI mode 0 (CPOL=0, CPHA=0) with the following connections:

- **MOSI**: Master Out Slave In
- **MISO**: Master In Slave Out
- **SCLK**: Serial Clock
- **CS**: Chip Select (active low)
- **VCC**: 1.71V to 3.6V
- **GND**: Ground

## Usage

### Basic Usage

```python
from imu import create_lsm6dsvtr

# Create an LSM6DSV reader
reader = create_lsm6dsvtr("/dev/spidev1.0")

# Read sensor data
data = reader.get_data()

if data.get('accelerometer'):
accel = data['accelerometer']
print(f"Acceleration: x={accel.x:.3f}, y={accel.y:.3f}, z={accel.z:.3f} m/s²")

if data.get('gyroscope'):
gyro = data['gyroscope']
print(f"Angular velocity: x={gyro.x:.3f}, y={gyro.y:.3f}, z={gyro.z:.3f} deg/s")

if data.get('temperature') is not None:
print(f"Temperature: {data['temperature']:.1f}°C")

# Clean up
reader.stop()
```

### Advanced Configuration

The driver supports runtime configuration of sensor ranges and output data rates:

```python
# Note: These methods would need to be exposed in the Python bindings
# reader.set_accel_range(AccelRange.G4) # ±4g range
# reader.set_gyro_range(GyroRange.Dps500) # ±500 dps range
# reader.set_accel_odr(AccelOdr.Hz208) # 208 Hz output rate
# reader.set_gyro_odr(GyroOdr.Hz208) # 208 Hz output rate
```

## Implementation Details

### File Structure

```
imu/drivers/lsm6dsv/
├── Cargo.toml # Rust package configuration
├── README.md # Driver-specific documentation
└── src/
├── lib.rs # Main driver implementation
├── registers.rs # Register definitions and constants
└── spi.rs # SPI communication layer
```

### Key Components

1. **Register Definitions** (`registers.rs`):
- All LSM6DSV register addresses
- Output data rate (ODR) settings
- Full-scale range settings
- Sensitivity constants

2. **SPI Communication** (`spi.rs`):
- Low-level SPI read/write operations
- Register-based communication
- Error handling for SPI operations

3. **Main Driver** (`lib.rs`):
- High-level sensor interface
- Data conversion and scaling
- Background thread management
- Configuration commands

### Data Conversion

- **Accelerometer**: Raw values are converted from mg to m/s² using appropriate sensitivity factors
- **Gyroscope**: Raw values are converted from mdps to deg/s using appropriate sensitivity factors
- **Temperature**: Raw values are converted to Celsius using the formula: `temp = (raw * 1/256) + 25`

### Error Handling

The driver provides comprehensive error handling for:
- SPI communication failures
- Invalid chip ID detection
- Register read/write errors
- Thread synchronization issues

## Testing

A test script is provided (`test_lsm6dsv.py`) that can be used to verify the implementation:

```bash
python3 test_lsm6dsv.py
```

This script will:
1. Test import functionality
2. Attempt to create an LSM6DSV reader
3. Try to read sensor data
4. Test cleanup procedures

## Dependencies

- `spidev`: Linux SPI device interface
- `byteorder`: Byte order conversion utilities
- `log`: Logging framework
- `imu-traits`: Common IMU interface traits

## Limitations

- Linux-only support (SPI device access)
- Requires appropriate permissions for SPI device access
- No magnetometer support (LSM6DSV doesn't include a magnetometer)
- No quaternion/euler angle calculation (accelerometer + gyroscope only)

## Future Enhancements

Potential improvements could include:
- I2C communication support
- Advanced filtering and sensor fusion
- Interrupt-driven data acquisition
- Additional sensor features (if available in LSM6DSV variants)

## Troubleshooting

### Common Issues

1. **Permission Denied**: Ensure the user has access to SPI devices
```bash
sudo usermod -a -G spi $USER
```

2. **Device Not Found**: Verify the SPI device path exists
```bash
ls -la /dev/spidev*
```

3. **Invalid Chip ID**: Check SPI connections and power supply

4. **No Data**: Verify sensor initialization and SPI communication

### Debug Mode

Enable debug logging to troubleshoot issues:
```python
import logging
logging.basicConfig(level=logging.DEBUG)
```

1 change: 1 addition & 0 deletions imu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ hiwonder = "0.6.4"
linux_bno055 = "0.1.3"
linux_bmi088 = "0.1.3"
hexmove = "0.2.3"
lsm6dsv = { path = "drivers/lsm6dsv" }
5 changes: 5 additions & 0 deletions imu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
create_bno055_reader,
create_hexmove_reader,
create_hiwonder_reader,
create_lsm6dsvtr_reader,
)


Expand Down Expand Up @@ -45,6 +46,10 @@ def create_hexmove(can_interface: str = "can0", node_id: int = 1, param_id: int
"""Create a Hexmove IMU reader on the specified CAN interface."""
return create_hexmove_reader(can_interface, node_id, param_id)

def create_lsm6dsvtr(spi_device: str = "/dev/spi-1") -> ImuReader:
"""Create a LSM6DSVTR IMU reader on the specified SPI device."""
return create_lsm6dsvtr_reader(spi_device)


__all__ = [
# Data types
Expand Down
18 changes: 18 additions & 0 deletions imu/bindings/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Python bindings for the IMU package."""

# Import the compiled extension module from parent directory
import sys
import os
import importlib.util

# Get the path to the compiled binary
parent_dir = os.path.dirname(os.path.dirname(__file__))
binary_path = os.path.join(parent_dir, 'bindings.cpython-311-aarch64-linux-gnu.so')

# Load the compiled binary directly
spec = importlib.util.spec_from_file_location("bindings", binary_path)
bindings_binary = importlib.util.module_from_spec(spec)
spec.loader.exec_module(bindings_binary)

# Make all symbols available in this module's namespace
globals().update({name: getattr(bindings_binary, name) for name in dir(bindings_binary) if not name.startswith('_')})
22 changes: 22 additions & 0 deletions imu/bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,26 @@ fn create_hexmove_reader(can_interface: &str, node_id: u8, param_id: u8) -> PyRe
}
}

#[pyfunction]
fn create_lsm6dsvtr_reader(spi_device: &str) -> PyResult<PyImuReader> {
#[cfg(target_os = "linux")]
{
match imu::Lsm6dsvReader::new(spi_device) {
Ok(reader) => Ok(PyImuReader {
reader: Box::new(reader),
}),
Err(e) => Err(PyRuntimeError::new_err(e.to_string())),
}
}
#[cfg(not(target_os = "linux"))]
{
let _ = spi_device;
Err(PyRuntimeError::new_err(
"LSM6DSV reader is only available on Linux systems.",
))
}
}

#[pymodule]
fn bindings(m: &Bound<PyModule>) -> PyResult<()> {
m.add_class::<PyVector3>()?;
Expand All @@ -346,5 +366,7 @@ fn bindings(m: &Bound<PyModule>) -> PyResult<()> {

m.add_function(wrap_pyfunction!(create_hexmove_reader, m)?)?;

m.add_function(wrap_pyfunction!(create_lsm6dsvtr_reader, m)?)?;

Ok(())
}
18 changes: 18 additions & 0 deletions imu/drivers/lsm6dsv/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "linux_lsm6dsv"
readme = "README.md"
description = "SPI driver for LSM6DSV 6-axis IMU sensor"
version = "0.1.3"
authors.workspace = true
edition.workspace = true
repository.workspace = true
license.workspace = true

[lib]
name = "linux_lsm6dsv"
crate-type = ["rlib"]

[dependencies]
byteorder = "1.5"
log = "0.4"
imu-traits = "0.1"
21 changes: 21 additions & 0 deletions imu/drivers/lsm6dsv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# LSM6DSV Driver

SPI driver for the LSM6DSV 6-axis IMU sensor from STMicroelectronics.

## Features

- Accelerometer and gyroscope data reading
- SPI communication interface
- Configurable output data rates and full-scale ranges
- Temperature reading
- Background thread for continuous data acquisition

## Usage

```rust
use lsm6dsv::Lsm6dsvReader;

let reader = Lsm6dsvReader::new("/dev/spidev1.0")?;
let data = reader.get_data()?;
```

Loading
Loading