Wire LSM6DS3 readings into the runtime telemetry stream, expose them over web endpoints, and render live voltage/IMU data in the dashboard with websocket updates. Made-with: Cursor
65 lines
1.7 KiB
Python
65 lines
1.7 KiB
Python
"""LSM6DS3 accelerometer / gyroscope over I2C (MicroPython)."""
|
|
|
|
import struct
|
|
|
|
WHO_AM_I_REG = 0x0F
|
|
WHO_AM_I_LSM6DS3 = 0x69
|
|
|
|
CTRL1_XL = 0x10
|
|
CTRL2_G = 0x11
|
|
OUT_TEMP_L = 0x20
|
|
|
|
# Default CTRL1_XL = 0x60: 104 Hz ODR, ±2 g, anti-aliasing filter BW ~100 Hz
|
|
# Default CTRL2_G = 0x40: 104 Hz ODR, 245 dps full scale
|
|
_DEFAULT_XL = b"\x60"
|
|
_DEFAULT_G = b"\x40"
|
|
|
|
# LSB scaling for default full-scale settings above
|
|
_G_PER_LSB = 0.000061
|
|
_DPS_PER_LSB = 0.00875
|
|
|
|
|
|
def is_lsm6ds3(who_am_i: int) -> bool:
|
|
return who_am_i == WHO_AM_I_LSM6DS3
|
|
|
|
|
|
class LSM6DS3:
|
|
def __init__(self, i2c, addr=0x6A):
|
|
self.i2c = i2c
|
|
self.addr = addr
|
|
|
|
def who_am_i(self) -> int:
|
|
return self.i2c.readfrom_mem(self.addr, WHO_AM_I_REG, 1)[0]
|
|
|
|
def configure(self, ctrl1_xl=_DEFAULT_XL, ctrl2_g=_DEFAULT_G) -> None:
|
|
self.i2c.writeto_mem(self.addr, CTRL1_XL, ctrl1_xl)
|
|
self.i2c.writeto_mem(self.addr, CTRL2_G, ctrl2_g)
|
|
|
|
def read_raw(self):
|
|
"""Returns (temp_raw, gx, gy, gz, ax, ay, az) as signed 16-bit values."""
|
|
data = self.i2c.readfrom_mem(self.addr, OUT_TEMP_L, 14)
|
|
return struct.unpack("<hhhhhhh", data)
|
|
|
|
def read(self):
|
|
"""
|
|
Scaled readings for default ±2 g / 245 dps configuration.
|
|
|
|
Returns:
|
|
temp_c: float, degrees C
|
|
accel_g: (ax, ay, az) in g
|
|
gyro_dps: (gx, gy, gz) in degrees per second
|
|
"""
|
|
temp, gx, gy, gz, ax, ay, az = self.read_raw()
|
|
temp_c = 25.0 + temp / 16.0
|
|
accel_g = (
|
|
ax * _G_PER_LSB,
|
|
ay * _G_PER_LSB,
|
|
az * _G_PER_LSB,
|
|
)
|
|
gyro_dps = (
|
|
gx * _DPS_PER_LSB,
|
|
gy * _DPS_PER_LSB,
|
|
gz * _DPS_PER_LSB,
|
|
)
|
|
return temp_c, accel_g, gyro_dps
|